迷你无人车 Gazebo 仿真

迷你无人车 Gazebo 仿真

从零开始搭建一台ROS开源迷你无人车

利用NEOR mini无人车的urdf模型文件,结合Gazebo物理仿真引擎和ROS开源社区的算法功能包,在Ubuntu + ROS开发环境下模拟出一台和NEOR mini实体无人车功能一致的仿真无人车。实现的过程如下图所示:

在这里插入图片描述

从三维模型到URDF文件

URDF全称为:统一机器人描述格式(Unified Robot Description Format)。URDF文件使用XML格式描述机器人模型中各个刚体(link)之间的位置与刚体之间使用关节(joint)链接,并定义相对运动的姿态

可以通过xml格式自定义简单形状的URDF机器人模型;也可以使用sw_urdf_expoter插件将机器人的设计图纸自动转换为urdf文件,在这里使用的是第二种方式。NEOR mini是一款后轮独立驱动,前轮转向的类阿克曼运动学的移动底盘。使用sw_urdf_expoter之前需要将整个NEOR mini三维模型分成如下几大块:

robot name is: neor_mini                  解释(explanation)
root Link: base_linkhas 6 child(ren)          主体实体
    child(1): front_steer_link               前轮转向实体
    child(2): front_steer_left_link          左前轮转向机构实体
        child(1):  front_left_wheel_link     左前轮实体
    child(3): front_steer_right_link         右前轮转向机构实体
        child(1):  front_right_wheel_link    右前轮实体
    child(4): left_rear_link                 左后轮驱动实体
    child(5): rear_wheel_link                驱动实体
    child(6):  right_rear_link               右后轮驱动实体

然后,设置好每个实体的旋转轴,利用sw_urdf_expoter即可导出对应的urdf模型文件。在导出之前需要检查上述各个实体的名称,若相同,导出的urdf模型很有可能会出现凌乱的现象,需要重命名名字重复的实体。导出的urdf模型文件以ROS功能包的形式,其文件树和urdf模型可视化如下:

在这里插入图片描述

阿克曼运动学插件 steer-drive-ros

URDF模型文件离动起来还需要程序去驱动对应的关节和实体完成指定的转动。前面提到了NEOR mini是一款类阿克曼运动学方式的移动底盘。因此该驱动程序需要将接收到的速度指令,解算为mini的每个轮子的转速和转向关节的旋转角度;该转换过程称之为“运动学解算

在这里插入图片描述

同理根据实际的执行情况,可以从后左右轮的转速和前轮的转向角度逆推出后轮中点出的线角速度(v,w)。从而可以推算出无人车的航迹信息

💡 其实就是阿克曼运动学正逆解的过程

steer_drive_ros功能包集内置了阿克曼类型urdf在gazebo下的驱动程序steer_bot_hardware_gazebo以及完成正逆向运动学的解算程序steer_drive_controller;整个功能包集的运行过程如下图示(摘自 wiki):

在这里插入图片描述

修改urdf文件适配steer-drive-ros

紧接下来的目标是:参照steer_drive_controller解算程序对urdf模型的构造要求,修改neor_mini.urdf文件以符合要求,然后更新对应的配置文件信息(关节和实体名称)。根据官网的解释,该程序所支持的urdf模型构造和已有的neor_mini.urdf的构造分别如下左右图所示:

在这里插入图片描述

在这里插入图片描述

💡 这里暂时省略具体的修改过程

为了能够在gazebo中顺利加载修改后的urdf文件,需要在标签内加入gazebo_ros_control标签。内容如下:

<gazebo>
  <pluginname="gazebo_ros_control"filename="libgazebo_ros_control.so">
    <robotSimType>steer_bot_hardware_gazebo/SteerBotHardwareGazebo</robotSimType>
    <legacyModeNS>false</legacyModeNS>
  </plugin>
</gazebo>

至此,修改后的urdf文件已经具备被steer-drive-ros程序驱动,并在gazebo中运动的必备条件。随后需要的就是更新改程序的配置文件中的相关驱动关节和实体的名字,link 和 joint 如下

redwall@redwall-G3-3500:~/neor_mini/mini_sim18_ws/src/neor_mini/urdf$ check_urdf neor_mini_gazebo_sensors.urdf 
robot name is: neor_mini
---------- Successfully Parsed XML ---------------
root Link: base_link has 10 child(ren)
    child(1):  laser_link
    child(2):  laser_link2
    child(3):  camera_link
    child(4):  front_steer_link
    child(5):  front_steer_left_link
        child(1):  front_left_wheel_link
    child(6):  front_steer_right_link
        child(1):  front_right_wheel_link
    child(7):  imu_link
    child(8):  left_rear_link
    child(9):  rear_wheel_link
    child(10):  right_rear_link
