Webots:Webots与ROS1、ROS2接口变迁

Gazebo:Gazebo与ROS1、ROS2接口变迁



ROS1

2016:ROS_Kinetic_18 使用V-Rep3.3.1和Matlab2015b(vrep_ros_bridge)续

CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-_学习

 

vrep_ros_bridge 插件

一、项目背景与目标

vrep_ros_bridge 是由位于法国雷恩的 Inria Lagadic 团队为 V-Rep(现更名为 CoppeliaSim)开发的一款插件。该插件旨在创建一个模拟环境,以便在模拟机器人上测试和调试算法。团队选择 V-Rep 作为 3D 模拟器,并利用 ROS(Robot Operating System)进行通信和利用其丰富的工具集。

二、主要功能

vrep_ros_bridge 的核心功能是提供一个通信接口,使得 ROS 能够控制 V-Rep 中的模拟环境。通过 ROS 消息和服务,用户可以外部控制 V-Rep 的仿真,包括发送控制指令、接收仿真数据等。

三、V-Rep 简介

V-Rep(CoppeliaSim)是由 Coppelia Robotics 开发的一款开源且先进的 3D 物理仿真引擎。它因其灵活性(支持多种机器人平台的模拟)、强大的动力学引擎(支持 ODE、Bullet 和 Vortex)以及高度的可定制性(允许用户包含自己的代码或与外部世界接口)而在机器人社区中越来越受欢迎。

四、插件架构与工作原理
  • 插件架构vrep_ros_bridge 是一个共享库,由 V-Rep 的主客户端程序在启动时自动加载。插件会查找场景中的已知对象并进行管理。
  • 数据交互:插件创建 ROS 发布者来发送仿真数据(如场景中物体的位置和速度),并接收 ROS 订阅者的消息,动态地将控制命令应用到对象上。
  • 模块化设计vrep_ros_bridge 是一个元包,而 vrep_ros_plugin 是实际的主包。它使用 pluginlib 来加载和卸载插件,这使得插件具有高度的灵活性和可扩展性。
五、支持的对象与处理器
  • 支持的对象
  • 机器人:包括机械臂和移动机器人(通过 manipulator_handler 处理),以及四旋翼飞行器(通过 quadrotor_handler 处理)。
  • 传感器:包括视觉传感器(通过 camera_handler 处理)和 IMU 传感器(通过 imu_handler 处理)。
  • 处理器
  • 刚体处理器rigid_body_handler):提供设置和获取物体的位置和速度(Twist)的功能。
六、如何链接插件与 V-REP 中的对象

要在 V-REP 中使用 vrep_ros_bridge 插件,你需要将插件与场景中的对象进行链接。这通常涉及以下几个步骤:

  1. 确保插件已加载:在 V-REP 启动时,插件应自动加载。
  2. 配置对象:在 V-REP 场景中,为需要控制的每个对象(如机器人、传感器)配置相应的属性,以便插件能够识别和管理它们。
  3. 设置 ROS 节点:在 ROS 端,启动相应的节点以订阅或发布与 V-REP 交互所需的话题和服务。
  4. 运行仿真:在 V-REP 中运行仿真,并通过 ROS 发送控制命令或接收仿真数据。
七、总结

vrep_ros_bridge 插件为 V-Rep 和 ROS 之间的通信提供了一个强大的接口,使得在模拟环境中测试和控制机器人变得更加容易和高效。通过支持多种机器人和传感器,以及灵活的模块化设计,该插件为机器人研究和开发提供了强大的支持。

 


ROS2

2019:CoppeliaSim(V-Rep)和ROS2的使用说明

2024:CoppeliaSim_Edu_V4_7_0_rev4_Ubuntu24_04 和 ROS2 Jazzy

CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-_学习_02

 

CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-_持续学习_03

 


ROS2 Interface Plugin for CoppeliaSim 中文详细总结

支持的ROS2版本
  • Humble Hawksbill:这是ROS2的一个主要版本,确保你的ROS2环境与此版本兼容。
