Feng-DDXY / blogs

个人博客 Personal blog(Mainly used for recording and backing up)
0 stars 0 forks source link

ROS建模仿真(一):使用URDF创建机器人模型并连接摄像头;配置launch文件;Arbotix发布话题控制小车移动 #2

Open Feng-DDXY opened 1 week ago

Feng-DDXY commented 1 week ago

使用版本:Ubuntu 16.04 ROS Kinetic(已安装)

机器人系统仿真是通过计算机对实体机器人系统进行模拟

在 ROS 中分别表现为

  1. 对机器人建模(URDF)
  2. 创建仿真环境(Gazebo)
  3. 感知环境(Rviz)等系统性实现。

URDF直译为统一(标准化)机器人描述格式,以 XML 方式描述机器人的部分结构,比如底盘,机械臂以及不同关节的自由度,且XML文件可以被 C++ 内置的解释器转换成可视化的机器人模型,URDF 不能单独使用,需要结合 Rviz或 Gazebo,前面在ROS编程基础(五)中已经安装完Rviz,本篇中直接使用

使用URDF创建长方体机器人模型

以下步骤自行完成(仅附终端命令) 1.在已有工作空间下创建功能包my_robot 2.导入urdf和xacro作为该功能包的依赖项

catkin_create_pkg my_robot std_msgs roscpp rospy urdf xacro
cd ~/catkin_ws
catkin_make
source devel/setup.bash   //添加环境变量

在my_robot文件夹路径下新建4个文件夹,规范化管理文件:

mkdir urdf meshes config launch

删除文件夹:(放在这万一路径新建错了记得删一下)

rm -r urdf meshes config launch

image-20241119152459478

编写URDF文件

在urdf文件夹下创建 URDF 文件

cd ./urdf
touch test_urdf.urdf

在test_urdf.urdf文件内输入以下内容:

<?xml version="1.0"?>
<robot name="red_box">
  <link name="base_link">
    <visual>
      <geometry>
        <box size="1 0.5 0.2"/> <!-- 长方体尺寸 (长宽高) -->
      </geometry>
      <material name="red">
        <color rgba="1 0 0 1"/> <!-- RGBA 模式 红色 完全不透明-->
      </material>
    </visual>
    <collision>
      <geometry>
        <box size="1 0.5 0.2"/>
      </geometry>
    </collision>
    <inertial>
      <mass value="1.0"/> <!-- 连杆质量 1.0 千克-->
      <origin xyz="0 0 0"/> <!-- 连杆惯性坐标系的原点位置-->
      <inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/> <!-- 连杆的惯性矩阵-->
    </inertial>
  </link>
</robot>

代码解释:

<visual>:定义了机器人的可视化部分

<geometry>:指定几何形状,在这里是一个长方体

<collision>:定义机器人与环境发生碰撞时的几何形状。该代码中碰撞体积与可视化部分相同,都是一个尺寸为 1 x 0.5 x 0.2 的长方体

<inertial>:定义机器人连杆的惯性属性


加载URDF文件到参数服务器

在两个终端中输入以下命令:(第二行命令要在urdf路径下)

roscore
rosparam load test_urdf.urdf /robot_description

可以使用以下命令检测第二行命令是否生效:

rosparam get /robot_description

如果命令输出了 URDF 文件的内容,说明文件已成功加载,如下所示:

image-20241119160457000

在 Rviz 中显示机器人模型

在终端中输入以下命令打开rviz

rviz

rviz默认情况下没有添加机器人显示组件,需要手动添加,如下操作:

  1. 在 RViz 界面左下角,点击 "Add" 按钮。
  2. 选择 "RobotModel" 插件并点击 "OK"
  3. 在左侧显示面板中,展开 "RobotModel",将 "Description Topic" 设置为 /robot_description

image-20241119160629837

image-20241119161022390

但是图中是白色的长方形,是因为Global Options里面的Fixed Frame默认值是map,通常用于机器人在地图中的定位和路径规划,将该参数修改成base_link,直接显示与 base_link 相关的模型数据

如下所示:

image-20241119161652617

image-20241119161710413

在长方形机器人模型前加摄像头,并使用launch文件加载

将刚刚的urdf文件进行修改,替换成以下代码:

