ROS入门(六)——仿真机器人二(Xacro+Rviz+Arbotix小车运动)
【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程P229-251【以上视频笔记见http://www.autolabor.com.cn/book/ROSTutorials/】
所用的学习链接:
【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程P252-270
【以上视频笔记见http://www.autolabor.com.cn/book/ROSTutorials/】
前文参考ROS入门(五)——仿真机器人一(URDF+Rviz)
一、介绍
1.Xacro作用
Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。
对于一个机器人,我们往往会有多个相类似的组件,例如车子的左轮和右轮,直接编写URDF文件会导致代码量重复,因此我们需要Xacro来起到一种函数封装的作用。在Xacro中,一些参数可以设置为定量和变量,在创建时传入变量,可以实现相似组件的批量生成。
它也可以实现变量计算和求解,避免一些运算中的人力劳动。
2.目标
1.创建底座和车轮的xacro文件
2.编写摄像头和雷达的 xacro 文件
3.编写一个组合文件,组合底盘、摄像头与雷达
4.通过 launch 文件启动 Rviz 并显示模型
3.Xacro语法
(1)属性
- 定义属性
即定义一些常量和数值,如小车高度、离地距离,在本次实操中数值固定。例如要定义PI=3.1415927
<xacro:property name="PI" value="3.1415927" />
- 属性调用
${属性名称}
- 算术运算
${数学表达式}
(2)宏
- 宏定义
即算法中的函数,可以对相同结构和属性进行封装.
<!-- 多参数之间使用空格分隔 -->
<xacro:macro name="宏名称" params="参数1 参数2 ..">
.....
</xacro:macro>
- 宏调用
调用创建好的宏,可以传入一批参数,和宏中定义的参数统一。
<xacro:宏名称 参数1="xxx" 参数2="yyy" ../>
(3)计算样例
实现1+6=7的宏定义和宏调用
<robot name="t" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 1.宏定义 -->
<xacro:macro name="getsum" params="num1 num2">
<result value="${num1+num2}"/>
</xacro:macro>
<!-- 2.宏调用 -->
<xacro:getsum num1="1" num2="6"/>
</robot>
(4)组合样例
在完成单独组件的xacro文件编写后,我们会希望将更多组件组合在一起,拼接成一个完整的模型,则需要新生成一个用于组合的xacro文件,运行launch时直接调用该文件。
<robot name="xxx" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="文件1.xacro" />
<xacro:include filename="文件2.xacro" />
<xacro:include filename="文件3.xacro" />
....
</robot>
二、分别创建车体、摄像头和雷达
1.创建底座和车轮(车体)
在之前文章中生成的xacro文件夹中,我们创建一个表示车体的xacro文件【t1_car.xacro】
<!--
1.利用xacro:property来封装常量
2.利用宏构造相似车轮(左右轮相似、前后轮相似)
-->
<!-- 根标签,必须声明 xmlns:xacro -->
<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- 封装变量、常量 -->
<xacro:property name="PI" value="3.141" />
<!-- 宏:黑色设置 -->
<material name="black">
<color rgba="0.0 0.0 0.0 1.0" />
</material>
<!-- 封装底盘属性 -->
<xacro:property name="base_footprint_radius" value="0.001" /> <!-- base_footprint 半径 -->
<xacro:property name="base_link_radius" value="0.1" /> <!-- base_link 半径 -->
<xacro:property name="base_link_length" value="0.08" /> <!-- base_link 长 -->
<xacro:property name="earth_space" value="0.015" /> <!-- 离地间距 -->
<!-- 底盘只有一个,直接编写 -->
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="${base_footprint_radius}" />
</geometry>
</visual>
</link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_link_radius}" length="${base_link_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow">
<color rgba="0.5 0.3 0.0 0.5" />
</material>
</visual>
</link>
<joint name="base_link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link" />
<origin xyz="0 0 ${earth_space + base_link_length / 2 }" />
</joint>
<!-- 驱动轮 -->
<!-- 驱动轮属性封装 -->
<xacro:property name="wheel_radius" value="0.0325" /> <!-- 半径 -->
<xacro:property name="wheel_length" value="0.015" /> <!-- 宽度 -->
<!-- 驱动轮宏实现 -->
<xacro:macro name="add_wheels" params="name flag">
<link name="${name}_wheel">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
<material name="black" />
</visual>
</link>
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="0 ${flag * base_link_radius} ${-(earth_space + base_link_length / 2 - wheel_radius) }" />
<axis xyz="0 1 0" />
</joint>
</xacro:macro>
<!-- 宏调用,添加左右轮 -->
<xacro:add_wheels name="left" flag="1" />
<xacro:add_wheels name="right" flag="-1" />
<!-- 支撑轮 -->
<!-- 支撑轮属性 -->
<xacro:property name="support_wheel_radius" value="0.0075" /> <!-- 支撑轮半径 -->
<!-- 支撑轮宏 -->
<xacro:macro name="add_support_wheel" params="name flag">
<link name="${name}_wheel">
<visual>
<geometry>
<sphere radius="${support_wheel_radius}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="black" />
</visual>
</link>
<!-- 支撑轮和底盘的关节宏 -->
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="${flag * (base_link_radius - support_wheel_radius)} 0 ${-(base_link_length / 2 + earth_space / 2)}" />
<axis xyz="1 1 1" />
</joint>
</xacro:macro>
<!-- 宏调用,添加前后支撑轮 -->
<xacro:add_support_wheel name="front" flag="1" />
<xacro:add_support_wheel name="back" flag="-1" />
</robot>
2.创建摄像头
在之前文章中生成的xacro文件夹中,我们创建一个表示摄像头的xacro文件【t2_camera.xacro】
<!-- 摄像头相关的 xacro 文件 -->
<robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 摄像头属性 -->
<xacro:property name="camera_length" value="0.01" /> <!-- 摄像头长度(x) -->
<xacro:property name="camera_width" value="0.025" /> <!-- 摄像头宽度(y) -->
<xacro:property name="camera_height" value="0.025" /> <!-- 摄像头高度(z) -->
<xacro:property name="camera_x" value="0.08" /> <!-- 摄像头安装的x坐标 -->
<xacro:property name="camera_y" value="0.0" /> <!-- 摄像头安装的y坐标 -->
<xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2 -->
<!-- 摄像头关节以及link -->
<link name="camera">
<visual>
<geometry>
<box size="${camera_length} ${camera_width} ${camera_height}" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
</visual>
</link>
<joint name="camera2base_link" type="fixed">
<parent link="base_link" />
<child link="camera" />
<origin xyz="${camera_x} ${camera_y} ${camera_z}" />
</joint>
</robot>
3.创建雷达
在之前文章中生成的xacro文件夹中,我们创建一个表示雷达的xacro文件【t3_laser.xacro】
<!--
小车底盘添加雷达
-->
<robot name="my_laser" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 雷达支架 -->
<xacro:property name="support_length" value="0.15" /> <!-- 支架长度 -->
<xacro:property name="support_radius" value="0.01" /> <!-- 支架半径 -->
<xacro:property name="support_x" value="0.0" /> <!-- 支架安装的x坐标 -->
<xacro:property name="support_y" value="0.0" /> <!-- 支架安装的y坐标 -->
<xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" /> <!-- 支架安装的z坐标:底盘高度 / 2 + 支架高度 / 2 -->
<link name="support">
<visual>
<geometry>
<cylinder radius="${support_radius}" length="${support_length}" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="red">
<color rgba="0.8 0.2 0.0 0.8" />
</material>
</visual>
</link>
<joint name="support2base_link" type="fixed">
<parent link="base_link" />
<child link="support" />
<origin xyz="${support_x} ${support_y} ${support_z}" />
</joint>
<!-- 雷达属性 -->
<xacro:property name="laser_length" value="0.05" /> <!-- 雷达长度 -->
<xacro:property name="laser_radius" value="0.03" /> <!-- 雷达半径 -->
<xacro:property name="laser_x" value="0.0" /> <!-- 雷达安装的x坐标 -->
<xacro:property name="laser_y" value="0.0" /> <!-- 雷达安装的y坐标 -->
<xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" /> <!-- 雷达安装的z坐标:支架高度 / 2 + 雷达高度 / 2 -->
<!-- 雷达关节以及link -->
<link name="laser">
<visual>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
</visual>
</link>
<joint name="laser2support" type="fixed">
<parent link="support" />
<child link="laser" />
<origin xyz="${laser_x} ${laser_y} ${laser_z}" />
</joint>
</robot>
三、组件组合
方法一(不推荐):转换成urdf后组合
在xacro文件夹下打开继承终端,运行。
# rosrun xacro xacro xxx.xacro > xxx.urdf
rosrun xacro xacro t1_car.xacro > t1_xacro_car.urdf
此时将xacro转换为urdf文件,后在launch中调用。调用方式可参考ROS入门(五)——仿真机器人一(URDF+Rviz)
方法二(推荐):新建xacro组合文件
在完成单独组件的xacro文件编写后,我们会希望将更多组件组合在一起,拼接成一个完整的模型,则需要新生成一个用于组合的xacro文件,运行launch时直接调用该文件就可以将所有组件一起显示。
需要组合的xacro:
- t1_car.xacro 【车体+车轮】
- t2_camera.xacro 【摄像头】
- t3_laser.xacro 【雷达】
新建一个t4_123combine.xacro文件,组合各个组件
<!-- 组合小车、摄像头、雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="t1_car.xacro" />
<xacro:include filename="t2_camera.xacro" />
<xacro:include filename="t3_laser.xacro" />
</robot>
四、launch调用xacro并运行rviz
1.编辑launch文件
在launch文件夹下新建一个launch文件【t4_xacro.launch】
<launch>
<!-- 将 xacro 文件内容设置进参数服务器 -->
<!-- urdf调用方式 -->
<!-- <param name="robot_description" textfile="$(find urdf_rviz)/urdf/urdf/t1_car.urdf" /> -->
<!-- xacro调用方式 -->
<param name="robot_description" command="$(find xacro)/xacro $(find urdf_rviz)/urdf/xacro/t4_123combine.xacro" />
<!-- 启动 rivz -->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_rviz)/config/t1_car.rviz" />
<!-- <node pkg="rviz" type="rviz" name="rviz" /> -->
<!-- 启动机器人状态和关节状态发布节点 -->
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" output="screen" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" />
<!-- 启动图形化的控制关节运动节点 -->
<node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" output="screen" />
</launch>
2.运行launch文件
①ctrl+shift+b编译
②打开新终端1
roscore
③打开新终端2
roslaunch urdf_rviz t4_xacro.launch
正常显示
五、小车运动(Arbotix)
1.安装Arbotix
下载源码
git clone https://github.com/vanadiumlabs/arbotix_ros.git
将下载好的文件夹复制到 工作空间/src 下
2.配置
(1)控制文件
在 src/config 目录下新建一个文件 control.yaml
# 该文件是控制器配置,一个机器人模型可能有多个控制器,比如: 底盘、机械臂、夹持器(机械手)....
# 因此,根 name 是 controller
controllers: {
# 单控制器设置
base_controller: {
#类型: 差速控制器
type: diff_controller,
#参考坐标
base_frame_id: base_footprint,
#两个轮子之间的间距
base_width: 0.2,
#控制频率
ticks_meter: 2000,
#PID控制参数,使机器人车轮快速达到预期速度
Kp: 12,
Kd: 12,
Ki: 0,
Ko: 50,
#加速限制
accel_limit: 1.0
}
}
(2)launch 文件中配置 arbotix 节点
在launch文件夹中新建一个 t5_arbotix.launch 文件,文件内容:
<launch>
<!-- 将 xacro 文件内容设置进参数服务器 -->
<!-- urdf调用方式 -->
<!-- <param name="robot_description" textfile="$(find urdf_rviz)/urdf/urdf/t1_car.urdf" /> -->
<!-- xacro调用方式 -->
<param name="robot_description" command="$(find xacro)/xacro $(find urdf_rviz)/urdf/xacro/t4_123combine.xacro" />
<!-- 启动 rivz -->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_rviz)/config/t1_car.rviz" />
<!-- <node pkg="rviz" type="rviz" name="rviz" /> -->
<!-- 启动机器人状态和关节状态发布节点 -->
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" output="screen" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" />
<!-- 集成 arbotix 运动控制节点,加载参数 -->
<node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
<!-- <rosparam file="$(find 工作空间)/config/文件名.yaml" command="load" /> -->
<rosparam file="$(find urdf_rviz)/config/control.yaml" command="load" />
<param name="sim" value="true" />
</node>
</launch>
- <node> 调用了 arbotix_python 功能包下的 arbotix_driver 节点
- <rosparam> arbotix 驱动机器人运行时,需要获取机器人信息,可以通过 file 加载配置文件
- <param> 在仿真环境下,需要配置 sim 为 true
3.启动
1.运行launch,打开rviz
roslaunch urdf_rviz t5_arbotix.launch
2.设置Fixed name为odom
3.Add添加odometry
4.设置odometry的Topic为/odom(展示运动轨迹)
5.检验
打开一个终端,输入
rostopic list
发现有一个/cmd_vel,说明发布 cmd_vel 话题消息控制小车运动了
6.运动起来
通过自定义线速度角速度,使小车自动运动
rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.2, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.5}}'
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)