ROS2与Gazebo11入门教程-包含插件(ContainPlugin)
说明:
- 介绍包含插件
简介
- 插件ContainPlugin是Gazebo中包含的一个仿真世界插件,当某物进入或退出一个块体(volume)时,该插件会发布一条消息。该插件可以用来触发一个动作。例如,在测试中当机器人进入一个禁区时,该插件可以用来引发一个错误。
插件ContainPlugin在仿真世界中的使用
- 该插件是一个仿真世界插件,因此必须用作
元素的子元素。其filename的属性值必须设置为libContainPlugin.so。
<world name="default">
<plugin name="MyContainPluginInstance" filename="libContainPlugin.so">
<!-- plugin parameters go here ... -->
Gazebo 9+中的话题
- 该插件使用两个ignition传输话题:contain和enable。Ignition传输话题使用ignition.msgs.Boolean类型的消息
插件参数
enabled参数
如果该参数值为true,则该插件将会立即输出数据,否则需要显式启用。如果未指定,则该参数的默认值为true。将一个true值发送到名为
/enable的话题以启用该插件,而发送false值来禁用该插件。 被禁用时,ContainPlugin插件不会发布任何消息。
示例:
<enabled> false </ enabled>
entity参数
该参数是仿真世界中某个链接、模型、嵌套模型或光源的作用域名称。
每次仿真更新时ContainPlugin插件都会检查该实体的原点是否在指定的几何体内。
示例:
<entity> robot :: hand_link </ entity>
namespace参数
该参数给出了ContainPlugin插件使用的下面两个话题的前缀:contain和enable。
示例:
/foo/bar 将会导致话题/foo/bar/ contain和/foo/bar/enable。
pose参数
该参数表示的是指定几何体的中心位置。如果未指定frame属性,则位姿使用的是仿真世界的坐标系。如果frame属性设置为某个作用域名称,则位姿坐标就是相对于该实体原点的。
示例:仿真世界坐标系中的位置
<pose> 1 2 3 0 0 0 </ pose>
- 示例:相对于实体的位置
<pose frame =“ tree :: limb”>0.2 0 0.4 1.570769 0 0 </pose>
geometry参数
- 该参数表示的是要检查是否包含
元素的几何体。ContainPlugin插件当前支持的唯一几何体是 。请参阅方盒几何体sdformat说明以获取更多相关信息。
示例
使用ContainPlugin插件触发动作
本示例会说明如何使用ContainPlugin插件来触发一个动作。当一个球在灯柱下滚动时,灯就会打开。
请下载这个示例仿真世界,插件源代码和CMake文件。以此教程为例,构建并运行该插件。在扩展GAZEBO_PLUGIN_PATH环境变量之前,请确保运行source
<install_path>/share/gazebo/setup.sh命令以对安装脚本进行source。如果是使用apt工具安装的Gazebo,则<install_path>就是/usr目录。
下面会配置一个ContainPlugin实例以监视球体何时进入灯柱下方的方盒。当球体滚进方盒中或从方盒中滚出时,ContainPlugin就会在contain话题上发布一条消息。
<plugin name='ContainPlugin' filename='libContainPlugin.so'>
<enabled>true</enabled>
<entity>unit_sphere::only_link</entity>
<namespace>contain_example</namespace>
<pose>0 -3 0.5 0 0 0</pose>
<geometry>
<box>
<size>4 4 1</size>
</box>
</geometry>
</plugin>
<!-- Launch example plugin -->
<plugin name='AutomaticLight' filename='libTurnOnLightPlugin.so'/>
</world>
</sdf>
- 这个自定义插件会从ContainPlugin插件接收消息,并打开或关闭电灯。
#include <ignition/msgs.hh>
#include <ignition/transport/Node.hh>
#include "gazebo/common/Plugin.hh"
#include "gazebo/msgs/msgs.hh"
#include "gazebo/physics/World.hh"
#include "gazebo/transport/Node.hh"
namespace gazebo
{
class TurnOnLightPlugin : public WorldPlugin
{
public: void Load(physics::WorldPtr _world, sdf::ElementPtr _sdf) override
{
gzmsg << "Loading Example plugin\n";
// Transport initialization
this->gzNode = transport::NodePtr(new transport::Node());
this->gzNode->Init();
// Subscribe to ContainPlugin output
std::string topic("contain_example/contain");
std::function<void(const ignition::msgs::Boolean &)> cb =
[=](const ignition::msgs::Boolean &_msg){
TurnOnLightPlugin::OnContainPluginMsg(_msg);
};
const bool containSub = this->node.Subscribe(topic, cb);
if (!containSub)
{
gzerr << "Failed to subscribe to [" << topic << "]\n";
}
// Make a publisher for the light topic
this->lightPub = this->gzNode->Advertise<msgs::Light>("~/light/modify");
}
public: void OnContainPluginMsg(const ignition::msgs::Boolean &_msg)
{
msgs::Light lightMsg;
lightMsg.set_name("post_light");
// Turn light on when the entity enters the box, and off when it leaves
if (_msg.data())
{
gzmsg << "Turning on light\n";
lightMsg.set_range(15.0);
}
else
{
gzmsg << "Turning off light\n";
lightMsg.set_range(0.0);
}
this->lightPub->Publish(lightMsg);
}
private: ignition::transport::Node node;
private: transport::NodePtr gzNode;
private: transport::PublisherPtr lightPub;
};
GZ_REGISTER_WORLD_PLUGIN(TurnOnLightPlugin);
} // namespace gazebo
- 在构建并运行该仿真世界后,就应该会看到球触发了灯的打开。 如果您错过了该仿真世界,请按CTRL + R组合键重启该仿真世界。
ContainPlugin插件跟踪移动块体(volume)
可以相对于另一个实体定义该插件的
标签。这样,块体就可以随着该实体一起移动,就好像通过固定关节将插件连接在该实体上一样。Gazebo中含有一个可以展示这一点的仿真世界。 以暂停模式用移动的几何体仿真世界启动Gazebo,命令为:
gazebo --pause --verbose worlds/contain_plugin_moving_demo.world
- 在另一个终端中回显contain话题的输出消息,命令为:
ign topic --echo /gazebo/default/drill/contain
- 一开始时该插件会报告一个false值,因为那时钻头还不在块体中。随着块体的下滑,当钻头进入块体时,该插件就会报告一个true值,而后当钻头不再在块体中时,又会报告一个false值。
参考:
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号