机器人仿真

常见仿真软件

目前市面上有许多机器人仿真软件,这些仿真软件其实是独立于ROS的,他们是通过一些物理引擎做的。通过一些插件,可以让这些仿真软件和ROS2结合。下面的笔记全是基于Gazebo的

所需参数

仿真时URDF文件必须定义一些子标签:

  • 碰撞(collison标签)
  • 内参:包括物体质量(mass标签)、旋转惯量(inertia标签)、摩擦力(gazebo扩展的一些标签)

Gazebo的使用

Gazebo本身是个与ROS无关的软件,必须通过一些插件,才能让它和ROS2结合

启动

直接启动Gazebo的话,不会启动对应的ROS2 node,这样的话就无法和ROS2联动了。所以启动Gazebo的时候必须指定ROS2插件

1
gazebo --verbose -s libgazebo_ros_init.so -s libgazebo_ros_factory.so 

此时会创建一个叫/gazebo的ROS节点,该节点创建了一些service,让我们可以与其交互(gazeo里面本身也有一些GUI操作工具,但是无法直接加载urdf文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ros2 service list
/delete_entity # 用于删除gazbeo中已经加载的模型
/gazebo/describe_parameters
/gazebo/get_parameter_types
/gazebo/get_parameters
/gazebo/list_parameters
/gazebo/set_parameters
/gazebo/set_parameters_atomically
/get_model_list # 用于获取模型列表
/pause_physics
/reset_simulation
/reset_world
/spawn_entity # 用于加载模型(urdf)到gazebo中
/unpause_physics

加载模型

ROS2中的gazebo_ros2功能包提供了一个节点(spawn_entity.py),这个节点会调用/spawn_entity服务,我们只需要在启动节点时设置一些参数,即可加载不同的模型进Gazebo

插件机制

Gazebo本体提供的功能并不多,为了在不修改其源码的情况下,对其工作做一些扩展(新增传感器、集成ROS、直接访问物理引擎…)它提供了一种插件机制。用户可以通过写插件(动态库),来实现对Gazebo进行二次开发,插件按功能可以分为以下几类:

插件类型 作用对象 典型应用
WorldPlugin 整个仿真世界 全局物理规则、环境动态变化(如天气)
ModelPlugin 单个模型 机器人运动控制、机械臂逆运动学
SensorPlugin 传感器 激光雷达噪声模拟、摄像头图像生成
SystemPlugin Gazebo系统本身 自定义命令行参数、日志记录
VisualPlugin 可视化元素 渲染特效(如粒子系统)
GUIPlugin 用户界面 添加自定义按钮或显示面板

通过ls /opt/ros/humble/lib/libgazebo_ros*可以看当前安装了什么插件

工作原理

插件加载流程

  1. 声明插件:在URDF/SDF文件中通过<plugin>标签指定插件库路径和参数:

    1
    2
    3
    4
    5
    <model name="robot">
    <plugin name="diff_drive" filename="libgazebo_ros_diff_drive.so">
    <wheel_separation>0.5</wheel_separation>
    </plugin>
    </model>
  2. 动态加载:Gazebo启动时通过dlopen()加载插件库,调用注册函数创建插件实例

  3. 初始化:插件重写基类的Load()方法,获取仿真对象(如模型指针)并绑定事件回调

事件响应机制

插件通过Gazebo的事件系统(如WorldUpdateBegin)实时响应仿真状态:

1
2
3
4
5
6
7
8
9
10
void MyPlugin::Load(gazebo::physics::ModelPtr _model, sdf::ElementPtr _sdf) {
this->model = _model;
this->updateConnection = gazebo::event::Events::ConnectWorldUpdateBegin(
std::bind(&MyPlugin::OnUpdate, this));
}

void MyPlugin::OnUpdate() {
// 每帧仿真步进时执行的控制逻辑
this->model->SetForce(...);
}

通信方式

  • 内部通信:插件直接访问Gazebo的API(如physics::World)修改仿真状态
  • 外部通信:通过ROS话题/服务(如libgazebo_ros_imu.so发布/imu/data)与外部系统交互

这些插件如果要和ROS交互,一般会作为一个node,与其他节点进行通信。在使用插件时,我们应该重点关注这些插件节点的输入和输出是什么

数据流

在同时使用ROS2、Gazebo、RVIZ的时候,数据流一般是这样的:

1
ros2->gazebo->rviz

首先通过ROS2节点往Gazebo的运动控制/传感器插件发数据,这些插件在计算完后,会将结果以topic的形式广播,再用RVIZ订阅这些topic就行了

URDF的扩展