Ignition入门教程-添加传感器
Ignition入门教程-添加传感器
说明:
- 我们将学习如何将传感器添加到我们的机器人和我们世界中的其他模型中。
- 我们将使用三种不同的传感器:IMU 传感器、接触传感器和激光雷达传感器。
- 我们还将学习如何使用 ign_launch 仅使用一个文件启动多个任务。
- 你可以在这里找到本教程的最终世界
IMU 传感器
- 惯性测量单元 (IMU) 以四元数形式输出我们机器人的方向、三个轴(X、Y、Z)的 angular_velocity 和三个轴的 linear_acceleration。
- 让我们使用我们的moving_robot.sdf 世界并对其进行修改。
- 创建一个新文件 sensor_tutorial.sdf 并将moving_robot.sdf 中的代码添加到其中。
- 要定义 IMU 传感器,请在
标签下添加以下代码:
<plugin filename="libignition-gazebo-imu-system.so"
name="ignition::gazebo::systems::Imu">
</plugin>
- 此代码定义了要在我们的世界中使用的 IMU 传感器插件。
- 现在我们可以将 IMU 传感器添加到我们的机器人中,如下所示:
<sensor name="imu_sensor" type="imu">
<always_on>1</always_on>
<update_rate>1</update_rate>
<visualize>true</visualize>
<topic>imu</topic>
</sensor>
- 传感器通常添加到我们模型的某个关节; 我们在底盘Link下添加了它。
- 让我们描述一下标签:
<always_on> 如果为真,则传感器将始终根据更新率进行更新。
<update_rate> 生成传感器数据的频率。
<visualize> 如果为真,则传感器在 GUI 中可视化。
<topic> 发布数据的主题的名称。
- 注意:并非所有传感器都支持所有标签。
读取IMU数据
- 新终端,执行
ign gazebo sensor_tutorial.sdf
- 新终端,执行
ign topic -e -t /imu
- 最后一个命令监听通过 /imu 主题发送的消息。
- 如上所述,IMU 数据是方向、角速度和线性加速度。 它应该如下所示:
- 使用键盘向上键向前移动机器人。 您应该看到传感器值发生变化。
接触式传感器
- 让我们介绍一种不同类型的传感器,即接触式传感器。 您可以从名称中猜出该传感器在接触(接触)其他物体时会给出指示。
- 我们将建造一个障碍物(墙)并将接触传感器添加到其中。 如果机器人撞到障碍物,它会停下来,防止机器人损坏自己。
- 让我们首先构建障碍物,如下所示:
<model name='wall'>
<static>true</static>
<pose>5 0 0 0 0 0</pose><!--pose relative to the world-->
<link name='box'>
<pose/>
<visual name='visual'>
<geometry>
<box>
<size>0.5 10.0 2.0</size>
</box>
</geometry>
<!--let's add color to our link-->
<material>
<ambient>0.0 0.0 1.0 1</ambient>
<diffuse>0.0 0.0 1.0 1</diffuse>
<specular>0.0 0.0 1.0 1</specular>
</material>
</visual>
<collision name='collision'>
<geometry>
<box>
<size>0.5 10.0 2.0</size>
</box>
</geometry>
</collision>
</link>
</model>
- 它只是一个简单的模型,带有一个盒子形状的LINK。 您可以查看构建自己的机器人教程以了解如何构建模型。
- 现在运行世界并确保墙出现在模拟中,如下所示
- 让我们将接触传感器添加到墙上。
- 与 IMU 传感器一样,我们应该首先通过添加以下代码来定义接触传感器:
<plugin filename="libignition-gazebo-contact-system.so"
name="ignition::gazebo::systems::Contact">
</plugin>
- 现在我们可以将接触传感器添加到墙模型的LINK中:
<sensor name='sensor_contact' type='contact'>
<contact>
<collision>collision</collision>
</contact>
</sensor>
的定义很简单,我们只需定义传感器的name和type。 - 在碰撞内部,我们定义了盒子链接碰撞名称,即collision。
- 我们还需要在墙模型下添加TouchPlugin,如下:
<plugin filename="libignition-gazebo-touchplugin-system.so"
name="ignition::gazebo::systems::TouchPlugin">
<target>vehicle_blue</target>
<namespace>wall</namespace>
<time>0.001</time>
<enabled>true</enabled>
</plugin>
- TouchPlugin 将在墙壁被触摸时发布(发送)一条消息。 插件的标签如下:
<target> 将与我们的墙接触,在我们的例子中是 vehicle_blue。
<namespace> 获取我们主题的命名空间,因此当我们的机器人撞墙时,它会向 /wall/touched 主题发送一条消息。
测试 :
- 新终端,执行启动世界
ign gazebo sensor_tutorial.sdf
- 新终端,执行订阅话题
ign topic -e -t /wall/touched
使用键盘箭头键将机器人向前推向墙壁。
当您遇到时,您应该在运行 ign topic -e -t /wall/touched的终端上看到一条消息 data: true。
现在我们可以使用 TriggeredPublisher 插件让我们的机器人在撞墙时停止,如下所示:
<plugin filename="libignition-gazebo-triggered-publisher-system.so"
name="ignition::gazebo::systems::TriggeredPublisher">
<input type="ignition.msgs.Boolean" topic="/wall/touched">
<match>data: true</match>
</input>
<output type="ignition.msgs.Twist" topic="/cmd_vel">
linear: {x: 0.0}, angular: {z: 0.0}
</output>
</plugin>
- 如移动机器人教程中所述,我们可以根据接收到的输入发布输出。
- 因此,当我们在 /wall/touched 话题上收到 data: true 时,我们会发布 linear: {x: 0.0}, angular: {z: 0.0} 以使我们的机器人停止。
激光传感器
- 我们根本不希望我们的机器人接触墙壁,因为这可能会造成一些损坏,所以我们可以使用激光雷达代替接触传感器。
- 激光雷达是“光探测和测距”的首字母缩写。 这个传感器可以帮助我们检测机器人周围的障碍物。
- 我们将使用它来测量机器人与墙壁之间的距离。
- 首先让我们创建一个框架来固定我们的激光雷达:
<frame name="lidar_frame" attached_to='chassis'>
<pose>0.8 0 0.5 0 0 0</pose>
</frame>
- 然后在
标签下添加这个插件,以便能够使用激光雷达传感器:
<plugin
filename="libignition-gazebo-sensors-system.so"
name="ignition::gazebo::systems::Sensors">
<render_engine>ogre2</render_engine>
</plugin>
- 在底盘链接下,我们可以添加激光雷达传感器,如下所示:
<sensor name='gpu_lidar' type='gpu_lidar'>"
<pose relative_to='lidar_frame'>0 0 0 0 0 0</pose>
<topic>lidar</topic>
<update_rate>10</update_rate>
<ray>
<scan>
<horizontal>
<samples>640</samples>
<resolution>1</resolution>
<min_angle>-1.396263</min_angle>
<max_angle>1.396263</max_angle>
</horizontal>
<vertical>
<samples>1</samples>
<resolution>0.01</resolution>
<min_angle>0</min_angle>
<max_angle>0</max_angle>
</vertical>
</scan>
<range>
<min>0.08</min>
<max>10.0</max>
<resolution>0.01</resolution>
</range>
</ray>
<always_on>1</always_on>
<visualize>true</visualize>
</sensor>
首先我们定义了传感器的名称和类型,然后我们定义了它相对于激光雷达框架的
。 在
中,我们定义了将发布激光雷达数据的主题。 <update_rate> 是生成激光雷达数据的频率,在我们的例子中为 10 Hz,即 0.1 秒。
在 <horizontal> 和
标签下,我们定义了水平和垂直激光射线的属性。 是每个完整激光扫描周期生成的模拟激光雷达射线的数量。 <分辨率>:此数字乘以样本以确定数字范围数据点。
<min_angle> 和 <max_angle> 是生成光线的角度范围。
在
下,我们定义了每条模拟射线的范围属性 和 定义每个激光雷达的最小和最大距离。
标签定义了每条激光雷达的线性分辨率。 <always_on>:如果为 true,则传感器将始终根据 <update_rate> 进行更新。 <visualize>:如果为 true,则传感器在 GUI 中可视化。
测试:
- 新终端,启动世界
ign gazebo sensor_tutorial.sdf
- 新终端,订阅激光数据
ign topic -e -t /lidar
- 效果
message LaserScan
{
Header header = 1;
string frame = 2;
Pose world_pose = 3;
double angle_min = 4;
double angle_max = 5;
double angle_step = 6;
double range_min = 7;
double range_max = 8;
uint32 count = 9;
double vertical_angle_min = 10;
double vertical_angle_max = 11;
double vertical_angle_step = 12;
uint32 vertical_count = 13;
repeated double ranges = 14;
repeated double intensities = 15;
}
避开墙壁
- 现在我们的机器人上有激光雷达,我们可以使用范围数据并让我们的机器人避免撞墙。
- 为此,我们将编写一个简短的 C++ 程序来监听传感器数据并向机器人发送速度命令。
- 该程序称为节点。 我们将构建一个订阅 /lidar 主题并读取其数据的节点。
- 查看本教程以了解如何构建发布者和订阅者节点。
- 您可以从此处下载此演示的已完成节点。
- 新建文件lidar_node.cc,lidar_node节点代码
ignition::transport::Node node;
std::string topic_pub = "/cmd_vel";
ignition::msgs::Twist data;
auto pub = node.Advertise<ignition::msgs::Twist>(topic_pub);
- 我们声明了一个将发布到 cmd_vel 话题的节点并定义了消息类型 Twist。 然后发布我们的节点。
void cb(const ignition::msgs::LaserScan &_msg)
{
bool allMore = true;
for (int i = 0; i < _msg.ranges_size(); i++)
{
if (_msg.ranges(i) < 1.0)
{
allMore = false;
break;
}
}
if (allMore) //if all bigger than one
{
data.mutable_linear()->set_x(0.5);
data.mutable_angular()->set_z(0.0);
}
else
{
data.mutable_linear()->set_x(0.0);
data.mutable_angular()->set_z(0.5);
}
pub.Publish(data);
}
- 在回调函数中,我们检查所有光线的范围是否大于 1.0。
- 如果是这样,我们会向我们的底盘发布一条消息以继续前进。 否则我们让机器人旋转。
int main(int argc, char **argv)
{
std::string topic = "/lidar";
// Subscribe to a topic by registering a callback.
if (!node.Subscribe(topic, cb))
{
std::cerr << "Error subscribing to topic [" << topic << "]" << std::endl;
return -1;
}
// Zzzzzz.
ignition::transport::waitForShutdown();
return 0;
}
- 在 main 中,我们订阅了激光雷达话题,并等待节点关闭。
- 新建 CMakeLists.txt, 可这里下载
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
project(avoid_wall)
# Find the Ignition_Transport library
find_package(ignition-transport8 QUIET REQUIRED OPTIONAL_COMPONENTS log)
set(IGN_TRANSPORT_VER ${ignition-transport8_VERSION_MAJOR})
include_directories(${CMAKE_BINARY_DIR})
if (EXISTS "${CMAKE_SOURCE_DIR}/lidar_node.cc")
add_executable(lidar_node lidar_node.cc)
target_link_libraries(lidar_node ignition-transport${IGN_TRANSPORT_VER}::core)
endif()
- 在lidar_node.cc目录下
mkdir build
cd build
cmake ..
make lidar_node
测试:
- 新终端,执行激光节点
./build/lidar_node
- 新终端,启动世界
ign gazebo sensor_tutorial.sdf
- 现在您可以看到机器人向前移动,当它接近墙壁时,它开始向左转,直到空无一人并再次向前移动。
Ignition launch/启动文件
- 我们可以创建一个启动文件,而不是从两个不同的终端运行两个不同的任务,该文件将同时运行 sensor_world 和 lidar_node。
- 打开您的文本编辑器并添加以下代码。
<?xml version='1.0'?>
<ignition version='1.0'>
<executable name='sensor-world'>
<command>ign gazebo sensor_tutorial.sdf</command>
</executable>
<executable name='lidar_node'>
<command>./build/lidar_node</command>
</executable>
</ignition>
- 启动文件是一个 XML 文件。 我们只需定义在
标记下将运行哪些命令。 - 第一个命令是启动世界的 ign Gazebo sensor_tutorial.sdf。
- 第二个命令是运行激光雷达节点的./build/lidar_node。
- 将文件另存为 sensor_launch.ign,然后使用以下命令运行它:
ign launch sensor_launch.ign
- 我们的机器人现在正在移动并避开墙壁。
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号