1、什么是gazebo_plugin
gazebo的插件机制给用户提供了更多的自由度和发挥空间,你可以通过插件与gazebo中的模型进行交互。比如改变模型的质量、惯性张量,给模型施加力、提供速度等等。同时,gazebo的插件机制也具有ros发布订阅、请求响应等模式。
2、怎么使用gazebo插件
gazebo的插件机制相关的教程比较少,我的个人对他的使用流程是这样的。首先你会写一个.cc文件以及相应的.hh文件,然后将其编译成为一个.so的动态链接库,然后再在模型的xacro文件中的gazebo标签中将这个动态链接库与模型绑定。然后加载模型后,插件将会一起上传到gazebo中,你可以在gazebo/model/plugins下查看一个模型绑定的插件。下面具体说说:
首先,你将编写.cc文件和.hh文件,此处的语法与C++略有不同。大概是这个样子
#include <gazebo/gazebo.hh>
namespace gazebo
{
class MyModelPlugin : public ModelPlugin
{
public:
void Load(physics::ModelPtr _parent, sdf::ElementPtr /*_sdf*/)
{
this->model = _parent;
// 每个仿真步骤都会调用Update函数
this->updateConnection = event::Events::ConnectWorldUpdateBegin(
std::bind(&MyModelPlugin::Update, this));
}
void Update()
{
// 在每个仿真步骤中执行的操作
// 可以在这里更新模型状态、执行控制算法等
}
private:
physics::ModelPtr model;
event::ConnectionPtr updateConnection;
};
GZ_REGISTER_MODEL_PLUGIN(MyModelPlugin)
}
此处的load函数,只运行一次,我认为他可以得到你的xacro文件和你gazebo中正在运行的模型信息,从而进行初始化。而update函数是在每个仿真步中运行,需要注意的是,你必须在load函数中使用
this->updateConnection = event::Events::ConnectWorldUpdateBegin(
std::bind(&MyModelPlugin::Update, this));
函数才可以让update函数在每个仿真步中运行。
然后你的CmakeListText大概是这样
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
find_package(gazebo REQUIRED)
include_directories(${GAZEBO_INCLUDE_DIRS})
link_directories(${GAZEBO_LIBRARY_DIRS})
list(APPEND CMAKE_CXX_FLAGS "${GAZEBO_CXX_FLAGS}")
add_library(MyPlugin SHARED MyPlugin.cc)
target_link_libraries(MyPlugin ${GAZEBO_LIBRARIES})
这样插件就可以编译成一个.so的动态链接库。
你的xacro大概要这样写
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="my_robot">
<xacro:include filename="$(find my_package)/urdf/my_robot.urdf.xacro" />
<link name="base_link">
<!-- 添加其他链接属性 -->
</link>
<joint name="fixed" type="fixed">
<parent link="world" />
<child link="base_link" />
<!-- 添加其他关节属性 -->
</joint>
<gazebo>
<plugin name="my_plugin" filename="libMyPlugin.so">
<!-- 添加其他插件属性 -->
</plugin>
</gazebo>
</robot>
其中
<gazebo>
<plugin name="my_plugin" filename="libMyPlugin.so">
<!-- 添加其他插件属性 -->
</plugin>
</gazebo>
就是将插件与模型绑定。
3、使用过程中的一个问题
我的问题是这样的,我需要在插件中写一个tf2_ros的broadcaster来广播我的tf信息,我将定义写在.hh文件中,private:tf2_ros::TransformBroadcaster tfB;,然后我编译成功了,但当我上传模型的时候,gazebo会崩丢,然后产生一个
undefined symbol: _ZN7tf2_ros20TransformBroadcasterC1Ev
原因大概是在执行过程中链接tf2_ros库失败。奇怪的是,我完全相同的代码在另外一个设备中可以成功运行,两台设备的区别是失败的设备的gazebo版本是9,成功的设备的gazebo版本是11。
之后我将private:tf2_ros::TransformBroadcaster tfB;的定义写在.cc文件中,失败设备也可以成功运行了。
我使用的环境是ubuntu18.04+ros1+gazebo9.19