roslaunch urdf_tutorial display.launch model:=./neor_mini_gazebo_sensors.urdf

在这里插入图片描述

rosrun tf2_tools view_frames

在这里插入图片描述

URDF在Gazebo中动起来

在前面所做准备的基础上,现在需要更新steer-drive-ros运行时加载的配置文件。根据该程序的参数在wiki中的解释1、2,将所有的参数分为4个配置文件(.yaml),如下:

ctrl_ackermann_steering_controller.yaml  for:   steer_drive_controller
ctrl_joint_state_publisher.yaml          for:   ros_controller
ctrl_gains.yaml                          for:  steer_bot_hardware_gazebo
ctrl_steer_bot_hardware_gazebo.yaml      for:   steer_bot_hardware_gazebo

为了方便管理,这里创建了一个ros 功能包,存储配置文件和程序启动的launch文件,以及使用package.xml管理程序运行所需的依赖包。创建的命令如下:

cd your_workspace/src
catkin_create steer_mini_gazebo roscpp

回车之后,其文件树如下:

.
├── CMakeLists.txt                #存储该功能包编译时的信息
├── include
│   └──  steer_mini_gazebo
├── package.xml                  # 存储依赖包名字
└── src                          # 存储源程序.cpp

此时,该功能包是不会被编译的,此时需要在steer_mini_gazebo/src目录下创建steer_mini_gazebo_node.cpp文件,并在该文件里面添加如下所示的源程序:

#include<ros/ros.h>
 int  main(int argc, char** argv)
{
      ros::init(argc, argv, "steer_mini_gazebo_node"); // 节点名称
      ros::NodeHandle nh;
      //.... 节点功能,此处没有功能,只是为了能够参与编译。
      ros::spin();//用于触发topic、service的响应队列
      return 0;
 }

修改steer_mini_gazebo/CMakeLists.txt 文件,去掉如下两条语句前的“#”注释

# add_executable(${PROJECT_NAME}_node  src/steer_mini_gazebo_node.cpp)
......
#target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
#)

steer_mini_gazebo可以被编译生成可执行程序节点。紧接着,需要在其中添加前面所述的四个配置文件和程序启动的launch文件。添加后的功能包文件树如下:

.
├── CMakeLists.txt
├── mini_control
│   └── config
│       ├──  ctrl_ackermann_steering_controller.yaml
│       ├── ctrl_gains.yaml
│       ├── ctrl_joint_state_publisher.yaml
│       └── ctrl_steer_bot_hardware_gazebo.yaml
├── mini_gazebo
│   └── launch
│       ├── steer_mini_sim.launch
│       └── steer_mini_sim_sensors.launch
├── package.xml
└── src
     └── steer_mini_gazebo_node.cpp

配置程序启动的steer_mini_sim.launch文件,内容如下:

<?xml version="1.0"?>
<launch>

    <arg name="x" default="0.0"/>
    <arg name="y" default="0.0"/>
    <arg name="z" default="0.0" />
    <arg name="roll" default="0.0"/>
    <arg name="pitch" default="0.0"/>
    <arg name="yaw" default="0.0"/>

    <!-- Gazebo  -->
    <!--Load the surrounding environment into Gazebo-->
    <include file="$(find gazebo_ros)/launch/empty_world.launch" >
        <arg name="world_name" value="$(find neor_mini)/worlds/cooneo_office.world"/>
    </include>

    <!-- Load the robot description -->
    <param name="robot_description" command="cat $(find neor_mini)/urdf/neor_mini_gazebo_sensors.urdf"/>

    <!-- Load ros_controllers configuration parameters -->
    <rosparam file="$(find steer_mini_gazebo)/mini_control/config/ctrl_ackermann_steering_controller.yaml" command="load"   />
    <rosparam file="$(find steer_mini_gazebo)/mini_control/config/ctrl_gains.yaml" command="load"   />
    <rosparam file="$(find steer_mini_gazebo)/mini_control/config/ctrl_joint_state_publisher.yaml" command="load"   />
    <rosparam file="$(find steer_mini_gazebo)/mini_control/config/ctrl_steer_bot_hardware_gazebo.yaml" command="load"   />

    <!-- Spawn the controllers -->
    <node pkg="controller_manager" type="spawner" name="controller_spawner"  args="joint_state_publisher ackermann_steering_controller" output="screen" respawn="false" />

    <!-- Launch  the robot state publisher -->
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher">
        <param name="publish_frequency" value="50.0"/>
    </node>

    <!-- Launch a rqt steering GUI for publishing to /steer_bot/steer_drive_controller/cmd_vel -->
    <node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering" >
        <param name="default_topic" value="ackermann_steering_controller/cmd_vel"/>                         <!-- default velocity control topic name -->
        <param name="default_vx_max" value="1.0"/>                        <!-- linear velocity max value    m/s -->
        <param name="default_vx_min" value="-1.0"/>                       <!-- linear velocity min value    m/s-->
        <param name="default_vw_max" value="0.69"/>                    <!-- angular velocity max value  rad/s (adaptor for urdf joint limit) -->
        <param name="default_vw_min" value="-0.69"/>                   <!-- angular velocity min value  rad/s (adaptor for urdf joint limit) -->
    </node> 

    <!--Start the Gazebo node and configure the location and posture of the accident when the model is loaded -->
    <node name="spawn_vehicle" pkg="gazebo_ros" type="spawn_model" args="-urdf -param robot_description -model neor_mini -gazebo_namespace /gazebo 
              -x $(arg x) -y $(arg y) -z $(arg z)
              -R $(arg roll) -P $(arg pitch) -Y $(arg yaw)"
          respawn="false" output="screen" />
    <!-- ******************************************************************************************************************************************* -->

   <node name="laser_to_base_link" pkg="tf" type="static_transform_publisher" args="0.0 0.0 0.135 0 0 0 base_link laser_link 40 " />
   <node name="imu_to_base_link" pkg="tf" type="static_transform_publisher" args="-0.10 0.0 0.02 0 0 0 base_link imu_link 40 " />
   <node name="camera_to_base_link" pkg="tf" type="static_transform_publisher" args="0.12 0.0 0.12 0 0 0 base_link camera_link 40 " />