编译准备
  1. 目录命名
  • 确保包含所有文件(如package.xml等)的目录命名为sim_ros2_interface,否则编译将失败。
  1. 安装simStubsGen所需包
  • 需要根据simStubsGen的README文档安装必要的包。simStubsGen是一个用于生成CoppeliaSim(之前称为V-REP)模拟环境中ROS接口代码的工具。
  1. 克隆并切换版本
  • 使用Git克隆simROS2仓库到本地,并命名为sim_ros2_interface
  • 切换到与你的CoppeliaSim版本相对应的分支。例如,如果你使用的是CoppeliaSim v4.5.0,则应该切换到coppeliasim-v4.5.0-rev0分支。注意替换为实际使用的CoppeliaSim版本。

bash

$ git clone https://github.com/CoppeliaRobotics/simROS2.git sim_ros2_interface 
$ cd sim_ros2_interface 
$ git checkout coppeliasim-v4.5.0-rev0

编辑meta/interfaces.txt

  • 如果需要包含更多的ROS接口,请编辑此文件。确保使用完全限定的接口名称,如geometry_msgs/msg/Twist而不是Twist。如果接口使用了非基本类型(即其他接口),则也需要将这些接口添加到文件中。
编译过程
  • 使用colcon进行编译。colcon是ROS2推荐的构建系统。bash
$ colcon build --symlink-install
  • 调试编译错误
  • 如果遇到编译错误,可以使用以下命令来构建,这将提供更详细的输出信息:bash
VERBOSE=1 MAKEFLAGS=-j1 colcon build --symlink-install --event-handlers console_direct+ --parallel-workers 1
  • 如果遇到运行时错误(如崩溃、意外行为等),可以在构建时添加--cmake-args -DCMAKE_BUILD_TYPE=Debug来启用调试模式。
  • 使用Clang编译器
  • 如果GCC编译器在编译大量接口时失败,可以尝试使用Clang编译器。首先安装Clang,然后设置环境变量CXXclang++,再进行编译。bash
sudo apt install clang 
export CXX=clang++ 
colcon build ...
  • 注意事项
  • 确保ROS2环境已正确设置,并且colcon和所有必要的依赖都已安装。
  • 如果你的CoppeliaSim版本与simROS2仓库中的分支不完全匹配,可能需要手动调整代码或查找是否有更新的分支/仓库。
  • 编译过程中可能会遇到与特定ROS2版本或CoppeliaSim版本相关的兼容性问题。在这种情况下,请检查官方文档或社区论坛以获取帮助。

通过以上步骤,你应该能够成功编译并设置ROS2 Interface Plugin for CoppeliaSim,以便在模拟环境中使用ROS2接口。


ROS2 与 CoppeliaSim 集成教程

本教程旨在以简单易懂的方式解释如何使CoppeliaSim(之前称为V-REP)支持ROS 2。首先,请确保您已经完成了ROS 2的官方教程,至少包括入门部分。我们假设您已经安装了最新版本的Ubuntu,ROS 2也已安装,并且工作空间文件夹已设置。请参考ROS 2安装的官方文档。

ROS2 Interface 插件

CoppeliaSim中的ROS 2功能主要通过ROS2 Interface(libsimROS2.so)支持。这个Linux发行版可能已经包含了在CoppeliaSim/compiledROSPlugins目录下编译好的文件,但首先需要将其复制到CoppeliaSim/目录下,否则不会被加载。不过,根据您的系统特性,您可能会遇到插件加载问题:请确保始终检查CoppeliaSim的终端窗口以获取有关插件加载操作的详细信息。加载ROS2插件的Lua代码如下:



lua复制代码

simROS2 = require('simROS2')

在运行CoppeliaSim之前,请确保已经导入了ROS 2环境。

插件编译

如果插件无法加载,您可能需要自己重新编译它。因为它是开源的,所以可以根据需要进行修改以支持特定功能或扩展其功能。如果需要支持特定的消息/服务等,请在重新编译之前编辑simROS2/meta/下的文件。

