• ROS仿真软件Turtlebot-Gazebo的安装使用以及错误处理[机器人避障]


            很多时候由于机器人价格比较贵,而且会因为环境因素、操作失误或者摔坏等,所以我们可以先在仿真软件上做测试,也可以避免这些问题,虽然没有那么真实感,可毕竟是免费的嘛。我们可以在这些仿真的机器人身上去学习如何控制机器人,读取它们的传感器数据,解析这些传感器数据并做出决策,通过前面我们学到的话题、服务、动作来驱动机器人。

    1、操作仿真机器人

    1.1、安装仿真软件

    这里主要介绍turtlebot-gazebo的安装以及在这个过程中遇到的一些问题,主要是版本问题
    安装命令如下

    sudo apt-get install ros-indigo-turtlebot-gazebo

    如果出现错误:

    E: Unable to locate package ros-indigo-turtlebot-gazebo

    这种安装出错的原因是Ubuntu的版本问题,比如本人的是Ubuntu 18.04版本,所以需要将indigo修改为melodic,这个在前面的文章也有介绍:Ubuntu18.04版本安装ROS及出现错误的处理方法

    所以在安装之前,先查看自己的OS版本:uname -v 

    修改之后,执行命令

    sudo apt-get install ros-melodic-turtlebot-gazebo

    不出意外的情况,将依然报错

    E: Unable to locate package ros-melodic-turtlebot-gazebo

    这个时候我们可以双击tab键来让其补全或出现可用的列表,因为很大程度上可能是输入的名称有误或者升级之后的名称有变化等,这种小技巧出了确保正确之外,还可以提高你的输入效率。 

    输入:sudo apt-get install ros-melodic-turtlebot,将自动补全为turtlebot3,继续双击tab键,将出现的正确的提示:sudo apt-get install ros-melodic-turtlebot3-gazebo

    从这里可以看到,turtlebot-gazebo版本已更新到了turtlebot3-gazebo,丢弃了以前的名称。 

    当然这里的情况不一定就适合大家,只能说出现错误,一般就是这个名称有误的问题,这个时候就使用双击Tab键来正确提示!!

    1.2、一些错误处理

    安装好了之后,我们来启动仿真软件

    roslaunch turtlebot3_gazebo turtlebot3_world.launch

    出现如下错误:

    ... logging to /home/yahboom/.ros/log/23567ca0-54f7-11ee-91f8-000c294b0b84/roslaunch-YAB-3881.log
    Checking log directory for disk usage. This may take a while.
    Press Ctrl-C to interrupt
    Done checking log file disk usage. Usage is <1GB.

    RLException: Invalid tag: environment variable 'TURTLEBOT3_MODEL' is not set. 

    Arg xml is
    The traceback for the exception was written to the log file

    从错误信息来看,这里有两个问题,一个是磁盘空间小了,日志文件需要超过1GB的容量;另一个问题是arg这个标签的问题,没有设置TURTLEBOT3_MODEL环境变量。
    清理日志:

    1. rosclean purge
    2. rosclean check

    设置环境变量:

    export TURTLEBOT3_MODEL=burger

    这里就是选定一个机器人,这里就选burger吧,还有一个waffle,大家可以试下

    查看环境变量:

    export [-p]

    然后再次执行:roslaunch turtlebot3_gazebo turtlebot3_world.launch

    当然这种环境变量的更改是临时的,推荐使用下面方法让其永久生效:

    1. echo "export TURTLEBOT3_MODEL=burger" >> ~/.bashrc
    2. source ~/.bashrc

    再次启动,仿真软件的界面在初始化的时候,突然就出现下面这样的错误然后终止了:

    log file: /home/yahboom/.ros/log/558bb39a-5509-11ee-86fb-000c294b0b84/spawn_urdf-4*.log
    [Err] [REST.cc:205] Error in REST request

    libcurl: (51) SSL: no alternative certificate subject name matches target host name 'api.ignitionfuel.org'
    VMware: vmw_ioctl_command error Invalid argument.
    Aborted (core dumped)
    [gazebo_gui-3] process has died [pid 2350, exit code 134, cmd /opt/ros/melodic/lib/gazebo_ros/gzclient __name:=gazebo_gui __log:=/home/yahboom/.ros/log/558bb39a-5509-11ee-86fb-000c294b0b84/gazebo_gui-3.log].
    log file: /home/yahboom/.ros/log/558bb39a-5509-11ee-86fb-000c294b0b84/gazebo_gui-3*.log

    错误的意思是没有证书与这个主机名匹配,实质原因是主机名变更了,所以我们修改配置文件,修改如下:

    gedit ~/.ignition/fuel/config.yaml

    将里面的

    url: https://api.ignitionfuel.org

    修改为

    url: https://fuel.ignitionrobotics.org 

    还需要追加一个环境变量,解决VMware: vmw_ioctl_command error Invalid argument.这个错误问题

    1. echo "export SVGA_VGPU10=0" >> ~/.bashrc
    2. source ~/.bashrc

    再次启动:roslaunch turtlebot3_gazebo turtlebot3_world.launch

    当然上面是带障碍物的场景,也可以是空地图的场景:

    roslaunch turtlebot3_gazebo turtlebot3_empty_world.launch

    还有很多其余地图,同样双击tab键可以看到:roslaunch turtlebot3_gazebo

    multi_map_merge.launch              turtlebot3_house.launch
    multi_turtlebot3.launch             turtlebot3_simulation.launch
    multi_turtlebot3_slam.launch        turtlebot3_stage_1.launch
    turtlebot3_autorace_2020.launch     turtlebot3_stage_2.launch
    turtlebot3_autorace.launch          turtlebot3_stage_3.launch
    turtlebot3_autorace_mission.launch  turtlebot3_stage_4.launch
    turtlebot3_empty_world.launch       turtlebot3_world.launch
    turtlebot3_gazebo_rviz.launch

    1.3、 操作机器人

    我们可以直接通过命令行发送话题来操作里面的机器人,那么这个话题与类型又是怎么知道的呢?我们可以通过前面的知识来理解
    首先查看话题列表:rostopic list

    /clock
    /cmd_vel
    /gazebo/link_states
    /gazebo/model_states
    /gazebo/parameter_descriptions
    /gazebo/parameter_updates
    /gazebo/set_link_state
    /gazebo/set_model_state
    /imu
    /joint_states
    /odom
    /rosout
    /rosout_agg
    /scan
    /tf

    这里可以看到主要是关于gazebo的话题,以及一些惯性测量单元IMU,关节话题等,里面的数据类型很多都属于传感器定义的类型。
    我们查看其中的/cmd_vel信息:rostopic info /cmd_vel

    Type: geometry_msgs/Twist

    Publishers: None

    Subscribers: 
     * /gazebo (http://YAB:38191/)

    发送消息的数据类型是geometry_msgs/Twist,然后我们可以继续查看这个类型的详细信息:rosmsg show geometry_msgs/Twist

    geometry_msgs/Vector3 linear
      float64 x
      float64 y
      float64 z
    geometry_msgs/Vector3 angular
      float64 x
      float64 y
      float64 z 

    可以看到是由两个向量组成,一个是线速度,另一个是角速度。
    有了这些之后,我们就可以通过输入命令,发布消息直接操作机器人:

    rostopic pub /cmd_vel geometry_msgs/Twist -- '[1.0, 0.0, 0.0]' '[0.0, 0.0, 0.0]'

    2、创建话题cmd_vel

    有了前面命令行操作机器人的知识铺垫,我们重新来定义一个话题,名称就是上面这个cmd_vel

    2.1、创建工作空间

    1. mkdir -p ~/mywanderbot_ws/src
    2. cd mywanderbot_ws/src
    3. catkin_init_workspace

     2.2、创建依赖包

    1. cd ~/mywanderbot_ws/src
    2. catkin_create_pkg mywanderbot rospy geometry_msgs sensor_msgs

    这样就创建好了一个mywanderbot包,以及让ROS构建系统需要知道的依赖包:rospy geometry_msgs sensor_msgs,这些依赖包是保证当依赖发生更改时,重新编译这个mywanderbot包到最新版本,以及在发布软件包时生成依赖。

    我们可以查看下里面的情况:ls ~/mywanderbot_ws/src/mywanderbot

    CMakeLists.txt  package.xml  src

    关于这块代码,更多详情,有兴趣的可以查阅:ROS新建工作区(workspace)与包(package)编译的实践(C++示例)

    2.3、自定义话题

    我们试着来做一个让机器人每隔三秒进行行驶和暂停的周期性切换,这里给出两个示例

    2.3.3、示例1
    1. cd ~/mywanderbot_ws/src/mywanderbot/src
    2. gedit red_green.py
    1. #!/usr/bin/env python
    2. import rospy
    3. from geometry_msgs.msg import Twist
    4. mycmd_vel_pub = rospy.Publisher('cmd_vel',Twist,queue_size=1)
    5. rospy.init_node('red_green')
    6. red_light_twist = Twist()
    7. green_light_twist = Twist()
    8. green_light_twist.linear.x = 0.5
    9. driving_forward = True
    10. rate = rospy.Rate(10)
    11. light_change_time=rospy.Time.now()
    12. while not rospy.is_shutdown():
    13. #print(light_change_time,rospy.Time.now())
    14. if light_change_time < rospy.Time.now():
    15. driving_forward = not driving_forward
    16. light_change_time= rospy.Time.now()+rospy.Duration(3)
    17. if driving_forward:
    18. mycmd_vel_pub.publish(green_light_twist)
    19. else:
    20. mycmd_vel_pub.publish(red_light_twist)
    21. rate.sleep()

    这个网上例子比较多,很多都是书上的原内容是错误的,原例内容是:
    if light_change_time > rospy.Time.now():
    这样的话,永远不会执行到这个位置也就不会做切换了,需要将>修改为<,一开始小,所以就当前时间加3秒,比当前时间大,这个时间段就是等待当前时间一直累加,累加到小于当前时间,再次切换,加3秒,继续等待......

    2.3.4、示例2
    1. cd ~/mywanderbot_ws/src/mywanderbot/src
    2. gedit red_green.py
    1. #!/usr/bin/env python
    2. import rospy
    3. from geometry_msgs.msg import Twist
    4. mycmd_vel_pub = rospy.Publisher('cmd_vel',Twist,queue_size=1)
    5. rospy.init_node('red_green')
    6. red_light_twist = Twist()
    7. green_light_twist = Twist()
    8. green_light_twist.linear.x = 0.5
    9. driving_forward = True
    10. rate = rospy.Rate(1)
    11. while not rospy.is_shutdown():
    12. if int(rospy.get_time()) % 3 == 0:
    13. driving_forward = not driving_forward
    14. #print(rospy.Time.now().to_sec(),int(rospy.get_time())%3,driving_forward)
    15. if driving_forward:
    16. mycmd_vel_pub.publish(green_light_twist)
    17. else:
    18. mycmd_vel_pub.publish(red_light_twist)
    19. rate.sleep()

    这种方式也不错,需要注意的是这里的频率不能是10了,需要每秒只发送一次,如果频率很快,试想下,在一秒钟里面进行取余会多次是一样的值,如果是0,那么会在这一秒钟内切换很多次,这肯定不可以。

    2.4、编译与执行

    添加可执行权限:chmod +x red_green.py

    1. cd ~/mywanderbot_ws
    2. catkin_make
    3. echo "source ~/mywanderbot_ws/devel/setup.bash" >> ~/.bashrc
    4. source ~/.bashrc

     执行上述节点:rosrun mywanderbot red_green.py

    可以看到机器人行驶了起来,也可以查看话题发布的输出信息:rostopic echo  cmd_vel

    linear: 
      x: 0.5
      y: 0.0
      z: 0.0
    angular: 
      x: 0.0
      y: 0.0
      z: 0.0
    ---
    linear: 
      x: 0.5
      y: 0.0
      z: 0.0
    angular: 
      x: 0.0
      y: 0.0
      z: 0.0

    2.5、rqt_graph

    我们除了使用rostopic info cmd_vel查看这个话题的类型,发布者和订阅者之外,还可以用到前面章节介绍的rqt_graph来查看
    发布的red_green节点通过cmd_vel话题,由gazebo机器人或其他订阅者订阅的关系图:

     

    3、避障测试

    我们打开的是带障碍物的地图,所以机器人遇到障碍物的时候会被迫停止,我们可以使用激光雷达LaserScan来测距,进行避障,这里用到实质是Turtlebot上的Kinect深度相机产生的数据。

    3.1、激光雷达LaserScan

    我们先来看下激光雷达的相关信息:

    scan话题:rostopic info scan

    Type: sensor_msgs/LaserScan

    Publishers: 
     * /gazebo (http://YAB:36357/)

    Subscribers: None

    可以看到类型是sensor_msgs/LaserScan

    查看sensor_msgs/LaserScan消息类型:rosmsg show sensor_msgs/LaserScan

    std_msgs/Header header
      uint32 seq
      time stamp
      string frame_id
    float32 angle_min
    float32 angle_max
    float32 angle_increment
    float32 time_increment
    float32 scan_time
    float32 range_min
    float32 range_max
    float32[] ranges
    float32[] intensities

    查看scan的输出信息:rostopic  echo scan  -n 1

     header: 
      seq: 1
      stamp: 
        secs: 2537
        nsecs: 462000000
      frame_id: "base_scan"
    angle_min: 0.0
    angle_max: 6.28318977356
    angle_increment: 0.0175019223243
    time_increment: 0.0
    scan_time: 0.0
    range_min: 0.119999997318
    range_max: 3.5
    ranges: [0.377697229385376, 0.38358184695243835, 0.3849789798259735, 0.4099400043487549, ...]
    intensities: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...]

    3.2、避障代码

    前面的机器人实现了行驶和暂停的功能,接下来使用激光扫描来测距,并进行避开测试。

    1. cd ~/mywanderbot_ws/src/mywanderbot/src
    2. gedit mybot.py
    1. #!/usr/bin/env python
    2. import rospy
    3. from geometry_msgs.msg import Twist
    4. from sensor_msgs.msg import LaserScan
    5. def scan_cb(msg):
    6. global g_range_ahead
    7. #g_range_ahead = msg.ranges[len(msg.ranges)/2]
    8. g_range_ahead = msg.ranges[0]
    9. print(g_range_ahead)
    10. g_range_ahead = 1
    11. cmd_vel_pub = rospy.Publisher('cmd_vel',Twist,queue_size=1)
    12. scan_sub = rospy.Subscriber('scan',LaserScan,scan_cb)
    13. rospy.init_node('mybot')
    14. state_change_time = rospy.Time.now() + rospy.Duration(30)
    15. driving_forward = True
    16. rate = rospy.Rate(10)
    17. while not rospy.is_shutdown():
    18. if driving_forward:
    19. if(g_range_ahead<0.8 or rospy.Time.now()>state_change_time):
    20. print(rospy.Time.now(),state_change_time)
    21. driving_forward = False
    22. state_change_time = rospy.Time.now() + rospy.Duration(5)
    23. else:
    24. if(g_range_ahead>0.8 or rospy.Time.now()>state_change_time):
    25. driving_forward = True
    26. state_change_time = rospy.Time.now() + rospy.Duration(30)
    27. twist = Twist()
    28. if deriving_forward:
    29. if g_range_ahead>0.8:
    30. twist.linear.z=0.0
    31. twist.linear.x=0.5
    32. else:
    33. twist.linear.x=-0.2
    34. twist.angular.z=0.5
    35. else:
    36. if g_range_ahead>0.8:
    37. twist.linear.z=0.5
    38. twist.linear.x=0.0
    39. else:
    40. twist.linear.x=-0.2
    41. twist.angular.z=0.5
    42. cmd_vel_pub.publish(twist)
    43. rate.sleep()

    加个执行权限:chmod +x mybot.py

    启动带障碍物的地图:roslaunch turtlebot3_gazebo turtlebot3_world.launch
    执行:rosrun mywanderbot mybot.py

    可以看到机器人在行驶中,遇到障碍物(小于0.8米)会进行避开,Nice~
    这里使用一个全局变量g_range_ahead来存储激光扫描器检测到的最小距离,这使得回调函数变得简单,直接复制最小距离到我们的全局变量中,当然对于复杂的程序来说,这是一种不好的习惯,影响性能。 

    查看下激光扫描:rostopic info scan

    Type: sensor_msgs/LaserScan

    Publishers: 
     * /gazebo (http://YAB:44733/)

    Subscribers: 
     * /mybot (http://YAB:37459/)

    可以看到订阅者就是我们定义的mybot机器人节点。
    也可以使用rqt_graph来查看下节点之间的关系,如下图: 

  • 相关阅读:
    owasp amass 子域名枚举神器 功能介绍
    javaBS景区票务管理系统设计与实现计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    大二数据结构实验(排序算法)
    shell脚本的函数
    利用Pycharm将python文件打包为exe文件
    Python函数装饰器的深入解析
    线性表-顺序表学习笔记(基础)
    centos7安装单机elasticsearch7.7.1
    python通过tkinter制作词云图工具
    k8s--基础--24.1--efk--介绍
  • 原文地址:https://blog.csdn.net/weixin_41896770/article/details/133759854