</launch>

想要编译成功,还需要在steer_mini_gazebo/package.xml中将所需的依赖包添加进去:

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>ackermann_steering_controller</build_depend>
  <build_depend>controller_manager</build_depend>
  <build_depend>gazebo_ros</build_depend>
  <build_depend>gazebo_ros_control</build_depend>
  <build_depend>joint_state_controller</build_depend>
  <build_depend>robot_state_publisher</build_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>roslaunch</build_depend>
  <build_depend>rqt_robot_steering</build_depend>
  <build_depend>steer_bot_hardware_gazebo</build_depend>
  <build_depend>steer_drive_controller</build_depend>
  <build_export_depend>ackermann_steering_controller</build_export_depend>
  <build_export_depend>controller_manager</build_export_depend>
  <build_export_depend>gazebo_ros</build_export_depend>
  <build_export_depend>gazebo_ros_control</build_export_depend>
  <build_export_depend>joint_state_controller</build_export_depend>
  <build_export_depend>robot_state_publisher</build_export_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>roslaunch</build_export_depend>
  <build_export_depend>rqt_robot_steering</build_export_depend>
  <build_export_depend>steer_bot_hardware_gazebo</build_export_depend>
  <build_export_depend>steer_drive_controller</build_export_depend>
  <build_export_depend>ros_control</build_export_depend>
  <exec_depend>ackermann_steering_controller</exec_depend>
  <exec_depend>controller_manager</exec_depend>
  <exec_depend>gazebo_ros</exec_depend>
  <exec_depend>gazebo_ros_control</exec_depend>
  <exec_depend>joint_state_controller</exec_depend>
  <exec_depend>robot_state_publisher</exec_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>roslaunch</exec_depend>
  <exec_depend>rqt_robot_steering</exec_depend>
  <exec_depend>steer_bot_hardware_gazebo</exec_depend>
  <exec_depend>steer_drive_controller</exec_depend>
  <exec_depend>ros_control</exec_depend>

效果如下

在这里插入图片描述

可以看到目前对于迷你无人车的控制是通过 ROS 自带的 rqt steering GUI 实现,很不方便,尝试通过手柄进行控制

	<!-- Launch a rqt steering GUI for publishing to /steer_bot/steer_drive_controller/cmd_vel -->
    <node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering" >
        <param name="default_topic" value="ackermann_steering_controller/cmd_vel"/>                         <!-- default velocity control topic name -->
        <param name="default_vx_max" value="1.0"/>                        <!-- linear velocity max value    m/s -->
        <param name="default_vx_min" value="-1.0"/>                       <!-- linear velocity min value    m/s-->
        <param name="default_vw_max" value="0.69"/>                    <!-- angular velocity max value  rad/s (adaptor for urdf joint limit) -->
        <param name="default_vw_min" value="-0.69"/>                   <!-- angular velocity min value  rad/s (adaptor for urdf joint limit) -->
    </node> 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Prejudices

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值