存在两个包:

  1. simROS2:这个包是ROS 2接口,将被编译成".so"文件并由CoppeliaSim使用。
  2. ros2_bubble_rob:这是一个非常简单的机器人控制器包,它通过ROS 2接口与CoppeliaSim连接。此节点将负责控制demo场景controlTypeExamples/controlledViaRos.ttt中的红色机器人。

这两个包应该被复制到您的ros2_ws/src文件夹中。

构建包

为了构建这些包,请导航到ros2_ws文件夹并输入以下命令:



bash复制代码

$ export COPPELIASIM_ROOT_DIR=~/path/to/coppeliaSim/folder 
$ ulimit -s unlimited # 否则编译可能会冻结/崩溃 
$ colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release

完成以上步骤后,包应该已经被生成并编译成库文件,该库文件将自动复制到CoppeliaSim的安装文件夹中。现在,插件已准备好使用。

加载和使用ROS2 Interface

打开一个新的终端,移动到CoppeliaSim的安装文件夹,启动CoppeliaSim,并使用上述Lua代码加载ROS2插件。成功加载ROS 2接口后,可以通过以下命令检查可用的节点:



bash复制代码

$ ros2 node list 
/sim_ros2_interface

在CoppeliaSim的一个空场景中,选择一个对象,然后为其附加一个非线程仿真脚本(通过[添加 > 脚本 > 仿真脚本 > 非线程 > Lua/Python])。打开该脚本的编辑器,并用以下代码替换其内容(根据您的需求编写具体的Lua代码来控制仿真):



lua复制代码

-- 在这里编写控制CoppeliaSim中对象的Lua代码

这样,您就可以开始通过ROS 2与CoppeliaSim进行交互了。

#python

def subscriber_callback(msg):
    # This is the subscriber callback function
    log_message = f'subscriber receiver following Float32: {msg["data"]}'
    sim.addLog(sim.verbosity_scriptinfos, log_message)

def getTransformStamped(objHandle, name, relTo, relToName):
    # This function retrieves the stamped transform for a specific object
    t = simROS2.getSystemTime()
    p = sim.getObjectPosition(objHandle, relTo)
    o = sim.getObjectQuaternion(objHandle, relTo)
    return {
        'header': {
            'stamp': t,
            'frame_id': relToName
        },
        'child_frame_id': name,
        'transform': {
            'translation': {'x': p[0], 'y': p[1], 'z': p[2]},
            'rotation': {'x': o[0], 'y': o[1], 'z': o[2], 'w': o[3]}
        }
    }

def sysCall_init():
    sim = require('sim')
    simROS2 = require('simROS2')

    # The simulation script initialization
    self.objectHandle = sim.getObject('..')
    self.objectAlias = sim.getObjectAlias(self.objectHandle, 3)
    
    # Prepare the float32 publisher and subscriber (we subscribe to the topic we publish):
    self.publisher = simROS2.createPublisher('/simulationTime', 'std_msgs/msg/Float32')
    self.subscriber = simROS2.createSubscription('/simulationTime', 'std_msgs/msg/Float32', subscriber_callback)

def sysCall_actuation():
    # Send an updated simulation time message, and send the transform of the object attached to this script:
    simROS2.publish(self.publisher, {'data': sim.getSimulationTime()})
    simROS2.sendTransform(getTransformStamped(self.objectHandle, self.objectAlias, -1, 'world'))
    # To send several transforms at once, use simROS2.sendTransforms instead

def sysCall_cleanup():
    # Following not really needed in a simulation script (i.e. automatically shut down at simulation end):
    simROS2.shutdownPublisher(self.publisher)
    simROS2.shutdownSubscription(self.subscriber)
--lua

function subscriber_callback(msg)
    -- This is the subscriber callback function
    sim.addLog(sim.verbosity_scriptinfos, 'subscriber receiver following Float32: '..msg.data)
end

