ROS卡车手推车。 第4部分。使用rviz和gazebo编辑器创建机器人仿真

系列文章:
8.我们从电话控制ROS控制,GPS节点
7.机器人本地化:映射,AMCL,房间地图上的参考点
6.带轮编码器的里程表,房间地图,激光雷达
5.我们在rviz和凉亭中工作:xacro,新传感器。
4.使用rviz和gazebo编辑器创建机器人仿真。
3.加速,更换相机,固定步态
2.软件
1.铁

关于创建小型机器人的一系列文章的续篇。 这次我们将讨论在仿真中创建机器人的副本,该副本由可视ROS环境rviz和凉亭(以下称为“编辑器”)提供。 编辑器中的工作将在虚拟机上进行,该虚拟机的映像先前已提供用于下载映像 。 由于我们正在谈论仿真,建立模型,因此不需要机器人推车本身。



该系列中的先前文章:

1. 第3部分
2. 第2部分
3. 第一部分

创建基本的urdf文件

通常,以简化方式创建机器人的过程通常包括以下阶段:

1.创建机器人模型。
2.在仿真中测试模型。
3.创建一个真实的机器人模型。
4.测试真实模型。

当与ROS编辑器一起工作时,他们为在虚拟世界中构建模型和进行测试提供了巨大的机会,我们必须承认,真实的机器人模型并不总是表现得像他们的无能兄弟。 在这里,在虚拟世界中使用模型的时间会增加到最终确定真实模型所需的时间。
一位著名人士说,这样的时间礼物不仅负担不起一切。

在这方面,在以前的文章中,机器人的顺序被打乱了:首先,创建了机器人的真实模型。 现在,我们将讨论其虚拟化。

创建urdf


为了充分享受在凉亭中进行的模拟并测试机器人,您必须首先为机器人创建一个URDF文件。

URDF文件是可视化领域中的一种骨架。
简而言之,URDF文件是描述机器人的文件。

如前所述,将使用已安装ROS(Ubuntu 16.04,ROS-Kinetic)和可视编辑器的VMWARE Workstation映像来执行工作。 因此,所有动作在此系统中都是可重现的。

创建一个名为rosbots_description的ROS包。

为此,您需要使用catkin_ws / src输入文件夹并执行命令以在ROS中创建软件包:

roscd; cd ..; cd src; catkin_create_pkg rosbots_description rospy 

*如果执行roscd命令时; cd ..; cd src; 如果您不喜欢catkin_ws,那么也许您有几种此类环境。 为了激活必要的文件,请转到catkin_ws文件夹并运行以下命令:source devel / setup.bash。 为了避免丢失,如果要处理映像,可以从根目录进入该文件夹:cd〜;; cd catkin_ws。

如果一切顺利,则将创建rosbots_description文件夹。

为什么仅在catkin_ws / src中手动创建一个文件夹如此困难而又不容易? 那是什么样的红润?

您可以手动创建一个文件夹,但是还必须手动编写ROS可以使用的另外两个文件:CMakeLists.txt和package.xml。

它们在创建后出现在文件夹中:



他们的ROS自己创造。 虽然我们不会详细介绍它们的内容。
命令末尾的rospy意味着创建依赖项,支持python

继续前进。

在新创建的rosbots_description包中,创建urdf文件夹,并在其中创建rosbots.xacro文件。

 roscd rosbots_description mkdir urdf; cd urdf; touch rosbots.xacro chmod +x rosbots.xacro 

ROS系统的优点在于,您不会将其放在系统的哪个文件夹中,只需在行首使用roscd命令键入其名称即可立即到达目标。

现在,将以下代码放入新创建的文件中:

