赞
踩
系列文章目录:
[ROS仿真小车(二)——添加摄像头雷达传感器]
结果演示:
找一个空闲地方,新建文件夹catkin_ws01,输入以下命令
导入依赖,在src目录下输入以下命令:
catkin_create_pkg jubot_demo urdf xacro #创建功能包、添加依赖
cd jubot_demo/
mkdir urdf
mkdir launch
mkdir meshes #存放渲染机器人模型的文件
mkdir config #存放rviz配置的文件
urdf文件夹中添加一个box_urdf.urdf
文件,复制如下内容:
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.2 0.1" />
</geometry>
</visual>
</link>
</robot>
在launch目录下,新建一个 box_launch.launch
文件,该 launch 文件需要启动 Rviz,并导入 urdf 文件,Rviz 启动后可以自动载入解析urdf文件,并显示机器人模型,核心问题:如何导入 urdf 文件? 在 ROS 中,可以将 urdf 文件的路径设置到参数服务器,使用的参数名是:robot_description,示例代码如下:
<launch>
<!-- 设置参数 -->
<param name="robot_description" textfile="$(find jubot_demo)/urdf/box_urdf.urdf" />
<!-- 启动 rviz -->
<node pkg="rviz" type="rviz" name="rviz" />
</launch>
同理先进行编译,再配置环境变量,然后启动rviz
rviz 启动后,会发现并没有盒装的机器人模型,这是因为默认情况下没有添加机器人显示组件,需要手动添加,添加方式如下
设置完毕后,可以正常显示了
重复启动launch文件时,Rviz 之前的组件配置信息不会自动保存,需要重复执行步骤4的操作,为了方便使用,可以使用如下方式优化:
首先,将当前配置保存进config目录
然后,launch文件中 Rviz 的启动配置添加参数:args,值设置为-d 配置文件路径
<launch>
<param name="robot_description" textfile="$(find 包名)/urdf/urdf/urdf01_HelloWorld.urdf" />
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find 报名)/config/rviz/show_mycar.rviz" />
</launch>
现在的launch文件如下:
<launch>
<!-- 设置参数 -->
<param name="robot_description" textfile="$(find jubot_demo)/urdf/box_urdf.urdf" />
<!-- 启动 rviz -->
<node pkg="rviz" type="rviz" name="rviz" />
<param name="robot_description" textfile="$find jubot_demo)/urdf/box_urdf.urdf" />
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find jubot_demo)/config/rviz/show_mycar.rviz" />
</launch>
再启动时,就可以包含之前的组件配置了,使用更方便快捷。
需求描述:
创建一个四轮圆柱状机器人模型,机器人参数如下,底盘为圆柱状,半径 10cm,高 8cm,四轮由两个驱动轮和两个万向支撑轮组成,两个驱动轮半径为 3.25cm,轮胎宽度1.5cm,两个万向轮为球状,半径 0.75cm,底盘离地间距为 1.5cm(与万向轮直径一致)
结果演示:
实现流程:
创建机器人模型可以分步骤实现
新建 urdf 文件,并与 launch 文件集成
搭建底盘
在底盘上添加两个驱动轮
在底盘上添加两个万向轮
在一的urdf和launch文件基础上进行修改
box_urdf.urdf文件
<!-- <robot name="mycar"> <link name="base_link"> <visual> <geometry> <box size="0.5 0.2 0.1" /> </geometry> </visual> </link> </robot> --> <robot name="mycar"> <!-- 设置 base_footprint --> <link name="base_footprint"> <visual> <geometry> <sphere radius="0.001" /> </geometry> </visual> </link> <!-- 添加底盘 --> <!-- 参数 形状:圆柱 半径:10 cm 高度:8 cm 离地:1.5 cm --> <link name="base_link"> <visual> <geometry> <cylinder radius="0.1" length="0.08" /> </geometry> <origin xyz="0 0 0" rpy="0 0 0" /> <material name="yellow"> <color rgba="0.8 0.3 0.1 0.5" /> </material> </visual> </link> <joint name="base_link2base_footprint" type="fixed"> <parent link="base_footprint" /> <child link="base_link"/> <origin xyz="0 0 0.055" /> </joint> <!-- 添加驱动轮 --> <!-- 添加驱动轮 --> <!-- 驱动轮是侧翻的圆柱 参数 半径: 3.25 cm 宽度: 1.5 cm 颜色: 黑色 关节设置: x = 0 y = 底盘的半径 + 轮胎宽度 / 2 z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm) axis = 0 1 0 --> <link name="left_wheel"> <visual> <geometry> <cylinder radius="0.0325" length="0.015" /> </geometry> <origin xyz="0 0 0" rpy="1.5705 0 0" /> <material name="black"> <color rgba="0.0 0.0 0.0 1.0" /> </material> </visual> </link> <joint name="left_wheel2base_link" type="continuous"> <parent link="base_link" /> <child link="left_wheel" /> <origin xyz="0 0.1 -0.0225" /> <axis xyz="0 1 0" /> </joint> <link name="right_wheel"> <visual> <geometry> <cylinder radius="0.0325" length="0.015" /> </geometry> <origin xyz="0 0 0" rpy="1.5705 0 0" /> <material name="black"> <color rgba="0.0 0.0 0.0 1.0" /> </material> </visual> </link> <joint name="right_wheel2base_link" type="continuous"> <parent link="base_link" /> <child link="right_wheel" /> <origin xyz="0 -0.1 -0.0225" /> <axis xyz="0 1 0" /> </joint> <!-- 添加万向轮(支撑轮) --> <!-- 添加万向轮(支撑轮) --> <!-- 参数 形状: 球体 半径: 0.75 cm 颜色: 黑色 关节设置: x = 自定义(底盘半径 - 万向轮半径) = 0.1 - 0.0075 = 0.0925(cm) y = 0 z = 底盘长度 / 2 + 离地间距 / 2 = 0.08 / 2 + 0.015 / 2 = 0.0475 axis= 1 1 1 --> <link name="front_wheel"> <visual> <geometry> <sphere radius="0.0075" /> </geometry> <origin xyz="0 0 0" rpy="0 0 0" /> <material name="black"> <color rgba="0.0 0.0 0.0 1.0" /> </material> </visual> </link> <joint name="front_wheel2base_link" type="continuous"> <parent link="base_link" /> <child link="front_wheel" /> <origin xyz="0.0925 0 -0.0475" /> <axis xyz="1 1 1" /> </joint> <link name="back_wheel"> <visual> <geometry> <sphere radius="0.0075" /> </geometry> <origin xyz="0 0 0" rpy="0 0 0" /> <material name="black"> <color rgba="0.0 0.0 0.0 1.0" /> </material> </visual> </link> <joint name="back_wheel2base_link" type="continuous"> <parent link="base_link" /> <child link="back_wheel" /> <origin xyz="-0.0925 0 -0.0475" /> <axis xyz="1 1 1" /> </joint> </robot>
box_launch.launch文件
<launch> <!-- 将 urdf 文件内容设置进参数服务器 --> <param name="robot_description" textfile="$(find jubot_demo)/urdf/box_urdf.urdf" /> <!-- 启动 rviz --> <!-- <node pkg="rviz" type="rviz" name="rviz" /> --> <node pkg="rviz" type="rviz" name="rviz" args="-d $(find jubot_demo)/config/rviz/show_four_wheel_car.rviz" /> <!-- 启动机器人状态和关节状态发布节点 --> <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" /> <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" /> <!-- 启动图形化的控制关节运动节点 --> <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" /> </launch>
然后启动roslaunch,在rviz中显示机器人模型:
前面 URDF 文件构建机器人模型的过程中,存在若干问题。
问题1:在设计关节的位置时,需要按照一定的公式计算,公式是固定的,但是在 URDF 中依赖于人工计算,存在不便,容易计算失误,且当某些参数发生改变时,还需要重新计算。
问题2:URDF 中的部分内容是高度重复的,驱动轮与支撑轮的设计实现,不同轮子只是部分参数不同,形状、颜色、翻转量都是一致的,在实际应用中,构建复杂的机器人模型时,更是易于出现高度重复的设计,按照一般的编程涉及到重复代码应该考虑封装。
如果在编程语言中,可以通过变量结合函数直接解决上述问题,在 ROS 中,已经给出了类似编程的优化方案,称之为:Xacro
概念
Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。
原理
Xacro 可以声明变量,可以通过数学运算求解,使用流程控制控制执行顺序,还可以通过类似函数的实现,封装固定的逻辑,将逻辑中需要的可变的数据以参数的方式暴露出去,从而提高代码复用率以及程序的安全性。
作用
较之于纯粹的 URDF 实现,可以编写更安全、精简、易读性更强的机器人模型文件,且可以提高编写效率。
在urdf文件夹下新建一个xacro文件夹,在文件夹中新建my_base.urdf.xacro
文件
<!-- 使用 xacro 优化 URDF 版的小车底盘实现: 实现思路: 1.将一些常量、变量封装为 xacro:property 比如:PI 值、小车底盘半径、离地间距、车轮半径、宽度 .... 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>
在 launch 文件中直接加载 xacro
box_launch.launch
内容示例:
<launch> <!-- 将 urdf 文件内容设置进参数服务器 --> <!-- <param name="robot_description" textfile="$(find jubot_demo)/urdf/box_urdf.urdf" /> --> <!-- 使用xacro优化urdf文件 --> <param name="robot_description" command="$(find xacro)/xacro $(find jubot_demo)/urdf/xacro/my_base.urdf.xacro" /> <!-- 启动 rviz --> <!-- <node pkg="rviz" type="rviz" name="rviz" /> --> <node pkg="rviz" type="rviz" name="rviz" args="-d $(find jubot_demo)/config/rviz/show_four_wheel_car.rviz" /> <!-- 启动机器人状态和关节状态发布节点 --> <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" /> <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" /> <!-- 启动图形化的控制关节运动节点 --> <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" /> </launch>
核心代码:
<!-- 使用xacro优化urdf文件 -->
<param name="robot_description" command="$(find xacro)/xacro $(find jubot_demo)/urdf/xacro/my_base.urdf.xacro" />
加载robot_description时使用command属性,属性值就是调用 xacro 功能包的 xacro 程序直接解析 xacro 文件。
重新启动launch,正常显示小车,说明配置成功
结果演示:
实现分析:
机器人模型由多部件组成,可以将不同组件设置进单独文件,最终通过文件包含实现组件的拼装。
实现流程:
1.首先编写摄像头和雷达的 xacro 文件
2.然后再编写一个组合文件,组合底盘、摄像头与雷达
3.最后,通过 launch 文件启动 Rviz 并显示模型
摄像头my_camera.urdf.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>
雷达 my_laser.urdf.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>
my_car_camera.urdf.xacro
文件
<!-- 组合小车底盘与摄像头与雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="my_base.urdf.xacro" />
<xacro:include filename="my_camera.urdf.xacro" />
<xacro:include filename="my_laser.urdf.xacro" />
</robot>
<launch> <!-- 将 urdf 文件内容设置进参数服务器 --> <!-- <param name="robot_description" textfile="$(find jubot_demo)/urdf/box_urdf.urdf" /> --> <!-- 使用xacro优化urdf文件 --> <!-- <param name="robot_description" command="$(find xacro)/xacro $(find jubot_demo)/urdf/xacro/my_base.urdf.xacro" /> --> <param name="robot_description" command="$(find xacro)/xacro $(find jubot_demo)/urdf/xacro/my_car_camera.urdf.xacro" /> <!-- 启动 rviz --> <!-- <node pkg="rviz" type="rviz" name="rviz" /> --> <node pkg="rviz" type="rviz" name="rviz" args="-d $(find jubot_demo)/config/rviz/show_four_wheel_car.rviz" /> <!-- 启动机器人状态和关节状态发布节点 --> <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" /> <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" /> <!-- 启动图形化的控制关节运动节点 --> <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" /> </launch>
在rviz中显示机器人
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。