function getTransformStamped(objHandle, name, relTo, relToName)
    -- This function retrieves the stamped transform for a specific object
    local t = simROS2.getSystemTime()
    local p = sim.getObjectPosition(objHandle,relTo)
    local o = sim.getObjectQuaternion(objHandle,relTo)
    return {
        header = {
            stamp = t,
            frame_id = relToName
        },
        child_frame_id = name,
        transform = {
            translation = {x = p[1], y = p[2], z = p[3]},
            rotation = {x = o[1], y = o[2], z = o[3], w = o[4]}
        }
    }
end

function sysCall_init()
    sim = require('sim')
    simROS2 = require('simROS2')

    -- The simulation script initialization
    objectHandle = sim.getObject('..')
    objectAlias = sim.getObjectAlias(objectHandle, 3)

    -- Prepare the float32 publisher and subscriber (we subscribe to the topic we publish):
    publisher = simROS2.createPublisher('/simulationTime', 'std_msgs/msg/Float32')
    subscriber = simROS2.createSubscription('/simulationTime', 'std_msgs/msg/Float32', 'subscriber_callback')
end

function sysCall_actuation()
    -- Send an updated simulation time message, and send the transform of the object this script is attached to:
    simROS2.publish(publisher, {data = sim.getSimulationTime()})
    simROS2.sendTransform(getTransformStamped(objectHandle, objectAlias, -1, 'world'))
    -- To send several transforms at once, use simROS2.sendTransforms instead
end

function sysCall_cleanup()
    -- Following not really needed in a simulation script (i.e. automatically shut down at simulation end):
    simROS.shutdownPublisher(publisher)
    simROS.shutdownSubscriber(subscriber)
end

上述脚本将同时发布仿真时间并订阅它,此外还会发布附加该脚本的对象的变换信息。你可以通过以下命令查看仿真时间的话题列表:



bash复制代码

$ ros2 topic list

为了查看消息内容,你可以输入:



bash复制代码

$ ros2 topic echo /simulationTime

接下来,加载演示场景 messaging/ros2InterfaceTopicPublisherAndSubscriber.ttt 并运行仿真。在这个场景中,附加到Vision_sensor的视觉传感器仿真脚本包含的代码将启用一个发布者来流式传输视觉传感器的图像数据,并启用一个订阅者来监听同一个数据流。这里的订阅者将读取到的数据应用到被动视觉传感器上,该被动视觉传感器仅用作数据容器。

以下是具体发生的情况的详细总结:

  1. 发布与订阅仿真时间
  • 脚本的一部分功能是在ROS 2网络中发布当前的仿真时间,并同时订阅该时间话题。这可以用于同步或记录仿真过程中的时间信息。
  1. 发布对象变换
  • 脚本还会发布附加该脚本的对象的变换信息(如位置、姿态等)。这对于需要知道对象在仿真环境中位置的应用来说非常有用。
  1. 视觉传感器数据的发布与订阅
  • messaging/ros2InterfaceTopicPublisherAndSubscriber.ttt场景中,视觉传感器通过ROS 2接口发布其捕获的图像数据。这允许其他ROS 2节点接收并处理这些数据。
  • 同时,该场景中还设置了一个订阅者,它订阅了由视觉传感器发布的相同数据流。订阅者接收到数据后,将其应用到被动视觉传感器上。这里,被动视觉传感器实际上并不进行任何实际的视觉处理,而是作为数据容器存在,用于演示数据如何在ROS 2网络中流动。
  1. 数据流的双向性
  • 这个例子展示了CoppeliaSim如何同时作为数据的生产者和消费者。它不仅能够发布数据供其他系统使用,还能够订阅并处理来自其他节点的数据。这种双向数据流的能力使得CoppeliaSim能够与其他ROS 2节点无缝集成,实现复杂的仿真和控制系统。
  1. 演示目的
  • 通过这个演示,用户可以直观地看到ROS 2接口如何在CoppeliaSim中工作,以及如何利用ROS 2的强大功能来扩展仿真应用的能力。这包括数据的实时传输、处理以及仿真与真实世界之间的交互等。

CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-_持续学习_04

 

