1.项目简介
任务概述
在这个项目中,在catkin_ws/src中创建两个ROS包:drive_bot和ball_chaser。下面是设计机器人的步骤,把它安置在一个设定的世界里,并编程让它追逐白色的球:
1) drive_bot:
-创建一个my_robot ROS包来保存你的机器人、白球和世界(My World)。
-用统一的机器人描述格式(URDF)设计一个差动驱动机器人。给机器人添加两个传感器:一个激光雷达和一个摄像头。为机器人的差动驱动器、激光雷达和相机添加Gazebo插件。
-把机器人安置在项目中建造的世界(My World)里。
-添加一个白色的球到Gazebo 世界,并保存这个世界的一个新的副本。
-world.launch文件用于启动世界(My World)与白色的球和机器人。
2)ball_chaser:
-创建一个ball_chaser ROS包来保存c++节点。
-编写一个drive_bot c++节点,它将提供一个ball_chaser/command_robot服务,通过控制机器人的线性x和角z速度来驱动机器人。服务应该发布到车轮关节并返回请求的速度。
-写一个process_image c++节点来读取机器人的摄像头图像,分析它来确定一个白球的出现和位置。如果图像中出现一个白球,编写的节点将通过客户端请求一个服务驱动机器人追逐它。
-ball_chaser. launch应该同时运行drive_bot和process_image节点。
项目文件夹
项目的提交参照以下的目录结构,包含列出的所有文件:
Project # Go Chase It Project
├── my_robot # my_robot package
│ ├── launch # launch folder for launch files
│ │ ├── robot_description.launch
│ │ ├── world.launch
│ ├── meshes # meshes folder for sensors
│ │ ├── hokuyo.dae
│ ├── urdf # urdf folder for xarco files
│ │ ├── my_robot.gazebo
│ │ ├── my_robot.xacro
│ ├── world # world folder for world files
│ │ ├── <myworld>.world
│ ├── CMakeLists.txt # compiler instructions
│ ├── package.xml # package info
├── ball_chaser # ball_chaser package
│ ├── launch # launch folder for launch files
│ │ ├── ball_chaser.launch
│ ├── src # source folder for C++ scripts
│ │ ├── drive_bot.cpp
│ │ ├── process_images.cpp
│ ├── srv # service folder for ROS services
│ │ ├── DriveToTarget.srv
│ ├── CMakeLists.txt # compiler instructions
│ ├── package.xml # package info
└──
2.设置my_robot
这个项目中的第一个任务是创建my_robot ROS包。在my_robot中,将存储并启动一个空的Gazebo世界文件。随着项目的进行,将建模并存储一个机器人,把空的世界文件替换为在项目中创建的世界。现在,按照以下步骤设置my_robot。
创建my_robot包
1)创建并初始化一个catkin_ws
$ mkdir -p /home/workspace/catkin_ws/src
$ cd /home/workspace/catkin_ws/src
$ catkin_init_workspace
2)导航到catkin_ws的src目录,创建my_robot包:
$ cd /home/workspace/catkin_ws/src/
$ catkin_create_pkg my_robot
3)接下来,创建一个worlds目录和一个launch目录,这将进一步定义包的结构:
$ cd /home/workspace/catkin_ws/src/my_robot/
$ mkdir launch
$ mkdir worlds
创建并存储一个空的 Gazebo World文件
在worlds目录中,创建并存储一个空的Gazebo world文件。提醒一下,在Gazebo中,世界是模型的集合,比如机器人,以及特定的环境。还可以定义一些特定于这个世界的其他物理属性。
1)创建一个空白的Gazebo world
Gazebo里的空白世界是一个简单的世界,没有物体,没有模型。
$ cd /home/workspace/catkin_ws/src/my_robot/worlds/
$ touch empty.world
2)将以下内容添加到empty.world
<?xml version="1.0" ?>
<sdf version="1.4">
<world name="default">
<include>
<uri>model://ground_plane</uri>
</include>
<!-- Light source -->
<include>
<uri>model://sun</uri>
</include>
<!-- World camera -->
<gui fullscreen='0'>
<camera name='world_camera'>
<pose>4.927360 -4.376610 3.740080 0.000000 0.275643 2.356190</pose>
<view_controller>orbit</view_controller>
</camera>
</gui>
</world>
</sdf>
.world文件使用XML文件格式描述与Gazebo环境有关的所有元素。在这里创建的简单世界有以下元素:
-<sdf>:封装整个文件结构和内容的基本元素。
-<world>: world元素定义了世界描述和一些与该世界相关的属性。在本例中的世界添加一个地平面、一个光源和一个摄像机。每个模型或属性都可以有进一步的元素来添加细节。例如,camera有一个pose元素,它定义了它的位置和方向。
-<include>: 包含元素,与<uri>元素,提供到特定模型的路径。在Gazebo中,默认情况下有几个可用的模型。
创建启动文件( Launch File )
ROS中的启动文件允许我们同时执行多个节点,这有助于避免在单独的shell或终端中定义和启动多个节点的潜在繁琐任务。
1)创建world.launch文件
$ cd /home/workspace/catkin_ws/src/my_robot/launch/
$ touch world.launch
2)将以下内容添加到world.launch
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<!-- World File -->
<argname="world_file"default="$(find my_robot)/worlds/empty.world"/>
<!-- Launch Gazebo World -->
<includefile="$(find gazebo_ros)/launch/empty_world.launch">
<argname="use_sim_time"value="true"/>
<argname="debug"value="false"/>
<argname="gui"value="true" />
<argname="world_name"value="$(arg world_file)"/>
</include>
</launch
与.world文件一样,.launch文件也是基于XML的。启动文件的结构有两部分:
-首先,使用<arg>元素定义参数。每个这样的元素都有一个name属性和一个默认值。
-其次,从gazebo_ros包,包含world. launch文件。empty_world(https://github.com/ros-simulation/gazebo_ros_pkgs/blob/kinetic-devel/gazebo_ros/launch/empty_world.launch)文件包含一组重要的定义,这些定义由我们所创建的世界继承。使用world_name参数和作为参数值(value)传递的.world文件路径,将能够在Gazebo中启动world。
启动empty.world
$ cd /home/workspace/catkin_ws/
$ catkin_make
$ source devel/setup.bash
$ roslaunch my_robot world.launch
3.理解统一机器人描述格式(URDF)
由于使用ROS,必须使用统一机器人描述格式(Unified robot Description Format, URDF)对机器人建模,使用XML(https://www.w3schools.com/xml/xml_whatis.asp)标记语言。我们可以使用URDF文件定义一个机器人模型,它的运动学属性,视觉元素,甚至机器人的模型传感器。URDF只能描述由链状或树形结构的关节连接的刚性链接的机器人。它不能描述具有柔性或平行连杆的机器人。
一个有两个连杆和一个关节的简单机器人可以用URDF描述如下:
<?xml version="1.0"?>
<robot name="two_link_robot">
<!--Links-->
<linkname="link_1">
<visual>
<geometry>
<cylinderlength="0.5"radius="0.2"/>
</geometry>
</visual>
</link>
<linkname="link_2">
<visual>
<geometry>
<boxsize="0.6 0.1 0.2"/>
</geometry>
</visual>
</link>
<!--Joints-->
<jointname="joint_1"type="continuous">
<parentlink="link_1"/>
<childlink="link_2"/>
</joint>
</robot>
由于我们使用URDF文件来描述几个机器人和环境属性,因此这些文件往往又长又乏味。这就是为什么我们使用Xacro (XML宏)将单个URDF文件划分为多个Xacro文件的原因。虽然语法保持不变,但我们现在可以将机器人描述划分为更小的子系统。
由于URDF(和Xacro)文件基本上是XML,所以它们使用标记来定义机器人的几何形状和属性。最重要和最常用的标签及其元素如下所示:
<robot> </robot>
这是一个顶级(top)标签,包含与给定机器人相关的所有其他标签。
<link> </link>
机器人中的每个刚性连杆(link)都必须与此标签相关联。
属性
名称:需要唯一的连杆(link)名称属性。
元素
<visual> </visual>
此元素指定用于可视化目的的对象的外观。
名称 | 描述 |
<origin> | 可视元素相对于连杆(link)的参考框架的参考框架。 |
<geometry> | 视觉对象的形状。 |
<material> | 可视元素的材料。 |
<collision> </collision>
连杆(link)的碰撞属性。请注意,这可能与连杆(link)的视觉属性不同,例如,通常使用更简单的碰撞模型来减少计算时间。
名称 | 描述 |
<origin> | 碰撞元素的参考框架,相对于连杆(link)的参考框架。 |
<geometry> | 请参阅上面可视化元素中的几何描述。 |
<inertial> </inertial>
这个标签描述了连杆的惯性特性。
名称 | 描述 |
<origin> | 这是惯性参照系的姿态,相对于连杆参照系。惯性参照系的原点需要在重心上。 |
<mass> | 连杆的质量由该元素的value属性表示。 |
<inertia> | 3x3转动惯量矩阵,表示在惯量坐标系中。因为转动惯量矩阵是对称的,这里只指定了这个矩阵的6个对角线以上的元素,使用属性ixx, ixy, ixz, iyy, iyz, izz。 |
包含重要元素的<link>标签示例片段:
<linkname="link_1">
<inertial>
<origin xyz="0 0 0.4" rpy="0 0 0"/>
<massvalue="${mass1}"/>
<inertia ixx="30" ixy="0" ixz="0" iyy="50" iyz="0" izz="50"/>
</inertial>
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<mesh filename="package://kuka_arm/meshes/kr210l150/visual/link_1.dae"/>
</geometry>
<material name="">
<color rgba="0.75294 0.75294 0.75294 1"/>
</material>
</visual>
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<mesh filename="package://kuka_arm/meshes/kr210l150/collision/link_1.stl"/>
</geometry>
</collision>
</link>
<link>标签有更多可选元素,可用于定义其他属性,如颜色、材质、纹理等。有关这些标签的详细信息,请参阅此链接(urdf/XML/link - ROS Wiki)。
<joint> </joint>
该标签通常定义机器人中两个连杆之间的单个关节。可以使用此标签定义的关节类型包括:
Name | Description |
Fixed | 没有自由度的刚性接头。用于焊接连接。 |
Revolute | 绕轴旋转的有一定范围的关节。 |
Prismatic | 滑动关节:沿轴滑动的范围有限的关节 |
Continuous | 类似于转动关节,但没有限制。它可以围绕一个轴连续旋转。 |
Planar | 二维移动关节,允许在垂直于轴的平面上运动 |
Floating | 具有6个自由度的关节,一般用于四旋翼飞行器和无人机 |
属性
名称 唯一的关节名
类型 关节类型
元素
为了定义关节,我们需要声明旋转/平移轴以及组成关节的两个连杆之间的关系。
名称 | 描述 |
<origin> | 这是从父连杆到子连杆的转换。关节位于子连杆的原始点。 |
<parent> | 各自连接的父连杆的名称。 |
<child> | 各自连接的子连杆的名称。 |
<axis> | 为转动关节定义旋转轴,为移动关节定义平移轴,为平面关节定义曲面法线。固定和浮动关节不使用轴场。 |
包含重要元素的<joint>标签示例片段:
<joint name="joint_2"type="revolute">
<origin xyz="0.35 0 0.42" rpy="0 0 0"/>
<parent link="link_1"/>
<childlink="link_2"/>
<axisxyz="0 1 0"/>
</joint>
<joint>标签下的其他可选元素可以在这里找到(urdf/XML/joint - ROS Wiki)。
还有更多可选的标签和属性,有助于定义机器人的各种动态和运动学属性,以及传感器和执行器。要获得完整的列表,请参阅URDF上的ROS文档(urdf - ROS Wiki)。