关于我自制了一个ROS小车的仿真模型,Gazebo车轮陷入地下
-
我自制了一个ROS小车的仿真模型,Gazebo车轮陷入地下
求大佬帮我看看
主要问题
在rviz中的显示为

在Gazebo中的显示为:

相关代码
URDF文件如下:
<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="ros_car"> <!-- 坐标系:x前、y左、z上。单位:米 --> <!-- 总质量约 1.6kg;这里把轮子质量估为 0.08kg/个,底盘质量自动补齐 --> <xacro:property name="total_mass" value="1.6"/> <xacro:property name="wheel_mass" value="0.044"/> <xacro:property name="base_mass" value="${total_mass - 4.0*wheel_mass}"/> <!-- 车体长方体:150*200*100mm。按常见约定我取:长度x=200mm,宽度y=150mm,高度z=100mm --> <!-- 如果你确实想 x=150,y=200,交换 base_length/base_width 即可 --> <xacro:property name="base_length" value="0.200"/> <xacro:property name="base_width" value="0.150"/> <xacro:property name="base_height" value="0.100"/> <!-- 麦轮:直径60mm,宽24.5mm --> <xacro:property name="wheel_radius" value="0.030"/> <xacro:property name="wheel_width" value="0.0245"/> <!-- 轮中心相对 base_link:|x|=60mm, |y|=87.5mm --> <xacro:property name="wheel_x" value="0.060"/> <xacro:property name="wheel_y" value="0.0875"/> <!-- 为了Gazebo不穿地:轮中心相对 base_link 的 z 取 -base_height/2 (= -50mm) --> <!-- 如果你只想严格按你描述(z=0),把下面改成 0 --> <xacro:property name="wheel_z_in_base" value="${-base_height/2.0}"/> <!-- 传感器安装(相对 base_link) --> <!-- A1:(-40mm, 0, 65mm);D435i:(80mm, 0, 62.5mm) --> <xacro:property name="lidar_x" value="-0.040"/> <xacro:property name="lidar_y" value="0.000"/> <xacro:property name="lidar_z" value="0.065"/> <xacro:property name="camera_x" value="0.080"/> <xacro:property name="camera_y" value="0.000"/> <xacro:property name="camera_z" value="0.0625"/> <!-- D435i 形状:100*25*25mm --> <xacro:property name="camera_box_x" value="0.100"/> <xacro:property name="camera_box_y" value="0.025"/> <xacro:property name="camera_box_z" value="0.025"/> <!-- A1 底座:100*100*30mm;雷达本体:圆柱直径70mm,高25mm --> <xacro:property name="lidar_base_xy" value="0.100"/> <xacro:property name="lidar_base_z" value="0.030"/> <xacro:property name="lidar_cyl_d" value="0.070"/> <xacro:property name="lidar_cyl_z" value="0.025"/> <!-- ================= 惯量宏(够用,后续可精修) ================= --> <xacro:macro name="inertial_box" params="m x y z"> <inertial> <origin xyz="0 0 0" rpy="0 0 0"/> <mass value="${m}"/> <inertia ixx="${(m/12.0) * (y*y + z*z)}" iyy="${(m/12.0) * (x*x + z*z)}" izz="${(m/12.0) * (x*x + y*y)}" ixy="0" ixz="0" iyz="0"/> </inertial> </xacro:macro> <xacro:macro name="inertial_cylinder_y" params="m r h"> <inertial> <origin xyz="0 0 0" rpy="0 0 0"/> <mass value="${m}"/> <inertia ixx="${(m/12.0) * (3*r*r + h*h)}" iyy="${(m/2.0) * (r*r)}" izz="${(m/12.0) * (3*r*r + h*h)}" ixy="0" ixz="0" iyz="0"/> </inertial> </xacro:macro> <!-- ================= TF 根:base_footprint 在地面投影点 ================= --> <link name="base_footprint"/> <!-- base_link 放在底盘几何中心;为了让轮子落在地面,base_link 高度=轮半径+底盘高度/2 --> <joint name="base_footprint_to_base_link" type="fixed"> <origin xyz="0 0 ${wheel_radius + base_height/2.0}" rpy="0 0 0"/> <parent link="base_footprint"/> <child link="base_link"/> </joint> <!-- ================= 底盘(简单长方体) ================= --> <link name="base_link"> <xacro:inertial_box m="${base_mass}" x="${base_length}" y="${base_width}" z="${base_height}"/> <visual> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <box size="${base_length} ${base_width} ${base_height}"/> </geometry> <material name="Gray"> <color rgba="0.6 0.6 0.6 1.0"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <box size="${base_length} ${base_width} ${base_height}"/> </geometry> </collision> </link> <!-- ================= 轮子(四个连续关节) ================= --> <xacro:macro name="wheel" params="prefix x y"> <link name="${prefix}_wheel_link"> <xacro:inertial_cylinder_y m="${wheel_mass}" r="${wheel_radius}" h="${wheel_width}"/> <!-- URDF cylinder 默认沿 z 轴;转 90° 让它沿 y 轴(轮子自转轴是 y) --> <visual> <origin xyz="0 0 0" rpy="1.57079632679 0 0"/> <geometry> <cylinder radius="${wheel_radius}" length="${wheel_width}"/> </geometry> <material name="Black"> <color rgba="0.1 0.1 0.1 1.0"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="1.57079632679 0 0"/> <geometry> <cylinder radius="${wheel_radius}" length="${wheel_width}"/> </geometry> </collision> </link> <!-- 轮子关节的坐标是“相对 base_link”,x/y 用你给的,z 用 wheel_z_in_base --> <joint name="${prefix}_wheel_joint" type="continuous"> <origin xyz="${x} ${y} ${wheel_z_in_base}" rpy="0 0 0"/> <parent link="base_link"/> <child link="${prefix}_wheel_link"/> <axis xyz="0 1 0"/> <dynamics damping="0.2" friction="0.2"/> </joint> </xacro:macro> <!-- LF 左前、RF 右前、LR 左后、RR 右后 --> <xacro:wheel prefix="lf" x="${ wheel_x}" y="${ wheel_y}"/> <xacro:wheel prefix="rf" x="${ wheel_x}" y="${-wheel_y}"/> <xacro:wheel prefix="lr" x="${-wheel_x}" y="${ wheel_y}"/> <xacro:wheel prefix="rr" x="${-wheel_x}" y="${-wheel_y}"/> <!-- ================= D435i(用长方体表示,放在 camera_link) ================= --> <link name="camera_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <box size="${camera_box_x} ${camera_box_y} ${camera_box_z}"/> </geometry> <material name="Blue"> <color rgba="0.2 0.3 0.9 1.0"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <box size="${camera_box_x} ${camera_box_y} ${camera_box_z}"/> </geometry> </collision> </link> <joint name="camera_joint" type="fixed"> <origin xyz="${camera_x} ${camera_y} ${camera_z}" rpy="0 0 1.57079632679"/> <parent link="base_link"/> <child link="camera_link"/> </joint> <!-- 可选:相机光学坐标系(ROS常用约定:z向前,x向右,y向下) --> <link name="camera_optical_frame"/> <joint name="camera_optical_joint" type="fixed"> <origin xyz="0 0 0" rpy="-1.57079632679 0 -1.57079632679"/> <parent link="camera_link"/> <child link="camera_optical_frame"/> </joint> <!-- ================= A1 雷达(雷达本体圆柱是 lidar_link;底座单独做成 child link) ================= --> <link name="lidar_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <cylinder radius="${lidar_cyl_d/2.0}" length="${lidar_cyl_z}"/> </geometry> <material name="White"> <color rgba="0.9 0.9 0.9 1.0"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <cylinder radius="${lidar_cyl_d/2.0}" length="${lidar_cyl_z}"/> </geometry> </collision> </link> <joint name="lidar_joint" type="fixed"> <origin xyz="0 0 ${lidar_cyl_z/2.0 + lidar_base_z/2.0}" rpy="0 0 0"/> <parent link="lidar_base_link"/> <child link="lidar_link"/> </joint> <!-- 底座放在雷达圆柱正下方:偏移 z = -(圆柱半高 + 底座半高) --> <joint name="lidar_base_joint" type="fixed"> <origin xyz="${lidar_x} ${lidar_y} ${lidar_z}" rpy="0 0 0"/> <parent link="base_link"/> <child link="lidar_base_link"/> </joint> <link name="lidar_base_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <box size="${lidar_base_xy} ${lidar_base_xy} ${lidar_base_z}"/> </geometry> <material name="DarkGray"> <color rgba="0.25 0.25 0.25 1.0"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <box size="${lidar_base_xy} ${lidar_base_xy} ${lidar_base_z}"/> </geometry> </collision> </link> <!-- IMU 坐标系(先给一个标准 link,后续你接真IMU/仿真IMU都方便) --> <link name="imu_link"/> <joint name="imu_joint" type="fixed"> <origin xyz="0 0 0" rpy="0 0 0"/> <parent link="base_link"/> <child link="imu_link"/> </joint> </robot>gazebo的launch文件如下:
from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import Command, LaunchConfiguration from launch_ros.actions import Node from ament_index_python.packages import get_package_share_directory import os def generate_launch_description(): use_sim_time = LaunchConfiguration("use_sim_time") world = LaunchConfiguration("world") gui = LaunchConfiguration("gui") verbose = LaunchConfiguration("verbose") # 你的 xacro desc_pkg = get_package_share_directory("ros_car_description") xacro_file = os.path.join(desc_pkg, "urdf", "ros_car.urdf.xacro") # Gazebo Classic 的官方 launch(来自 gazebo_ros) gazebo_ros_pkg = get_package_share_directory("gazebo_ros") gazebo_launch = os.path.join(gazebo_ros_pkg, "launch", "gazebo.launch.py") # 获取worlds文件夹路径 worlds_dir = os.path.join(desc_pkg, "worlds") default_world = os.path.join(worlds_dir, "custom_room.world") # robot_description robot_description = Command(["xacro", " ", xacro_file]) return LaunchDescription( [ DeclareLaunchArgument("use_sim_time", default_value="true"), # world 参数现在默认指向 worlds 文件夹中的 custom_room.world DeclareLaunchArgument("world", default_value=default_world), DeclareLaunchArgument("gui", default_value="true"), DeclareLaunchArgument("verbose", default_value="false"), # 启动 Gazebo Classic IncludeLaunchDescription( PythonLaunchDescriptionSource(gazebo_launch), launch_arguments={ "world": world, "gui": gui, "verbose": verbose, }.items(), ), # 发布 TF(RViz / TF 树用) Node( package="robot_state_publisher", executable="robot_state_publisher", parameters=[ { "use_sim_time": use_sim_time, "robot_description": robot_description, } ], output="screen", ), # 没有 ros2_control 的情况下,让关节至少有默认 0 值(轮子连续关节不至于缺 joint_states) Node( package="joint_state_publisher", executable="joint_state_publisher", parameters=[{"use_sim_time": use_sim_time}], output="screen", ), # 把模型从 robot_description 生成到 Gazebo 里 # -z 给个高度避免初始穿地(根据你模型尺寸 0.2 基本够) Node( package="gazebo_ros", executable="spawn_entity.py", arguments=[ "-entity", "ros_car", "-topic", "robot_description", "-x", "0", "-y", "0", "-z", "0.2", ], output="screen", ), ] )rviz2的launch文件如下:
from launch import LaunchDescription from launch.substitutions import Command from launch_ros.actions import Node from ament_index_python.packages import get_package_share_directory import os def generate_launch_description(): pkg = get_package_share_directory("ros_car_description") xacro_file = os.path.join(pkg, "urdf", "ros_car.urdf.xacro") robot_description = {"robot_description": Command(["xacro", " ", xacro_file])} rviz_config = os.path.join(pkg, "config", "display_robot.rviz") return LaunchDescription( [ Node( package="robot_state_publisher", executable="robot_state_publisher", parameters=[robot_description], output="screen", ), Node( package="joint_state_publisher", executable="joint_state_publisher", output="screen", ), Node( package="rviz2", executable="rviz2", arguments=["-d", rviz_config], output="screen", ), ] ) -
@1402485721 gazebo 的kp kd 太小