目标:设置机器人仿真并通过 ROS 2 控制它。
教程级别:高级
时间:30 分钟
目录
背景
先决条件
任务
1 创建包结构
2 设置模拟世界
3 编辑
my_robot_driver
插件4 创建
my_robot.urdf
文件5 创建启动文件
6 编辑其他文件
7 测试代码
摘要
下一步
背景
在本教程中,您将使用 Webots 机器人模拟器来设置和运行一个非常简单的 ROS 2 仿真场景。
webots_ros2
包提供了 ROS 2 和 Webots 之间的接口。它包括几个子包,但在本教程中,您将只使用 webots_ros2_driver
子包来实现控制模拟机器人的 Python 或 C++ 插件。其他一些子包包含不同机器人(如 TurtleBot3)的演示。它们在 Webots ROS 2 示例页面中有记录。
先决条件
建议了解初学者教程中涵盖的基本 ROS 原理。特别是,使用 turtlesim、ros2 和 rqt,理解主题,创建工作区,创建包和创建启动文件是有用的先决条件。
Linux:
本教程的 Linux 和 ROS 命令可以在标准的 Linux 终端中运行。以下页面安装 (Ubuntu) 解释了如何在 Linux 上安装 webots_ros2
包。
本教程兼容 webots_ros2
版本 2023.1.0 和 Webots R2023b 以及即将发布的版本。
任务
1 创建包结构
让我们在自定义的 ROS 2 包中组织代码。从 ROS 2 工作区的 src
文件夹中创建一个名为 my_package
的新包。将终端的当前目录更改为 ros2_ws/src
并运行:
Python:
ros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_robot_driver my_package --dependencies rclpy geometry_msgs webots_ros2_driver
--node-name my_robot_driver
选项将在 my_package
子文件夹中创建一个 my_robot_driver.py
模板 Python 插件,您稍后将进行修改。 --dependencies rclpy geometry_msgs webots_ros2_driver
选项指定 package.xml
文件中 my_robot_driver.py
插件所需的包。
让我们在 my_package
文件夹中添加一个 launch
文件夹和一个 worlds
文件夹。
cxy@ubuntu2404-cxy:~/ros2_ws/src/my_package$ mkdir launch
cxy@ubuntu2404-cxy:~/ros2_ws/src/my_package$ mkdir worlds
cxy@ubuntu2404-cxy:~/ros2_ws/src/my_package$ tree
.
├── launch
├── LICENSE
├── my_package
│ ├── __init__.py
│ └── my_robot_driver.py
├── package.xml
├── resource
│ └── my_package
├── setup.cfg
├── setup.py
├── test
│ ├── test_copyright.py
│ ├── test_flake8.py
│ └── test_pep257.py
└── worlds
6 directories, 10 files
C++ :
ros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name MyRobotDriver my_package --dependencies rclcpp geometry_msgs webots_ros2_driver pluginlib
--node-name MyRobotDriver
选项将在 my_package/src
子文件夹中创建一个 MyRobotDriver.cpp
模板 C++ 插件,您稍后将进行修改。 --dependencies rclcpp geometry_msgs webots_ros2_driver pluginlib
选项指定 package.xml
文件中 MyRobotDriver
插件所需的包。
让我们在 my_package
文件夹中添加一个 launch
、一个 worlds
和一个 resource
文件夹。
cd my_package
mkdir launch
mkdir worlds
mkdir resource
必须创建两个附加文件: MyRobotDriver
的头文件和 my_robot_driver.xml
的 pluginlib 描述文件。
touch my_robot_driver.xml
touch include/my_package/MyRobotDriver.hpp
你应该最终得到以下文件夹结构:
src/
└── my_package/
├── include/
│ └── my_package/
│ └── MyRobotDriver.hpp
├── launch/
├── resource/
├── src/
│ └── MyRobotDriver.cpp
├── worlds/
├── CMakeList.txt
├── my_robot_driver.xml
└── package.xml
2 设置模拟世界
您将需要一个包含机器人的世界文件来启动您的模拟。 Download this world file
并将其移动到 my_package/worlds/
内。https://docs.ros.org/en/jazzy/_downloads/5ad123fc6a8f1ea79553d5039728084a/my_world.wbt
#VRML_SIM R2022b utf8 // VRML_SIM 文件格式,版本 R2022b,使用 UTF-8 编码
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2022b/projects/objects/backgrounds/protos/TexturedBackground.proto" // 引用外部原型文件 TexturedBackground.proto
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2022b/projects/objects/backgrounds/protos/TexturedBackgroundLight.proto" // 引用外部原型文件 TexturedBackgroundLight.proto
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2022b/projects/objects/floors/protos/CircleArena.proto" // 引用外部原型文件 CircleArena.proto
WorldInfo { // 世界信息节点
}
Viewpoint { // 视点节点
orientation -0.33185733874619844 -0.09874274160469809 0.9381474178937331 3.686018050088086 // 视点的方向
position 1.700313773507203 1.0549607538959629 1.4846240848267684 // 视点的位置
follow "my_robot" // 视点跟随的对象
}
TexturedBackground { // 纹理背景节点
}
TexturedBackgroundLight { // 纹理背景光节点
}
CircleArena { // 圆形竞技场节点
}
Robot { // 机器人节点
children [ // 子节点列表
HingeJoint { // 铰链关节节点
jointParameters HingeJointParameters { // 铰链关节参数
axis 0 1 0 // 关节轴
anchor 0 0 0.025 // 关节锚点
}
device [ // 设备列表
RotationalMotor { // 旋转电机节点
name "left wheel motor" // 电机名称
}
]
endPoint Solid { // 终点实体节点
translation 0 0.045 0.025 // 终点位置
children [ // 子节点列表
DEF WHEEL Transform { // 定义轮子变换节点
rotation 1 0 0 1.5707996938995747 // 轮子旋转
children [ // 子节点列表
Shape { // 形状节点
appearance PBRAppearance { // PBR 外观节点
baseColor 1 0 0 // 基础颜色
roughness 1 // 粗糙度
metalness 0 // 金属度
}
geometry Cylinder { // 几何体为圆柱体
height 0.01 // 圆柱体高度
radius 0.025 // 圆柱体半径
}
}
]
}
]
name "left wheel" // 轮子名称
boundingObject USE WHEEL // 使用定义的轮子作为边界对象
physics Physics { // 物理属性
}
}
}
HingeJoint { // 铰链关节节点
jointParameters HingeJointParameters { // 铰链关节参数
axis 0 1 0 // 关节轴
anchor 0 0 0.025 // 关节锚点
}
device [ // 设备列表
RotationalMotor { // 旋转电机节点
name "right wheel motor" // 电机名称
}
]
endPoint Solid { // 终点实体节点
translation 0 -0.045 0.025 // 终点位置
children [ // 子节点列表
USE WHEEL // 使用定义的轮子
]
name "right wheel" // 轮子名称
boundingObject USE WHEEL // 使用定义的轮子作为边界对象
physics Physics { // 物理属性
}
}
}
Transform { // 变换节点
translation 0 0 0.0415 // 变换位置
children [ // 子节点列表
Shape { // 形状节点
appearance PBRAppearance { // PBR 外观节点
baseColor 0 0 1 // 基础颜色
roughness 1 // 粗糙度
metalness 0 // 金属度
}
geometry DEF BODY Cylinder { // 定义几何体为圆柱体
height 0.08 // 圆柱体高度
radius 0.045 // 圆柱体半径
}
}
]
}
DistanceSensor { // 距离传感器节点
translation 0.042 0.02 0.063 // 传感器位置
rotation 0 0 1 0.5236003061004253 // 传感器旋转
children [ // 子节点列表
DEF SENSOR Transform { // 定义传感器变换节点
rotation 0 1 0 1.5708 // 传感器旋转
children [ // 子节点列表
Shape { // 形状节点
appearance PBRAppearance { // PBR 外观节点
baseColor 1 1 0 // 基础颜色
roughness 1 // 粗糙度
metalness 0 // 金属度
}
geometry Cylinder { // 几何体为圆柱体
height 0.004 // 圆柱体高度
radius 0.008 // 圆柱体半径
}
}
]
}
]
name "ds0" // 传感器名称
lookupTable [ // 查找表
0 1020 0
0.05 1020 0
0.15 0 0
]
numberOfRays 2 // 射线数量
aperture 1 // 光圈
}
DistanceSensor { // 距离传感器节点
translation 0.042 -0.02 0.063 // 传感器位置
rotation 0 0 1 -0.5235996938995747 // 传感器旋转
children [ // 子节点列表
USE SENSOR // 使用定义的传感器
]
name "ds1" // 传感器名称
lookupTable [ // 查找表
0 1020 0
0.05 1020 0
0.15 0 0
]
numberOfRays 2 // 射线数量
aperture 1 // 光圈
}
]
boundingObject Transform { // 边界对象变换节点
translation 0 0 0.0415 // 变换位置
children [ // 子节点列表
USE BODY // 使用定义的主体
]
}
physics Physics { // 物理属性
}
controller "<extern>" // 控制器
name "my_robot" // 机器人名称
}
这实际上是一个相当简单的文本文件,您可以在文本编辑器中可视化。一个简单的机器人已经包含在这个 my_world.wb