Gazebo中的传感器配置

本文介绍了在Gazebo中使用IMU、接触和Lidar传感器,以及如何通过gzlaunch一次性启动多个任务,如机器人运动和数据收集,以实现避障功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传感器

注意: 本教程是在Gazebo Garden中使创建好的机器人动起来教程的延续。
在本教程中,我们将学习如何向我们的机器人和世界中的其他模型添加传感器。我们将使用三种不同的传感器:IMU 传感器、接触传感器Lidar传感器。我们还将学习如何使用 gz launch 仅用一个文件启动多个任务。

IMU传感器

惯性测量单元(IMU)以四元数的形式输出机器人的方向,以及三个轴(X、Y、Z)的角速度和线加速度。我们使用 moving_robot.sdf 世界并对其进行修改。创建一个新文件 sensor_tutorial.sdf,并将 moving_robot.sdf 中的代码添加到其中。要定义 IMU 传感器,请在<world>标签下添加以下代码:

<plugin filename="gz-sim-imu-system"
        name="gz::sim::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>

传感器通常添加到我们模型的某个链接中;我们将其添加到chassis链接下。
让我们描述一下这些标签:

  • <always_on>如果为 true,则传感器将始终根据更新率进行更新。
  • <update_rate>生成传感器数据的频率。
  • <visualize>如果为 true,则传感器将在 GUI 中可视化。
  • <topic>发布数据的主题名称。

注意: 并非任意标签都支持所有传感器。

从IMU读取数据

要从 IMU 读取数据,请在一个终端中运行世界并按下播放按钮:

gz sim sensor_tutorial.sdf

在另一个终端中,运行:

gz 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'>
        <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>

这只是一个简单的模型,只有一个盒状链接。你可以查看“在Gazebo Garden中创建一个机器人”教程来学习如何构建模型。
现在运行世界,并确保墙壁像这样出现在模拟中:
在这里插入图片描述
让我们将接触传感器添加到墙上。与 IMU 传感器一样,我们首先应该通过添加以下代码来定义接触传感器:

<plugin filename="gz-sim-contact-system"
        name="gz::sim::systems::Contact">
</plugin>

现在我们可以将contact传感器添加到wall模型的box链接中:

<sensor name='sensor_contact' type='contact'>
    <contact>
        <collision>collision</collision>
    </contact>
</sensor>

<sensor>的定义很简单,我们只定义了传感器的名称和类型。在collision内部,我们定义了box链接的碰撞的名称,即collision
我们还需要在墙壁模型下添加 TouchPlugin,如下所示:

<plugin filename="gz-sim-touchplugin-system"
        name="gz::sim::systems::TouchPlugin">
    <target>vehicle_blue</target>
    <namespace>wall</namespace>
    <time>0.001</time>
    <enabled>true</enabled>
</plugin>

TouchPlugin 将在墙壁被碰触时发布(发送)一条消息。插件的标签如下:

  • <target>将与我们的墙壁接触,在我们的例子中是 vehicle_blue。
  • <namespace>采用我们的主题的命名空间,因此当我们的机器人撞到墙壁时,它将向 /wall/touched 话题发送一条消息。
    在一个终端中运行仿真世界:
gz sim sensor_tutorial.sdf

在另一个终端中,监听 /wall/touched 主题:

gz topic -e -t /wall/touched

使用键盘箭头键将机器人向前驱向墙壁。确保通过点击播放按钮开始仿真,并通过单击插件下拉列表(垂直省略号)启用 Key Publisher 插件。
当机器人撞到障碍物时,你应该在运行 gz topic -e -t /wall/touched 的终端上看到一条消息 data: true
现在我们可以使用 TriggeredPublisher 插件让我们的机器人在撞到墙壁时停止,如下所示:

<plugin filename="gz-sim-triggered-publisher-system"
        name="gz::sim::systems::TriggeredPublisher">
    <input type="gz.msgs.Boolean" topic="/wall/touched">
        <match>data: true</match>
    </input>
    <output type="gz.msgs.Twist" topic="/cmd_vel">
        linear: {x: 0.0}, angular: {z: 0.0}
    </output>
</plugin>

在Gazebo Garden中使创建好的机器人动起来中所述,我们可以根据接收到的输入发布输出。因此,当我们在 /wall/touched 主题上接收到 data: true 时,我们发布 linear: {x: 0.0}, angular: {z: 0.0} 以使我们的机器人停止。

Lidar传感器

