[未完,还在写] 自己动手写一个 基于ROS用xacro文件新建自己的简单小车 搭载kinect

    技术2024-07-10  75

    写机器人主体

    机器人主体的代码很长,如下:

    <?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:property name="M_PI" value="3.14159"/> <xacro:property name="wheel_radius" value="0.033"/> <xacro:property name="wheel_length" value="0.017"/> <xacro:property name="base_link_radius" value="0.13"/> <xacro:property name="base_link_length" value="0.005"/> <xacro:property name="motor_radius" value="0.02"/> <xacro:property name="motor_length" value="0.08"/> <xacro:property name="motor_x" value="-0.055"/> <xacro:property name="motor_y" value="0.075"/> <xacro:property name="plate_height" value="0.07"/> <xacro:property name="standoff_x" value="0.12"/> <xacro:property name="standoff_y" value="0.10"/> <!-- 定义MRobot本体的宏 --> <xacro:macro name="mrobot_standoff_2in" params="parent number x_loc y_loc z_loc"> <joint name="standoff_2in_${number}_joint" type="fixed"> <origin xyz="${x_loc} ${y_loc} ${z_loc}" rpy="0 0 0" /> <parent link="${parent}"/> <child link="standoff_2in_${number}_link" /> </joint> <link name="standoff_2in_${number}_link"> <inertial> <mass value="0.001" /> <origin xyz="0 0 0" /> <inertia ixx="0.0001" ixy="0.0" ixz="0.0" iyy="0.0001" iyz="0.0" izz="0.0001" /> </inertial> <visual> <origin xyz=" 0 0 0 " rpy="0 0 0" /> <geometry> <box size="0.01 0.01 0.07" /> </geometry> <material name="black"> <color rgba="0.16 0.17 0.15 0.9"/> </material> </visual> <collision> <origin xyz="0.0 0.0 0.0" rpy="0 0 0" /> <geometry> <box size="0.01 0.01 0.07" /> </geometry> </collision> </link> </xacro:macro> <xacro:macro name="mrobot_body"> <material name="Green"> <color rgba="0.0 0.8 0.0 1.0"/> </material> <material name="yellow"> <color rgba="1 0.4 0 1"/> </material> <material name="black"> <color rgba="0 0 0 0.95"/> </material> <material name="gray"> <color rgba="0.75 0.75 0.75 1"/> </material> <link name="base_footprint"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <box size="0.001 0.001 0.001" /> </geometry> </visual> </link> <link name="base_link"> <inertial> <mass value="2" /> <origin xyz="0 0 0.0" /> <inertia ixx="0.01" ixy="0.0" ixz="0.0" iyy="0.01" iyz="0.0" izz="0.5" /> </inertial> <visual> <origin xyz=" 0 0 0" rpy="0 0 0" /> <geometry> <cylinder length="${base_link_length}" radius="${base_link_radius}"/> </geometry> <material name="yellow" /> </visual> <collision> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <cylinder length="${base_link_length}" radius="${base_link_radius}"/> </geometry> </collision> </link> <joint name="base_footprint_joint" type="fixed"> <origin xyz="0 0 ${wheel_radius}" rpy="0 0 0" /> <parent link="base_footprint"/> <child link="base_link" /> </joint> <link name="left_motor"> <inertial> <origin xyz="0.0 0 0"/> <mass value="0.1" /> <inertia ixx="0.001" ixy="0.0" ixz="0.0" iyy="0.001" iyz="0.0" izz="0.001" /> </inertial> <visual> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${motor_radius}" length = "${motor_length}"/> </geometry> <material name="gray" /> </visual> <collision> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${motor_radius}" length = "${motor_length}"/> </geometry> </collision> </link> <joint name="base_left_motor_joint" type="fixed"> <origin xyz="${motor_x} ${motor_y} 0" rpy="0 0 0" /> <parent link="base_link"/> <child link="left_motor" /> </joint> <link name="left_wheel_link"> <inertial> <origin xyz="0 0 0"/> <mass value="0.01" /> <inertia ixx="0.001" ixy="0.0" ixz="0.0" iyy="0.001" iyz="0.0" izz="0.001" /> </inertial> <visual> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${wheel_radius}" length = "${wheel_length}"/> </geometry> <material name="white"> <color rgba="1 1 1 0.9"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${wheel_radius}" length = "${wheel_length}"/> </geometry> </collision> </link> <joint name="left_wheel_joint" type="continuous"> <origin xyz="0 ${(motor_length+wheel_length)/2} 0" rpy="0 0 0"/> <parent link="left_motor"/> <child link="left_wheel_link"/> <axis xyz="0 1 0"/> </joint> <link name="right_motor"> <inertial> <origin xyz="0.0 0 0"/> <mass value="0.1" /> <inertia ixx="0.001" ixy="0.0" ixz="0.0" iyy="0.001" iyz="0.0" izz="0.001" /> </inertial> <visual> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${motor_radius}" length = "${motor_length}" /> </geometry> <material name="gray" /> </visual> <collision> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${motor_radius}" length = "${motor_length}"/> </geometry> </collision> </link> <joint name="base_right_motor_joint" type="fixed"> <origin xyz="${motor_x} -${motor_y} 0" rpy="0 0 0" /> <parent link="base_link"/> <child link="right_motor" /> </joint> <link name="right_wheel_link"> <inertial> <origin xyz="0 0 0"/> <mass value="0.01" /> <inertia ixx="0.001" ixy="0.0" ixz="0.0" iyy="0.001" iyz="0.0" izz="0.001" /> </inertial> <visual> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${wheel_radius}" length = "${wheel_length}"/> </geometry> <material name="white"> <color rgba="1 1 1 0.9"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" /> <geometry> <cylinder radius="${wheel_radius}" length = "${wheel_length}"/> </geometry> </collision> </link> <joint name="right_wheel_joint" type="continuous"> <origin xyz="0 -${(motor_length+wheel_length)/2} 0" rpy="0 0 0"/> <parent link="right_motor"/> <child link="right_wheel_link"/> <axis xyz="0 1 0"/> </joint> <link name="front_caster_link"> <inertial> <origin xyz="0 0 0"/> <mass value="0.001" /> <inertia ixx="0.0001" ixy="0.0" ixz="0.0" iyy="0.0001" iyz="0.0" izz="0.0001" /> </inertial> <visual> <origin xyz="0 0 0" rpy="${M_PI/2} 0 0"/> <geometry> <sphere radius="${wheel_radius/2}" /> </geometry> <material name="black" /> </visual> <collision> <origin xyz="0 0 0.01" rpy="${M_PI/2} 0 0" /> <geometry> <sphere radius="${wheel_radius/2}" /> </geometry> </collision> </link> <joint name="front_caster_joint" type="fixed"> <origin xyz="${base_link_radius-wheel_radius/2} 0 -${wheel_radius/2}" rpy="0 0 0"/> <parent link="base_link"/> <child link="front_caster_link"/> </joint> <mrobot_standoff_2in parent="base_link" number="1" x_loc="-${standoff_x/2 + 0.03}" y_loc="-${standoff_y - 0.03}" z_loc="${plate_height/2}"/> <mrobot_standoff_2in parent="base_link" number="2" x_loc="-${standoff_x/2 + 0.03}" y_loc="${standoff_y - 0.03}" z_loc="${plate_height/2}"/> <mrobot_standoff_2in parent="base_link" number="3" x_loc="${standoff_x/2}" y_loc="-${standoff_y}" z_loc="${plate_height/2}"/> <mrobot_standoff_2in parent="base_link" number="4" x_loc="${standoff_x/2}" y_loc="${standoff_y}" z_loc="${plate_height/2}"/> <joint name="plate_1_joint" type="fixed"> <origin xyz="0 0 ${plate_height}" rpy="0 0 0" /> <parent link="base_link"/> <child link="plate_1_link" /> </joint> <link name="plate_1_link"> <inertial> <mass value="0.1" /> <origin xyz="0 0 0" /> <inertia ixx="0.01" ixy="0.0" ixz="0.0" iyy="0.01" iyz="0.0" izz="0.01" /> </inertial> <visual> <origin xyz=" 0 0 0 " rpy="0 0 0" /> <geometry> <cylinder length="${base_link_length}" radius="${base_link_radius}"/> </geometry> <material name="yellow"/> </visual> <collision> <origin xyz="0.0 0.0 0.0" rpy="0 0 0" /> <geometry> <cylinder length="${base_link_length}" radius="${base_link_radius}"/> </geometry> </collision> </link> <mrobot_standoff_2in parent="standoff_2in_1_link" number="5" x_loc="0" y_loc="0" z_loc="${plate_height}"/> <mrobot_standoff_2in parent="standoff_2in_2_link" number="6" x_loc="0" y_loc="0" z_loc="${plate_height}"/> <mrobot_standoff_2in parent="standoff_2in_3_link" number="7" x_loc="0" y_loc="0" z_loc="${plate_height}"/> <mrobot_standoff_2in parent="standoff_2in_4_link" number="8" x_loc="0" y_loc="0" z_loc="${plate_height}"/> <joint name="plate_2_joint" type="fixed"> <origin xyz="0 0 ${plate_height}" rpy="0 0 0" /> <parent link="plate_1_link"/> <child link="plate_2_link" /> </joint> <link name="plate_2_link"> <inertial> <mass value="0.01" /> <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> <visual> <origin xyz=" 0 0 0 " rpy="0 0 0" /> <geometry> <cylinder length="${base_link_length}" radius="${base_link_radius}"/> </geometry> <material name="yellow" /> </visual> <collision> <origin xyz="0.0 0.0 0.0" rpy="0 0 0" /> <geometry> <cylinder length="${base_link_length}" radius="${base_link_radius}"/> </geometry> </collision> </link> </xacro:macro> </robot>

    代码很长,下面开始解释

    <?xml version="1.0" ?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro">

    首先需要声明该文件使用XML描述,然后使用< robot>根标签定义一个机器人模型。 < robot>是完整机器人模型的最顶层标签,和标签都必须包含在标签内。 xacro是URDF的升级版,模型文件的后缀名由.urdf变为.xacro,而 且在模型标签中需要加入xacro的声明

    <xacro:property name="M_PI" value="3.14159"/>

    这是xacro提供了一种常量属性的定义方式,常量名字M_PI,值为3.14159 下面是M_PI常量调用方法

    <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" />

    下面是使用宏定义来声明MRobot本体的代码块,这样重复使用

    <xacro:macro name="mrobot_standoff_2in" params="parent number x_loc y_loc z_loc">

    以上宏定义的名字为mrobot_standoff_2in,params="parent number x_loc y_loc z_loc"中包含五个输入参数:joint的parent link,支撑柱的序号,支撑柱在x、y、z三个方向上的偏移。 需要该宏模块时,使用如下语句调用,设置输入参数即可:

    <mrobot_standoff_2in parent="base_link" number="1" x_loc="-${standoff_x/2 + 0.03}" y_loc="-${standoff_y - 0.03}" z_loc="${plate_height/2}"/>

    接着需要定义parent(这里是参数,需要传入具体的值,比如一个底板或者柱子之类的)和柱子之间的joint,joint的类型是fixed型,即固定关节,不允许运动。

    <origin xyz="${x_loc} ${y_loc} ${z_loc}" rpy="0 0 0" />

    位置标签:,xyz为空间位置,rpy是方位角roll、pitch、yaw。< origin>标签定义了joint的起点,即安装位置,xyz是坐标位置,rpy是角度,如 rpy=“1.5707 0 0” 表示围绕x轴旋转90°(使用弧度表示大约为1.5707)。

    <link name="standoff_2in_${number}_link"> <inertial> <mass value="0.001" /> <origin xyz="0 0 0" /> <inertia ixx="0.0001" ixy="0.0" ixz="0.0" iyy="0.0001" iyz="0.0" izz="0.0001" /> </inertial> <visual> <origin xyz=" 0 0 0 " rpy="0 0 0" /> <geometry> <box size="0.01 0.01 0.07" /> </geometry> <material name="black"> <color rgba="0.16 0.17 0.15 0.9"/> </material> </visual> <collision> <origin xyz="0.0 0.0 0.0" rpy="0 0 0" /> <geometry> <box size="0.01 0.01 0.07" /> </geometry> </collision> </link>

    < link>标签用于描述机器人某个刚体部分的外观和物理属性,包括尺寸(size)、颜色(color)、形状(shape)、惯性矩阵(inertial matrix)、碰撞参数(collision properties)等。

    <mass value="0.001" />

    这里mass代表质量, 以 kg 为单位。参考官网 参考博客

    < visual>标签用于描述机器人link部分的外观参数,< inertial>标签用于描述link的惯性参数,而< collision>标签用于描述link的碰撞属性。从下图可以看到,检测碰撞的link区域大于外观可视的区域,这就意味着只要有其他物体与collision区域相交,就认为link发生碰撞。

    <inertia ixx="0.0001" ixy="0.0" ixz="0.0" iyy="0.0001" iyz="0.0" izz="0.0001" />

    这是3x3转动惯量矩阵由惯量元素指定。因为这是对称的,所以只能用6个元素来表示。也出自:ROS学习–第11篇:ROS机器人建模与仿真—向URDF模型添加 物理属性 和 碰撞属性

    <geometry> <box size="0.01 0.01 0.07" /> </geometry>

    暂时没有在网上直接查到,但是从《ROS机器人开发实践》这本书里可以找到间接的答案,geometry是几何的意思,那么这三行代码就是定义一个几何体,几何体是个方块box,长宽高是0.01m,0.01m,0.07m。如果我这里没理解对,请留言纠正。

    <material name="black"> <color rgba="0.16 0.17 0.15 0.9"/> </material>

    通过material参数设置外观颜色

    写launch文件

    文件名:display_mrobot_with_kinect.launch

    <launch> <arg name="model" default="$(find xacro)/xacro --inorder '$(find mrobot_description)/urdf/mrobot_with_kinect.urdf.xacro'" /> <arg name="gui" default="true" /> <param name="robot_description" command="$(arg model)" /> <!-- 设置GUI参数,显示关节控制插件 --> <param name="use_gui" value="$(arg gui)"/> <!-- 运行joint_state_publisher节点,发布机器人的关节状态 --> <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" /> <!-- 运行robot_state_publisher节点,发布tf --> <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" /> <!-- 运行rviz可视化界面 --> <node name="rviz" pkg="rviz" type="rviz" args="-d $(find mrobot_description)/config/mrobot.rviz" required="true" /> <arg name="model" default="$(find xacro)/xacro --inorder '$(find mrobot_description)/urdf/mrobot_with_kinect.urdf.xacro'" />

    1,从指定包中加载urdf文件

    < arg> 类似于launch文件内部的局部变量,仅限于launch文件使用,便于launch文件的重构,与ROS节点内部的实现没有关系。

    参数: 这里中的name声明一个参数model, 默认值是一个地址,mrobot_with_kinect.urdf.xacro这个文件的位置。

    <arg name="gui" default="true" />

    声明一个参数gui,默认值为true

    <param name="robot_description" command="$(arg model)" />

    parameter是ROS系统运行中的参数,存储在参数服务器中。在launch文件中通过元素加载parameter;launch文件执行后,parameter就加载到ROS的参数服务器上了。 运行launch文件后,robot_description这个command的位置就设置为$(arg model)。网上关于command的解析几乎没有,如果有发现伙伴,留言讨论,然后我对此处进行补充。

    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />

    启动文件的核心是启动ROS节点,采用标签定义。 name属性用来定义节点运行的名称,将覆盖节点中init()赋予节点的名称。pkg定义节点所在的功能包名称。type定义节点的可执行文件名称,这两个属性等同于在终端中使用rosrun命令执行节点时的输入参数。

    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find mrobot_description)/config/mrobot.rviz" required="true" />

    args="…":节点需要的输入参数。 required=“true”:必要节点,当该节点终止时,launch文件中的其 他节点也被终止。

    mrobot_with_kinect.urdf.xacro

    Processed: 0.022, SQL: 9