<?xml version="1.0"?>
<robot name="mycar">
    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.5 0.2 0.1" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="blue">
                <color rgba="0 0 1.0 0.5" />
            </material>
        </visual>
    </link>

    <link name="camera">
        <visual>
            <geometry>
                <box size="0.02 0.05 0.05" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="red">
                <color rgba="1 0 0 0.5" />
            </material>
        </visual>
    </link>

    <joint name="camera2baselink" type="continuous">
        <parent link="base_link"/>
        <child link="camera" />
        <origin xyz="0.25 0 0.075" rpy="0 0 0" />
        <axis xyz="0 0 1" />
    </joint>

</robot>

代码解释:

底盘 (base_link) 是机器人的主要框架,形状为一个矩形盒子,表示机器人的车身

摄像头 (camera) 小矩形盒子,0.02 米 x 0.05 米 x 0.05 米

关节 (camera2baselink) 通过 joint 标签将摄像头连接到底盘,通过一个continuous旋转关节来在整个范围内允许旋转


link 定义机器人组件的基本元素,每个 link 都可以包含视觉、碰撞和物理属性

<origin xyz="0 0 0" rpy="0 0 0" /> 位置相对于自身链接的原点,且没有旋转

origin xyz="0.25 0 0.1" 表示该关节的位置。也就是说,摄像头相对于底盘的位置是在 x 轴方向偏移 0.25 米,z 轴方向偏移 0.1 米

axis xyz="0 0 1" 定义了关节旋转的轴,这里表示关节沿 z 轴(垂直方向)旋转


修改代码后在终端中输入以下命令将 URDF 文件载入到 ROS 参数服务器 (要在roscore开着的情况下)

rosparam load test_urdf.urdf /robot_description

进入 launch 文件夹创建launch脚本:

cd ~/catkin_ws/src/my_robot/launch
gedit robot_launch.launch

在launch文件中编写以下内容:

<launch>
    <!-- 加载 URDF 文件到参数服务器 -->
    <param name="robot_description" textfile="$(find my_robot)/urdf/test_urdf.urdf" />

    <!-- 启动 RViz,加载自定义配置文件 -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find my_robot)/config/robot_config.rviz" />

    <!-- 启动关节状态发布器 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />

    <!-- 启动机器人状态发布器 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />

    <!-- 可选: 启动 GUI 控制关节状态发布的节点 -->
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
</launch>

安装joint_state_publisher_gui

我的环境直接运行以上代码的时候会遇到报错:[ERROR] [1584370263.037038]: Could not find the GUI, install the 'joint_state_publisher_gui' package

原因是joint_state_publisher_gui 包没有安装,输入以下命令进行安装即可:

sudo apt-get install ros-kinetic-joint-state-publisher-gui

运行launch节点

通过文件的绝对路径运行launch命令:

roslaunch ~/catkin_ws/src/my_robot/launch/robot_launch.launch

因为我通过功能包 运行失败,不知道为什么,失败代码也在这里放出来:

roslaunch my_robot launch/robot_launch.launch

这里省去刚刚导入RobotModel和修改Fixed Frame的步骤,自行完成

可以转动joint_state的滑条看红色摄像头疯狂旋转

效果如下:image-20241119165419450

优化 rviz 启动(这个操作我没有试)

重复启动launch文件时,Rviz 之前的组件配置信息不会自动保存,需要重复执行导入的操作,为了方便使用,可以使用如下方式优化:

首先,将当前配置保存进config目录

img

然后,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>

再启动时,就可以包含之前的组件配置了,使用更方便快捷。

使用URDF创建小车底盘模型

本篇在ROS建模仿真(一)的基础上,请确保已经完成之前步骤

以下步骤自行完成(仅附终端命令) 1.在已有工作空间下创建功能包my_robot 2.导入urdf和xacro作为该功能包的依赖项

catkin_create_pkg my_robot std_msgs roscpp rospy urdf xacro
cd ~/catkin_ws
catkin_make
source devel/setup.bash   //添加环境变量

编写URDF文件

在test_urdf.urdf文件内输入以下内容:(这里沿用上一篇的文件,只修改代码)

