Wiki
差速底盘物理仿真
Existing English translations were reused. 25 current source blocks remain in Simplified Chinese, without triggering paid translation.
本节自己创建一个物理底盘模型,显式使用反馈计算里程计。沿用机械臂物理仿真的 Fortress 启动文件。
1.示例 1:编写完整底盘模型
保存为 urdf/diff_gz.urdf.xacro:
<?xml version="1.0"?>
<robot name="learning_diffbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<link name="base_link">
<inertial><mass value="2"/><inertia ixx="0.02" ixy="0" ixz="0" iyy="0.03" iyz="0" izz="0.04"/></inertial>
<visual><geometry><box size="0.3 0.2 0.08"/></geometry></visual>
<collision><geometry><box size="0.3 0.2 0.08"/></geometry></collision>
</link>
<link name="left_wheel">
<inertial><mass value="0.2"/><inertia ixx="0.00014" ixy="0" ixz="0" iyy="0.00025" iyz="0" izz="0.00014"/></inertial>
<visual><origin rpy="1.57079632679 0 0"/><geometry><cylinder radius="0.05" length="0.03"/></geometry></visual>
<collision><origin rpy="1.57079632679 0 0"/><geometry><cylinder radius="0.05" length="0.03"/></geometry></collision>
</link>
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/><child link="left_wheel"/>
<origin xyz="0 0.15 0"/><axis xyz="0 1 0"/>
<limit effort="5" velocity="20"/>
</joint>
<link name="right_wheel">
<inertial><mass value="0.2"/><inertia ixx="0.00014" ixy="0" ixz="0" iyy="0.00025" iyz="0" izz="0.00014"/></inertial>
<visual><origin rpy="1.57079632679 0 0"/><geometry><cylinder radius="0.05" length="0.03"/></geometry></visual>
<collision><origin rpy="1.57079632679 0 0"/><geometry><cylinder radius="0.05" length="0.03"/></geometry></collision>
</link>
<joint name="right_wheel_joint" type="continuous">
<parent link="base_link"/><child link="right_wheel"/>
<origin xyz="0 -0.15 0"/><axis xyz="0 1 0"/>
<limit effort="5" velocity="20"/>
</joint>
<link name="front_caster">
<inertial><mass value="0.02"/><inertia ixx="0.0000032" ixy="0" ixz="0" iyy="0.0000032" iyz="0" izz="0.0000032"/></inertial>
<visual><geometry><sphere radius="0.02"/></geometry></visual>
<collision><geometry><sphere radius="0.02"/></geometry></collision>
</link>
<joint name="front_caster_fixed" type="fixed"><parent link="base_link"/><child link="front_caster"/><origin xyz="0.12 0 -0.03"/></joint>
<gazebo reference="front_caster"><mu1>0.0</mu1><mu2>0.0</mu2></gazebo>
<link name="rear_caster">
<inertial><mass value="0.02"/><inertia ixx="0.0000032" ixy="0" ixz="0" iyy="0.0000032" iyz="0" izz="0.0000032"/></inertial>
<visual><geometry><sphere radius="0.02"/></geometry></visual>
<collision><geometry><sphere radius="0.02"/></geometry></collision>
</link>
<joint name="rear_caster_fixed" type="fixed"><parent link="base_link"/><child link="rear_caster"/><origin xyz="-0.12 0 -0.03"/></joint>
<gazebo reference="rear_caster"><mu1>0.0</mu1><mu2>0.0</mu2></gazebo>
<ros2_control name="DiffSystem" type="system">
<hardware><plugin>gz_ros2_control/GazeboSimSystem</plugin></hardware>
<joint name="left_wheel_joint"><command_interface name="velocity"/>
<state_interface name="position"/><state_interface name="velocity"/>
</joint>
<joint name="right_wheel_joint"><command_interface name="velocity"/>
<state_interface name="position"/><state_interface name="velocity"/>
</joint>
</ros2_control>
<gazebo>
<plugin filename="gz_ros2_control-system" name="gz_ros2_control::GazeboSimROS2ControlPlugin">
<parameters>$(find learn_control_hardware)/config/diff_controllers.yaml</parameters>
</plugin>
</gazebo>
</robot>
1.1.几何与方向说明
车体 x 轴朝前,左轮在 y=+0.15 m,右轮在 y=-0.15 m,轮半径为 0.05 m。两轮关节轴都沿 +y,因此同号正角速度对应同一前进方向。前后小球提供支撑,并设低摩擦以便转弯。
本模型用于控制与接触入门,参数并非对某台实物的辨识结果。固定关节合并、碰撞和摩擦都会影响仿真,调试时要同时观察车体与轮子。
2.示例 2:编写底盘控制器参数
保存为 config/diff_controllers.yaml:
controller_manager:
ros__parameters:
update_rate: 100
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
diff_controller:
type: diff_drive_controller/DiffDriveController
diff_controller:
ros__parameters:
left_wheel_names: [left_wheel_joint]
right_wheel_names: [right_wheel_joint]
wheel_separation: 0.30
wheel_radius: 0.05
position_feedback: true
open_loop: false
use_stamped_vel: false
cmd_vel_timeout: 0.5
publish_rate: 50.0
odom_frame_id: odom
base_frame_id: base_link
enable_odom_tf: true
linear.x.has_velocity_limits: true
linear.x.max_velocity: 0.2
angular.z.has_velocity_limits: true
angular.z.max_velocity: 0.5
在 package.xml 中补充:
<exec_depend>diff_drive_controller</exec_depend>
2.1.和上一章不同的地方
本例 use_stamped_vel: false,输入 Topic 为 /diff_controller/cmd_vel_unstamped,消息类型 Twist;open_loop: false,里程计来自轮子反馈。不能沿用上一章的 /cmd_vel 和 TwistStamped。
3.编译运行
停止其它机器人后执行:
cd ~/ros2_control_humble_ws
colcon build --symlink-install --packages-select learn_control_hardware
source install/setup.bash
ros2 launch learn_control_hardware sim.launch.py gui:=false \
model:=$(ros2 pkg prefix learn_control_hardware)/share/learn_control_hardware/urdf/diff_gz.urdf.xacro \
controller:=diff_controller
Terminal 2:
source /opt/ros/humble/setup.bash
source ~/ros2_control_humble_ws/install/setup.bash
ros2 topic pub --rate 10 /diff_controller/cmd_vel_unstamped \
geometry_msgs/msg/Twist "{linear: {x: 0.08}, angular: {z: 0.0}}"
另一个终端观察:
ros2 topic echo /diff_controller/odom
ros2 topic echo /joint_states
ign topic -l
3.1.运行结果与检查方法
发送直行目标后,两轮位置应沿同一方向增加,反馈里程计 x 应持续变化。使用 GUI 时观察车体是否前进;无界面运行时,可以检查世界中的模型位姿:
ign topic -e -n 1 -t /world/empty/pose/info
在输出中按模型名称找到 learning_robot,比较不同时刻的 position。分别记录里程计和模型世界位姿,确认车体确实移动,而不只是轮子反馈发生变化。具体位移随实际仿真时长和接触情况变化,不要求与某个示例小数完全一致。
轮子反馈计算的里程计仍不是世界真值:打滑时两轮可以转动而车体位移很小。需要对照 Gazebo 世界坐标中的模型姿态,例如通过 /world/empty/pose/info 查找 learning_robot,或者在 GUI 中观察模型位移。
4.示例 3:验证转弯与停止
先按 Ctrl+C 停止直行发布,再发送:
ros2 topic pub --rate 10 /diff_controller/cmd_vel_unstamped \
geometry_msgs/msg/Twist "{linear: {x: 0.0}, angular: {z: 0.3}}"
停止发布后,cmd_vel_timeout 应让轮速目标归零。显式停车命令是:
ros2 topic pub --once /diff_controller/cmd_vel_unstamped \
geometry_msgs/msg/Twist "{linear: {x: 0.0}, angular: {z: 0.0}}"
4.1.Points to note in this example
轮子不动时先查控制器与接口;轮子转而车不走时再查接触、摩擦、关节轴和模型是否离地。不要为了让里程计“看着动了”而改成 open_loop 掩盖物理问题。
对应源码:gz_ros2_control/gz_ros2_control/src/gz_system.cpp、ros2_controllers/diff_drive_controller/src/odometry.cpp。
返回 Humble 总览 · 上一篇:DiffBot与差速底盘控制 · 下一篇:多接口与硬件类型