rosbots.xacro
 <?xml version="1.0" encoding="utf-8"?> <robot name="rosbots" xmlns:xacro="http://www.ros.org/wiki/xacro"> <link name="base_footprint"/> <joint name="base_joint" type="fixed"> <origin xyz="0 0 0.05" rpy="0 0 0" /> <parent link="base_footprint"/> <child link="base_link" /> </joint> <link name="base_link"> <visual> <geometry> <mesh filename="package://rosbots_description/meshes/base.dae"/> </geometry> <origin xyz="-0.52 -0.4 0.43" rpy="0 0 0"/> </visual> <collision> <geometry> <mesh filename="package://rosbots_description/meshes/base.dae"/> </geometry> <origin xyz="-0.52 -0.4 0.43" rpy="0 0 0"/> </collision> <inertial> <origin xyz="0.0 0 0."/> <mass value="0.5"/> <inertia ixx="0.01" ixy="0.0" ixz="0.0" iyy="0.01" iyz="0.0" izz="0.03" /> </inertial> </link> <joint name="second_level_joint" type="fixed"> <origin xyz="0 0 0.68" rpy="0 0 0" /> <parent link="base_link"/> <child link="base_second_link" /> </joint> <link name="base_second_link"> <visual> <geometry> <mesh filename="package://rosbots_description/meshes/base.dae"/> </geometry> <origin xyz="-0.52 -0.4 0.0" rpy="0 0 0"/> </visual> <collision> <geometry> <mesh filename="package://rosbots_description/meshes/base.dae"/> </geometry> <origin xyz="-0.52 -0.4 0.0" rpy="0 0 0"/> </collision> <!--inertial> <origin xyz="0.01 0 0.7"/> <mass value="1.0"/> <inertia ixx="0.01" ixy="0.0" ixz="0.0" iyy="0.01" iyz="0.0" izz="0.03" /> </inertial--> </link> <joint name="mcu_joint" type="fixed"> <origin xyz="0.02 0.12 0.73" rpy="0 0 0" /> <parent link="base_link"/> <child link="mcu_link" /> </joint> <link name="mcu_link"> <visual> <geometry> <mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/> </geometry> <origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/> </visual> <collision> <geometry> <mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/> </geometry> <origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/> </collision> <!-- inertial> <origin xyz="0.01 0 0"/> <mass value="1.0"/> <inertia ixx="0.019995" ixy="0.0" ixz="0.0" iyy="0.019995" iyz="0.0" izz="0.03675" /> </inertial--> </link> <joint name="mcu_joint_1" type="fixed"> <origin xyz="0.02 0.12 0.83" rpy="0 0 0" /> <parent link="base_link"/> <child link="mcu_link_1" /> </joint> <link name="mcu_link_1"> <visual> <geometry> <mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/> </geometry> <origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/> </visual> <collision> <geometry> <mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/> </geometry> <origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/> </collision> <!-- inertial> <origin xyz="0.01 0 0"/> <mass value="1.0"/> <inertia ixx="0.019995" ixy="0.0" ixz="0.0" iyy="0.019995" iyz="0.0" izz="0.03675" /> </inertial--> </link> <joint name="stand_mcu1_joint" type="fixed"> <origin xyz="0.02 0.25 0.78" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_mcu1_link" /> </joint> <link name="stand_mcu1_link"> <visual> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> </link> <joint name="stand_mcu2_joint" type="fixed"> <origin xyz="0.02 -0.1125 0.78" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_mcu2_link" /> </joint> <link name="stand_mcu2_link"> <visual> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> </link> <joint name="stand_mcu3_joint" type="fixed"> <origin xyz="0.25 0.25 0.78" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_mcu3_link" /> </joint> <link name="stand_mcu3_link"> <visual> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> </link> <joint name="stand_mcu4_joint" type="fixed"> <origin xyz="0.25 -0.1125 0.78" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_mcu4_link" /> </joint> <link name="stand_mcu4_link"> <visual> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.1" radius="0.01"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> </link> <joint name="batery_joint" type="fixed"> <origin xyz="1.2 0.2 0.43" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="batery_link" /> </joint> <link name="batery_link"> <visual> <geometry> <mesh filename="package://rosbots_description/meshes/battery.dae" scale="13.0 6.0 6.0"/> </geometry> <origin xyz="0 4.5 0.05" rpy="1.57 0 1.57"/> </visual> <collision> <geometry> <mesh filename="package://rosbots_description/meshes/battery.dae" scale="13.0 6.0 6.0"/> </geometry> <origin xyz="0 4.5 0.05" rpy="1.57 0 1.57"/> </collision> <!-- inertial> <origin xyz="0.01 0 0"/> <mass value="1.0"/> <inertia ixx="0.01" ixy="0.0" ixz="0.0" iyy="0.01" iyz="0.0" izz="0.03" /> </inertial--> </link> <joint name="stand_1_joint" type="fixed"> <origin xyz="0.5 0.4125 0.58" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_1_link" /> </joint> <link name="stand_1_link"> <visual> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> <!--inertial> <origin xyz="0.0 0 0"/> <mass value="1.0"/> <inertia ixx="0.019995" ixy="0.0" ixz="0.0" iyy="0.019995" iyz="0.0" izz="0.03675" /> </inertial--> </link> <joint name="stand_2_joint" type="fixed"> <origin xyz="0.5 -0.2625 0.58" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_2_link" /> </joint> <link name="stand_2_link"> <visual> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> <!--inertial> <origin xyz="0.0 0 0"/> <mass value="1.0"/> <inertia ixx="0.019995" ixy="0.0" ixz="0.0" iyy="0.019995" iyz="0.0" izz="0.03675" /> </inertial--> </link> <joint name="wheel_left_joint" type="continuous"> <parent link="base_link"/> <child link="wheel_left_link"/> <origin xyz="0.15 0.4125 0.30" rpy="-1.57 0 0"/> <axis xyz="0 0 1"/> </joint> <link name="wheel_left_link"> <collision> <geometry> <cylinder length="0.20" radius="0.23"/> </geometry> <origin rpy="0.0 0.0 0" xyz="0 0 0.1"/> </collision> <visual name="visual"> <geometry> <!-- cylinder length="0.0206" radius="0.0550"/--> <!--cylinder length="0.20" radius="0.26"/--> <mesh filename="package://rosbots_description/meshes/wheel.dae" scale="8.0 8.0 8.0"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0"/> </visual> <inertial> <mass value="0.4" /> <origin xyz="0 0 0" /> <inertia ixx="0.001" ixy="0.0" ixz="0.0" iyy="0.001" iyz="0.0" izz="0.001" /> </inertial> </link> <joint name="wheel_right_joint" type="continuous"> <parent link="base_link"/> <child link="wheel_right_link"/> <origin xyz="0.15 -0.5625 0.30" rpy="-1.57 0 0"/> <axis xyz="0 0 1"/> </joint> <link name="wheel_right_link"> <collision> <geometry> <cylinder length="0.20" radius="0.23"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.195"/> </collision> <visual name="visual"> <geometry> <!--cylinder length="0.20" radius="0.26"/--> <mesh filename="package://rosbots_description/meshes/wheel.dae" scale="8.0 8.0 8.0"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0"/> </visual> <inertial> <mass value="0.4" /> <origin xyz="0 0.0 0.3" /> <inertia ixx="0.001" ixy="0.0" ixz="0.0" iyy="0.001" iyz="0.0" izz="0.001" /> </inertial> </link> <joint name="caster_back_joint" type="fixed"> <parent link="base_link"/> <child link="caster_back_link"/> <origin xyz="-0.4 0.1 0.26" rpy="0 0 0"/> </joint> <link name="caster_back_link"> <collision> <geometry> <!-- cylinder length="0.05" radius="0.19"/--> <sphere radius="0.19"/> </geometry> <origin rpy="0 0 0" xyz="0 0 0"/> </collision> <visual> <geometry> <!--cylinder length="0.05" radius="0.19"/--> <sphere radius="0.19"/> </geometry> <origin rpy="0 0 0" xyz="0 0 0"/> </visual> <inertial> <mass value="0.1" /> <origin xyz="0 0 0" /> <inertia ixx="0.001023539" ixy="0.0" ixz="0.0" iyy="0.001023539" iyz="0.0" izz="0.001023539" /> </inertial> </link> <joint name="stand_3_joint" type="fixed"> <origin xyz="-0.4 0.4125 0.58" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_3_link" /> </joint> <link name="stand_3_link"> <visual> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> </link> <joint name="stand_4_joint" type="fixed"> <origin xyz="-0.4 -0.2625 0.58" rpy="0 0 1.57" /> <parent link="base_link"/> <child link="stand_4_link" /> </joint> <link name="stand_4_link"> <visual> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </visual> <collision> <geometry> <cylinder length="0.20" radius="0.03"/> </geometry> <origin rpy="0.0 0 0" xyz="0 0 0.0"/> </collision> </link> </robot> 