在这个实验中,你可以尝试对代码进行一些修改和实验。CoppeliaSim 能够通过 ROS 2 接口流式传输图像数据,你可以使用以下命令来可视化这些图像:



bash复制代码

$ ros2 run image_tools showimage --ros-args --remap image:=/image

这个命令会启动 image_tools 包中的 showimage 工具,并通过 --remap 参数将 /image 话题映射为工具所需的输入。这样,你就可以在运行时窗口中看到从 CoppeliaSim 传输过来的图像了。

如果你传输的是更简单的数据类型(比如数字、字符串等),你也可以使用 ros2 topic echo 命令来查看这些数据:



bash复制代码

$ ros2 topic echo /image

但请注意,对于图像数据,ros2 topic echo 并不适用,因为它无法直接以人类可读的形式显示图像内容。

现在,停止当前的仿真,并加载 controlTypeExamples/controlledViaRos2.ttt 演示场景,然后运行仿真。在这个场景中,有一个简化的机器人模型,其行为也被设计为尽可能简单,以便于理解。这个机器人通过 ROS 2 接口进行控制。

通过这个演示,你可以学习到如何使用 ROS 2 来控制 CoppeliaSim 中的机器人。你可以通过发送特定的 ROS 2 消息来控制机器人的运动,比如移动关节、设置末端执行器的位置或姿态等。这个过程涉及到 ROS 2 节点之间的通信,以及如何将 ROS 2 消息映射到 CoppeliaSim 的仿真环境中。

CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-_持续学习_05

在CoppeliaSim中,附加到机器人的仿真脚本以非线程方式运行,主要负责以下任务:

  1. 确定对象句柄:例如电机关节句柄和接近传感器句柄。
  2. 启动电机速度订阅者:监听并响应来自ROS 2的电机速度控制命令。
  3. 启动传感器发布者和仿真时间发布者:将传感器的数据和当前的仿真时间发布到ROS 2话题上。
  4. 启动客户端应用程序:调用名为ros2BubbleRob的客户端应用程序,并传递一些话题名称作为参数,以便它知道需要监听和订阅哪些话题。之后,ros2BubbleRob客户端应用程序将通过ROS 2接管对机器人的控制。

在仿真运行时,你可以复制并粘贴机器人模型多次。注意,每次复制的机器人都是直接可操作且独立的。这是CoppeliaSim众多强大功能之一,允许用户轻松创建复杂的仿真场景。

现在,停止当前仿真并打开一个新场景,然后将Models/tools/ros2Interface helper tool.ttm模型拖入其中。这个模型包含一个自定义脚本,提供了以下话题的发布者和订阅者:

  • startSimulation:通过向此话题发布std_msgs/msg/Bool消息来启动仿真。
  • pauseSimulation:通过向此话题发布std_msgs/msg/Bool消息来暂停仿真。
  • stopSimulation:通过向此话题发布std_msgs/msg/Bool消息来停止仿真。
  • enableSyncMode:通过向此话题发布std_msgs/msg/Bool消息来启用或禁用步进模式。
  • triggerNextStep:在步进模式下,通过向此话题发布std_msgs/msg/Bool消息来触发下一个仿真步骤。
  • simulationStepDone:在每个仿真周期结束时,发布类型为std_msgs/msg/Bool的消息。
  • simulationState:定期发布类型为std_msgs/msg/Int32的消息,其中0表示仿真已停止,1表示正在运行,2表示已暂停。
  • simulationTime:定期发布类型为std_msgs/msg/Float32的消息,指示当前的仿真时间。

你可以查看并完全自定义这个自定义脚本,以满足不同的需求。此外,尝试从命令行生成话题消息,例如使用ROS 2命令行工具来发布消息到这些话题,以测试和控制仿真过程。这提供了一种灵活的方式来与CoppeliaSim中的ROS 2接口进行交互。

$ ros2 topic pub /startSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /pauseSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /stopSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /enableSyncMode std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /startSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /triggerNextStep std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /triggerNextStep std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /triggerNextStep std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /stopSimulation std_msgs/msg/Bool '{data: true}' --once