Wiki
機械臂物理仿真
本文由簡體中文內容確定性轉換,並受版本化術語表保護。
本節使用 Gazebo Fortress 與 gz_ros2_control 0.7.21。前面的接口與控制器繼續使用,反饋改由物理仿真提供。
1.環境與版本約定
先完成環境準備與源碼地圖的 Humble 安裝與 ROS 2 軟件源配置。下面安裝 Fortress 仿真器及 ROS 集成包;已經安裝對應組件時,可以直接檢查版本與包路徑。
1.1.安裝 Fortress 仿真器
按 Fortress 官方 Ubuntu 安裝説明 配置 OSRF 軟件源。以下命令用於 Ubuntu 22.04(jammy);若系統已配置同一軟件源,無需重複添加。
sudo apt-get update
sudo apt-get install -y curl ca-certificates gnupg lsb-release
curl -fsSL https://packages.osrfoundation.org/gazebo.gpg -o /tmp/gazebo-key.gpg
sudo install -m 644 /tmp/gazebo-key.gpg /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
printf 'deb [arch=%s signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] https://packages.osrfoundation.org/gazebo/ubuntu-stable jammy main\n' \
"$(dpkg --print-architecture)" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
sudo apt-get update
sudo apt-get install -y ignition-fortress
1.2.安裝 ROS 集成包並檢查
sudo apt-get install -y ros-humble-ros-gz ros-humble-gz-ros2-control
source /opt/ros/humble/setup.bash
ign gazebo --versions
ros2 pkg prefix ros_gz_sim
ros2 pkg prefix ros_gz_bridge
ros2 pkg prefix gz_ros2_control
ign gazebo --versions 應能找到 Fortress 對應的 Gazebo Sim 6,三個 ROS 包都應返回有效安裝路徑。插件安裝方式參考 Humble gz_ros2_control 文檔。
本章不使用 Gazebo Classic 的 libgazebo_ros2_control.so。Fortress 環境中啓動命令仍可能是 ign gazebo;ROS 包名採用 ros_gz_sim、gz_ros2_control,按實際安裝接口運行。
在 package.xml 中補充以下運行依賴,放在 export 之前:
<exec_depend>gz_ros2_control</exec_depend>
<exec_depend>ros_gz_sim</exec_depend>
<exec_depend>ros_gz_bridge</exec_depend>
2.示例 1:編寫完整仿真模型
在自己的包中創建 urdf/mini_gz.urdf.xacro:
<?xml version="1.0"?>
<robot name="mini" xmlns:xacro="http://www.ros.org/wiki/xacro">
<link name="world"/>
<link name="base_link">
<inertial><mass value="1"/><inertia ixx="0.005" ixy="0" ixz="0" iyy="0.005" iyz="0" izz="0.007"/></inertial>
<visual><geometry><box size="0.2 0.2 0.1"/></geometry></visual>
</link>
<joint name="world_fixed" type="fixed"><parent link="world"/><child link="base_link"/></joint>
<link name="link1">
<inertial><origin xyz="0 0 0.2"/><mass value="1"/>
<inertia ixx="0.0135" ixy="0" ixz="0" iyy="0.0135" iyz="0" izz="0.00042"/>
</inertial>
<visual><origin xyz="0 0 0.2"/><geometry><box size="0.05 0.05 0.4"/></geometry></visual>
<collision><origin xyz="0 0 0.2"/><geometry><box size="0.05 0.05 0.4"/></geometry></collision>
</link>
<joint name="joint1" type="revolute">
<parent link="base_link"/><child link="link1"/>
<origin xyz="0 0 0.05"/><axis xyz="0 1 0"/>
<limit lower="-1" upper="1" effort="20" velocity="2"/>
</joint>
<link name="link2">
<inertial><origin xyz="0 0 0.2"/><mass value="1"/>
<inertia ixx="0.0135" ixy="0" ixz="0" iyy="0.0135" iyz="0" izz="0.00042"/>
</inertial>
<visual><origin xyz="0 0 0.2"/><geometry><box size="0.05 0.05 0.4"/></geometry></visual>
<collision><origin xyz="0 0 0.2"/><geometry><box size="0.05 0.05 0.4"/></geometry></collision>
</link>
<joint name="joint2" type="revolute">
<parent link="link1"/><child link="link2"/>
<origin xyz="0 0 0.4"/><axis xyz="0 1 0"/>
<limit lower="-1" upper="1" effort="20" velocity="2"/>
</joint>
<ros2_control name="MiniSystem" type="system">
<hardware><plugin>gz_ros2_control/GazeboSimSystem</plugin></hardware>
<joint name="joint1">
<command_interface name="position"/>
<state_interface name="position"><param name="initial_value">0.0</param></state_interface>
<state_interface name="velocity"/>
</joint>
<joint name="joint2">
<command_interface name="position"/>
<state_interface name="position"><param name="initial_value">0.0</param></state_interface>
<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/controllers.yaml</parameters>
</plugin>
</gazebo>
</robot>
2.1.兩種插件分別負責什麼
硬件標籤中的 gz_ros2_control/GazeboSimSystem 連接關節狀態與命令接口;gazebo 標籤中的系統插件負責把控制框架接入仿真過程,並按 parameters 路徑讀取 YAML。
仿真插件會在仿真進程中創建管理器,因此本章不另外啓動 mini.launch.py 中的獨立 ros2_control_node。同一機械人啓動兩個管理器會造成資源與名稱衝突。
2.2.模型為什麼需要慣量
物理引擎需要質量與慣量;只有 visual 的 link 可能在模型轉換時被丟棄。例如,base_link 缺少有效慣量時,模型轉換可能導致其子關節找不到父座標系。應補齊有效的質量與慣量,並重新檢查模型轉換日誌。即使 RViz 能顯示模型,也不能保證它已經是有效的物理模型。
3.示例 2:編寫仿真啓動文件
保存為 launch/sim.launch.py:
from pathlib import Path
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import Command, LaunchConfiguration, PythonExpression
from launch_ros.actions import Node
from launch_ros.parameter_descriptions import ParameterValue
def generate_launch_description():
share = Path(get_package_share_directory('learn_control_hardware'))
gui = LaunchConfiguration('gui')
model = LaunchConfiguration('model')
controller = LaunchConfiguration('controller')
description = ParameterValue(Command(['xacro ', model]), value_type=str)
args = PythonExpression(["'-r -v 2 empty.sdf' if '", gui,
"' == 'true' else '-s -r -v 2 empty.sdf'"])
return LaunchDescription([
DeclareLaunchArgument('gui', default_value='false'),
DeclareLaunchArgument('model', default_value=str(share / 'urdf' / 'mini_gz.urdf.xacro')),
DeclareLaunchArgument('controller', default_value='forward_position_controller'),
IncludeLaunchDescription(PythonLaunchDescriptionSource(
str(Path(get_package_share_directory('ros_gz_sim')) / 'launch' / 'gz_sim.launch.py')),
launch_arguments={'gz_args': args}.items()),
Node(package='ros_gz_bridge', executable='parameter_bridge',
arguments=['/clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock'], output='screen'),
Node(package='robot_state_publisher', executable='robot_state_publisher',
parameters=[{'robot_description': description, 'use_sim_time': True}]),
Node(package='ros_gz_sim', executable='create',
arguments=['-topic', '/robot_description', '-name', 'learning_robot', '-z', '0.02']),
Node(package='controller_manager', executable='spawner',
arguments=['joint_state_broadcaster', '-c', '/controller_manager',
'--controller-manager-timeout', '60']),
Node(package='controller_manager', executable='spawner',
arguments=[controller, '-c', '/controller_manager',
'--controller-manager-timeout', '60']),
])
3.1.完整啓動過程
启动 Fortress world
→ robot_state_publisher 发布展开的机器人描述
→ ros_gz_sim/create 请求生成机器人
→ 模型中的系统插件加载控制管理器
→ spawner 等待服务并激活控制器
→ /clock 桥接到 ROS,使用仿真时间
create 返回請求成功,還應繼續檢查模型是否真正生成、插件是否加載、控制器是否 active。不能只憑一個 OK 判斷整條鏈路成功。
4.編譯運行
停止前面的獨立 mini 實例:
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
上面的 gui:=false 只運行仿真服務,適合先檢查後台鏈路。在 Ubuntu 圖形桌面中需要 Gazebo 窗口時,將啓動參數改為 gui:=true。兩種方式使用相同的模型和控制器;啓動前先停止上一套實例。
另一個終端:
source /opt/ros/humble/setup.bash
source ~/ros2_control_humble_ws/install/setup.bash
ros2 control list_controllers
ros2 topic echo /clock --once
ros2 topic pub --once /forward_position_controller/commands \
std_msgs/msg/Float64MultiArray "{data: [0.3, -0.2]}"
ros2 topic echo /joint_states
4.1.運行結果與檢查方法
兩個關節的反饋應逐漸接近 0.3、-0.2 rad。檢查控制器是否 active、/clock 是否前進,以及 /joint_states 中的名稱和數值是否對應。使用 GUI 時,還應觀察模型關節是否按目標運動。
position 接口在仿真後端中具有自己的執行方式。即使模型位於物理引擎中,也不能把默認位置執行器響應直接當成真實電機的性能。
5.對應底層源碼
閲讀 gz_ros2_control/gz_ros2_control/src/gz_ros2_control_plugin.cpp、gz_ros2_control/gz_ros2_control/src/gz_system.cpp,尋找仿真更新回調、管理器調用和關節數據訪問。再與獨立 ros2_control_node 對照。
返回 Humble 總覽 · 上一篇:Joint-Trajectory-Controller · 下一篇:DiffBot與差速底盤控制