如果代码未出现,则可以在文章末尾下载所有文件。

对于上面的代码,我们还需要单元(网格),这些单元将在程序包启动时加载。

机甲可以在这里
并将解压后的meches文件夹放在rosbots_description中。

如果仔细查看代码,您会发现这是一个由块组成的标准xml文件:
-视觉
-碰撞
-惯性

每个块都描述了自己的部分:视觉是机器人的外观,仅此而已,碰撞和惯性是机器人的物理特性,一切将如何与外界交互-碰撞,惯性。
关节-有助于确定机器人各部分之间运动的元素(链接)。 例如,轮子(轮子)的运动会影响整个框架(底盘)。

原点xyz是对象沿x,y,z轴的初始位置。

父链接和子链接分别是父链接和子链接,它们是从什么中扩展出来的。
类型的存在也值得注意:type =“ continuous”,type =“ fixed”。 这是什么可以旋转和不能旋转的定义。 因此轮子是连续的。 并且,例如,batery_joint是固定的。
代码中的缩进与python中一样有意义,在python中,您不能干扰制表符和空格,请勿携带。 但是,对于完美主义者的天堂和知名度而言,最好拥有它们。

上面的代码实质上是机器人模型。

在rviz工作


让我们看看发生了什么。

为此,请创建一个将运行ROS软件包的启动文件。