我们不希望机器人碰到墙壁,因为这可能会造成一些损坏,所以我们可以使用激光雷达而不是接触传感器。Lidar是“light detection and ranging(光探测和测距)”的缩写。该传感器可以帮助我们检测机器人周围的障碍物。我们将使用它来测量机器人与墙壁之间的距离。
首先,我们创建一个Frame来固定Lidar。这应该添加到 vehicle_blue<model>标记内,因为lidar frame附加在机器人的底盘(chassis)上:

<frame name="lidar_frame" attached_to='chassis'>
    <pose>0.8 0 0.5 0 0 0</pose>
</frame>

然后在<world>标签下添加此插件,以便能够使用lidar传感器:

    <plugin
      filename="gz-sim-sensors-system"
      name="gz::sim::systems::Sensors">
      <render_engine>ogre2</render_engine>
    </plugin>

chassis链接下,我们可以添加lidar传感器,如下所示:

<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>
  • 首先,我们定义了传感器的名称和类型,然后定义了它相对于 lidar_frame<pose>
  • <topic>中,我们定义了 lidar 数据将发布的话题。
  • <update_rate>是 lidar 数据生成的频率,在我们的例子中是 10 Hz,即 0.1 秒。
  • <horizontal><vertical>标签下,我们定义了水平和垂直激光射线的属性。
  • <samples>是每个完整激光扫射周期生成的模拟 lidar 射线的数量。
  • <resolution>:该数字乘以 samples 来确定数据点的数量范围。
  • <min_angle><max_angle>是生成射线的角度范围。
  • <range>下,我们定义了每个模拟射线的范围属性
    • <min><max>定义了每条 lidar 射线的最小和最大距离。
    • <resolution>标签在此处定义了每条 lidar 射线的线性分辨率。
  • <always_on>:如果为 true,则传感器将根据<update_rate>始终更新。
  • <visualize>:如果为 true,则传感器将在 GUI 中可视化。
    现在运行世界并按左下角的播放按钮:
gz sim sensor_tutorial.sdf

查看 lidar 主题上的 lidar 消息,特别是范围数据:

gz topic -e -t /lidar

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节点

gz::transport::Node node;
std::string topic_pub = "/cmd_vel";
gz::msgs::Twist data;
auto pub = node.Advertise<gz::msgs::Twist>(topic_pub);

我们声明一个将发布到 cmd_vel 话题的节点,并定义了消息类型 Twist。然后宣传我们的节点。

void cb(const gz::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.
    gz::transport::waitForShutdown();

    return 0;
}

在 main 内部,我们订阅 lidar 话题,并等待节点关闭。

构建节点

下载 CMakeLists.txt,并在 lidar_node 所在的同一文件夹中创建 build/ 目录:

mkdir build
cd build

执行cmka命令并构建:

cmake ..
make lidar_node

运行代码

在终端1运行节点:

./build/lidar_node

在终端2执行:

gz sim sensor_tutorial.sdf

现在你可以看到机器人向前移动,当它接近墙壁时,它开始向左转动,直到它清除并再次向前移动(确保按下左下角的播放按钮以使机器人开始移动)。

启动Gazebo

与其从两个不同的终端运行两个不同的任务,我们可以制作一个启动文件,同时运行 sensor_worldlidar_node。打开你的文本编辑器并添加以下代码。

<?xml version='1.0'?>
<gz version='1.0'>
  <executable name='sensor-world'>
    <command>gz sim sensor_tutorial.sdf</command>
  </executable>

  <executable name='lidar_node'>
    <command>./build/lidar_node</command>
  </executable>

</gz>

启动文件是一个 XML 文件。我们只需在<executable>标签下定义将运行的命令。第一个命令是 gz sim sensor_tutorial.sdf,它启动仿真世界。第二个命令是 ./build/lidar_node,它运行 lidar_node。将文件保存为 sensor_launch.gzlaunch,然后通过以下命令运行它:

gz launch sensor_launch.gzlaunch

按播放按钮开始模拟。我们的机器人现在正在移动并避开墙壁。
要使仿真更加复杂,请在下一个教程中学习如何向仿真世界添加演员。