<?xml version="1.0"?>
<robot name="mycar">

    <link name="base_footprint">
        <visual>
            <geometry>
                <sphere radius="0.001" />
            </geometry>
        </visual>
    </link>

    <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>

    <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>

    <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>

修改代码后在终端中输入以下命令将 URDF 文件载入到 ROS 参数服务器 (要在roscore开着的情况下)

rosparam load test_urdf.urdf /robot_description

进入 launch 文件夹修改launch脚本内容:

cd ~/catkin_ws/src/my_robot/launch
gedit robot_launch.launch

在launch文件中编写以下内容:

<launch>
    <!-- 将 urdf 文件内容设置进参数服务器 -->
    <param name="robot_description" textfile="$(find my_robot)/urdf/test_urdf.urdf" />

    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find my_robot)/config/helloworld.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>

通过文件的绝对路径运行launch命令:

roslaunch ~/catkin_ws/src/my_robot/launch/robot_launch.launch

效果如下:

image-20241119175814667

使用Arbotix发布话题控制小车移动

Arbotix:Arbotix 是一款控制电机、舵机的控制板,并提供相应的 ros 功能包。该功能包不仅可以驱动真实的 Arbotix 控制板,它还提供一个差速控制器,通过接受速度控制指令更新机器人的 joint 状态,从而帮助我们实现机器人在 rviz 中的运动。

安装 Arbotix

sudo apt-get install ros-kinetic-arbotix

添加 arbotix 所需的配置文件

进入config 文件夹创建一个 YAML 文件:arbotix_controllers.yaml

cd ~/catkin_ws/src/my_robot/config
gedit arbotix_controllers.yaml

在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 
    }
}

将之前的launch修改成以下内容:

即在launch 文件中配置 arbotix 节点

<launch>
    <!-- 将 urdf 文件内容设置进参数服务器 -->
    <param name="robot_description" textfile="$(find my_robot)/urdf/test_urdf.urdf" />

    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find my_robot)/config/helloworld.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" />

    <!-- 添加 arbotix 节点,加载配置文件并设置参数 -->
    <node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
        <!-- 加载配置文件 -->
        <rosparam file="$(find my_robot)/config/arbotix_controllers.yaml" command="load" />
        <!-- 设置模拟模式参数 -->
        <param name="sim" value="true" />
    </node>
</launch>

代码解释:

调用了 arbotix_python 功能包下的 arbotix_driver 节点 arbotix 驱动机器人运行时,需要获取机器人信息,可以通过 file 加载配置文件 在仿真环境下,需要配置 sim 为 true ------ 通过文件的绝对路径运行launch命令: ```bash roslaunch ~/catkin_ws/src/my_robot/launch/robot_launch.launch ``` 将Fixed Frame里面修改成odom: ![image-20241119185300410](https://raw.githubusercontent.com/Feng-DDXY/img_cloud/main/202411191929209.png) 此时调用 rostopic list 会发现/cmd_vel话题: 一旦启动了 Arbotix 节点和相关的配置(即roslaunch),`arbotix_driver` 节点会自动创建并监听 `cmd_vel` 话题,我们只需要通过发布消息到该话题,机器人就能收到控制指令 ![image-20241119185405376](https://raw.githubusercontent.com/Feng-DDXY/img_cloud/main/202411191929211.png) **可以在RViz里导入TF和Odometry查看运动效果**(Odometry的Topic设置为/odom可以看到如图红色箭头) ------ 在终端输入以下指令可以发布小车进行圆周行驶/键盘控制 的控制指令 1.圆周运动 ```bash 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}}' ``` ![image-20241119185933113](https://raw.githubusercontent.com/Feng-DDXY/img_cloud/main/202411191929212.png) 2.键盘操作的任意运动**(!!!注:这个命令需要安装teleop_twist_keyboard包 安装指令在后面)** ```bash rosrun teleop_twist_keyboard teleop_twist_keyboard.py ``` ![image-20241119190625893](https://raw.githubusercontent.com/Feng-DDXY/img_cloud/main/202411191929213.png) #### 安装teleop_twist_keyboard包 你可以使用以下命令安装 `teleop_twist_keyboard` 包: ```bash sudo apt-get install ros-kinetic-teleop-twist-keyboard ``` ```bash cd ~/catkin_ws catkin_make ```