为此,在ROS中使用了所谓的启动文件。 启动文件的本质是允许使用一个短命令启动一个节点,命令或多个节点,而无需在其中指定所有参数和其他参数。

使用rviz.launch文件在rosbots_description中创建一个启动文件夹:

 roscd rosbots_description mkdir launch; cd launch; touch rviz.launch 

*此后,不再需要像以前一样创建ROS程序包。 现在,系统本身将“查看”软件包中的文件。 因此,我们只创建一个目录。

用内容填充文件-
rviz.launch
  <?xml version="1.0"?> <launch> <param name="robot_description" command="cat '$(find rosbots_description)/urdf/rosbots.xacro'"/> <!-- send fake joint values --> <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"> <param name="use_gui" value="False"/> </node> <!-- Combine joint values --> <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher"/> <!-- Show in Rviz --> <node name="rviz" pkg="rviz" type="rviz" /> </launch> 


在这里,您可以看到启动时系统将在rosbots.xacro中查找模型描述。

接下来,它将启动3个节点:来自joint_state_publisher包的joint_state_publisher,来自robot_state_publisher的robot_state_publisher,来自rviz的rviz。 type是节点的类型,通常对应于同名的Python或C文件,但未指定扩展名。

运行:

在第一个终端中,运行ROS master:

 roscore 

在第二个:

 roslaunch rosbots_description rviz.launch 