<think>嗯,用户现在的问题是关于Gazebo中的传感器模拟的配置和使用教程。在之前的对话历史中,用户提到站内引用,但我注意到那些引用并不是用户真正的需求,用户要求参考上一次问题和我的回答。不过用户现在明确表示想了解配置Gazebo中的传感器模拟。首先需要回忆之前的对话。用户之前可能问过相关的问题吗?根据当前信息,用户提供了两条引用:一条是关于Gazebo模拟相机、GPS和IMU传感器的,另一条是关于给仿真机械臂添加力传感器配置细节。在用户这次的query中,重点在于力传感器配置使用教程。接下来需要整理关于Gazebo传感器配置步骤。根据引用2中的内容,关键步骤包括导入Gazebo的力传感器插件,设置更新频率、话题名称和关节名称。用户提到的那个可能是bug的地方很重要,力传感器必须放在关节上,所以在模型文件中需要有一个专门用于传感器的关节(比如ft_sensor_joint)。可能还需要补充更多实际操作的细节。比如如何编写模型文件(SDF或URDF),如何定义传感器插件和关节的连接。此外,用户可能需要知道如何解析传感器数据,比如在ROS中订阅话题并处理消息类型(geometry_msgs/WrenchStamped)。用户的使用场景可能涉及机器人仿真,特别是在机械臂的应用中,力传感器常用于装配任务或力反馈控制。因此需要考虑说明应用场景,比如工业自动化中的精密操作。用户可能遇到的常见问题包括传感器数据不更新或关节配置错误。需要提醒用户检查关节名称是否正确,模型加载是否成功,以及Gazebo日志是否有错误信息。此外,更新频率的设置也会影响数据发布的频率,这一点需要强调。最后需要生成相关问题,可能涉及传感器数据的应用、高级配置,或故障排查方法。同时要注意回答的结构,分步骤说明配置过程,清晰易懂。确认所有内容符合系统级指令:使用中文,正确引用标记如[^1][^2],数学表达式用$...$(虽然这里可能不涉及),独立公式用$$...$$(同样可能用不到),并生成相关问题。结尾部分需要自然引出问题,帮助用户深入理解。</think> 以下是Gazebo传感器模拟的配置与使用指南,基于标准SDF模型实现流程(以UR5机械臂为例): --- ### 一、模型配置文件修改 在机械臂的URDF/SDF模型文件中添加力传感器插件: ```xml <gazebo reference="ft_sensor_joint"> <!-- 必须绑定到关节 --> <sensor type="force_torque" name="ft_sensor"> <update_rate>100</update_rate> <!-- 数据更新频率(Hz) --> <plugin name="ft_plugin" filename="libgazebo_ros_ft_sensor.so"> <topicName>ft_data</topicName> <!-- ROS话题名称 --> <frameName>ft_frame</frameName> <!-- 参考坐标系 --> </plugin> <force_torque> <frame>child</frame> <!-- 测量基于子链接坐标系 --> </force_torque> </sensor> </gazebo> ``` **关键参数说明:** - `jointName`:必须指定某个关节(Gazebo当前限制) - `update_rate`:直接影响控制回路实时性 - `frame`:child/parent决定测量坐标系方向 --- ### 二、ROS数据接收处理 1. **启动Gazebo仿真环境** ```bash roslaunch ur_gazebo ur5.launch ``` 2. **监听力传感器数据** ```python import rospy from geometry_msgs.msg import WrenchStamped def callback(data): # 解析六维力/力矩数据 (N, N·m) force_x = data.wrench.force.x torque_z = data.wrench.torque.z print(f"受力: X={force_x:.2f}N, 扭矩Z={torque_z:.2f}N·m") rospy.Subscriber("/ft_data", WrenchStamped, callback) ``` --- ### 三、典型应用场景示例 | 场景 | 实现方式 | 数据用途 | |---------------------|----------------------------|------------------------| | 装配作业仿真 | 末端接触力监控 | 过载保护控制[^1] | | 柔顺控制训练 | 实时力矩反馈 | 阻抗参数调整[^2] | | 抓取稳定性分析 | 多指力传感器协同 | 滑移检测 | --- ### 四、常见问题解决 1. **数据无更新** - 检查关节命名一致性(需与模型文件严格匹配) - 验证插件路径:`ls /usr/lib/x86_64-linux-gnu/gazebo-11/plugins/*ft*` 2. **数据坐标系错误** ```xml <!-- 添加坐标变换补偿 --> <origin xyz="0.01 0 0" rpy="0 1.57 0"/> ``` 3. **噪声过大** 在Gazebo环境配置中增加物理引擎精度: ```xml <physics type="ode"> <real_time_update_rate>1000</real_time_update_rate> <max_step_size>0.001</max_step_size> </physics> ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值