跳到正文

Wiki

差速底盤物理模擬

約 4 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

本節自己建立一個物理底盤模型,顯式使用反饋計算里程計。沿用機械臂物理模擬的 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

終端 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.本示例需要注意的點

輪子不動時先查控制器與介面;輪子轉而車不走時再查接觸、摩擦、關節軸和模型是否離地。不要為了讓里程計“看著動了”而改成 open_loop 掩蓋物理問題。

對應原始碼:gz_ros2_control/gz_ros2_control/src/gz_system.cpp、ros2_controllers/diff_drive_controller/src/odometry.cpp。


返回 Humble 總覽 · 上一篇:DiffBot與差速底盤控制 · 下一篇:多介面與硬體型別