*如果发生错误
ROS_MASTER_URI [http://192.168.1 ....:11311]主机未设置为此机器
,那么您需要检查bashrc-运行ip ROS的地址:

 nano ~/.bashrc 

在bashrc文件本身中指定虚拟机的ip(例如,这一步):

 export ROS_MASTER_URI=http://192.168.1.114:11311 

重读bashrc:

source ~/.bashrc或重新启动。
**
如果roslaunch仍然没有启动,那么您可以尝试转到catkin_ws文件夹并运行:source devel / setup.bash

跳入Rviz


执行命令后,Rviz编辑器将启动,图形外壳程序将打开。
视觉呈现可能会有所不同,但通常视图大致如下:



在“显示”列的左侧,您可以观察到与ROS节点交互的各种元素的显示选项,在中间(是机器人的图像)在右边是可以看到机器人视图的列。 我必须马上说,最好使用带有rviz的三轮鼠标,因为这里涉及所有鼠标按钮。 按住左侧,您可以在显示机器人的窗口中旋转空间,按住右侧-放大/缩小,按住两个键-相对于机器人移动空间。

编辑器中的大部分工作在前两列中进行:机器人的显示和视觉表示。

让我们与机器人的外观一起工作


让我们在该行中选择“固定框架”-“基本链接”:



并将“机器人描述”添加到显示器:

单击“添加”,然后在列表中选择“ RobotModel”:



现在,在模拟窗口中,您可以观察到从rviz.xacro模型复制的机器人:



太好了 通过视觉表示,一切都变得清晰。 现在,您需要了解如何运行模拟,因为rviz只是模拟的可视化 ,而不是模拟本身。
也就是说,物理学在这里不起作用。

模拟本身存在于名为Gazebo的编辑器中。

凉亭


要将创建的模型放在凉亭中,请在项目的启动文件夹中创建另一个启动文件-spawn.launch。 现在,我们有2个启动文件!

生成启动
 <?xml version="1.0" encoding="UTF-8"?> <launch> <param name="robot_description" command="cat '$(find rosbots_description)/urdf/rosbots.xacro'" /> <arg name="x" default="0"/> <arg name="y" default="0"/> <arg name="z" default="0.5"/> <node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen" args="-urdf -param robot_description -model rosbots -x $(arg x) -y $(arg y) -z $(arg z)" /> </launch> 


在这里,我们还读取了模型,然后使用参数传递其在x,y,z轴上在空间中的位置。 接下来,仅运行一个节点-gazebo_ros软件包中的mybot_spawn。
*无需重新安装上述软件包。 如果需要,可以使用相同的命令roscd查看这些软件包。 例如roscd gazebo_ros。

现在在终端1中停止Ros-master:

 CTRL+C 

并运行Gazebo编辑器:

 roslaunch gazebo_ros empty_world.launch 

在终端2中,运行新创建的文件:

 roslaunch rosbots_description spawn.launch 

现在,我们在Gazebo编辑器的仿真中看到了我们的机器人:



*如果输入有误: Waiting for service /gazebo/spawn_urdf_model
这意味着您在没有先启动凉亭的情况下启动了模型,这违反了启动顺序。

让我们进入凉亭模拟。


现在,将以下代码添加到rosbots.xacro的结束标记之前:

代号
 <gazebo> <plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so"> <legacyMode>false</legacyMode> <alwaysOn>true</alwaysOn> <publishWheelTF>true</publishWheelTF> <publishTf>1</publishTf> <publishWheelJointState>true</publishWheelJointState> <updateRate>100.0</updateRate> <leftJoint>wheel_left_joint</leftJoint> <rightJoint>wheel_right_joint</rightJoint> <wheelSeparation>1.1</wheelSeparation> <wheelDiameter>0.52</wheelDiameter> <wheelAcceleration>1.0</wheelAcceleration> <torque>20</torque> <commandTopic>/part2_cmr/cmd_vel</commandTopic> <odometryTopic>odom</odometryTopic> <odometryFrame>odom</odometryFrame> <robotBaseFrame>base_link</robotBaseFrame> </plugin> </gazebo> 


编辑时无法关闭Simulator Gazebo。

现在,从凉亭编辑器中删除模型:

 rosservice call /gazebo/delete_model "model_name: 'rosbots'" 

或者只是重新启动编辑器。

*凉亭在虚拟机中很老套,因此即使关闭它,有时也会在终端中原谅CTRL +C。

编辑后,将模型重新放置在凉亭中:

 roslaunch rosbots_description spawn.launch 

如果现在查看ROS主题列表,您会发现其中有

 /part2_cmr/cmd_vel 



现在,让我们尝试通过在单独的终端中运行控件来在仿真中控制机器人:

 rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/part2_cmr/cmd_vel 

在运行控件的窗口中,并在终端窗口中按“ i”,“ l”,“ j”,“ k”,“,”键,您可以在Gazebo编辑器的仿真中观察机器人的运动:



代码下载

待续。

Source: https://habr.com/ru/post/zh-CN467241/


All Articles