move_base 控制机器人(1)

 本教程将具体涉及如下问题:

系列(1):move_base发出的控制指令是什么?该如何转化为移动机器人左右轮的速度。

系列(2):移动机器人的左右轮的编码器信息如何转化为ROS的/odom;

系列(3):navigation的几个坐标系(/map frame , /odom frame , /base_link frame)是什么,他们之间该如何建立tf转换;如何使用move_base在一个空白的地图(blank map)上完成对实际机器人的控制。

控制系统的架构:

关于机器人导航与定位的系统架构,这里按照自己的理解以及开发经验给出三个层次。

最底层:机器人本身的电机驱动部分,该部分通过串口接收电脑端输出的左右轮期望速度,对左右轮分别进行PID控速。同时,定时采样电机码盘值,并转化为左右轮速度值通过串口上传给电脑。当然PID控速这一部分也可以放到电脑ROS端,这样的话,电脑串口输出的是直接的PWM值而不是之前的期望速度了。

中间通信层:电脑端和底层电机的控制通信,以及将传感器信息发布给ROS的通信。这一层主要通过串口(ROS已经集成了pyserial 用python操作这个模块进行串口控制)收集左右轮速度值,用航迹推演法将左右轮速度转化为机器人的x轴方向速度和机器人的旋转速度,然后发布/odom主题,好让ROS的相应package收到这个消息,进行机器人位置的估计。同时,这一部分还要关注ROS相应部分发出的机器人控制指令,转化为左右轮的期望速度,再通过串口传给DSP。这一层是自己写程序完成。

决策层:就是与导航有关的了,建立地图和定位,然后用move_base根据你发布的传感器信息做出路径规划以及机器人的速度和转向控制。这一部分为ROS相应的package已经完成,我们只需要调用即可。

在这个系列里,我们只关注如何用 move_base package 做出的控制对机器人进行实际控制。文章接下来的部分将按照从上到下的顺序,一个问题接一个问题的来介绍如何使用move_base控制实际机器人。

1. move_base package的系统介绍:

ROS提供的move_base 包让我们能够在已建立好的地图中指定目标位置和方向后,move_base根据机器人的传感器信息控制机器人到达我们想要的目标位置。它主要功能包括:结合机器人码盘推算出的odometry信息,作出路径规划,输出前进速度和转向速度。这两个速度是根据你在配置文件里设定的最大速度和最小速度而自动作出的加减速决策。下面的白色底色方框内就是move_base的内容:

在此框架中白色和灰色的都是ROS已经封装好的功能包:

这其中gmapping 和hector的功能是一样的,都是用来构建地图的,区别在于gmapping在构建过程中依赖于机器人的里程odom数据,hector则不需要odom,算法不同,在实际使用中选用其中的一个就可以了。

而蓝色标识的功能包则需要根据选用硬件平台的不同来定制。

图中我们可以看到move_base package 的输入和输出。要使得它能运行起来,我们就得构建好这些输入和输出。

必要的输入:

goal : 期望机器人在地图中的目标位置。

tf : 各个坐标系之间的转换关系。(具体/map frame --> /odom frame ,/odom frame --> /base_link frame)

odom:根据机器人左右轮速度推算出的航向信息(即/odom 坐标系中机器人x,y坐标以及航向角yaw,下面会具体介绍)

LaserScan:激光传感器的信息,用于定位。(在这个系列教程中,我们没有用到这个激光信息,而是在一个假的空白地图上对机器人进行控制,并假定/map坐标系和/odom坐标系完全重合,在后面会有关于这两个坐标系的介绍)

输出:

cmd_vel:在cmd_vel这个主题上发布Twist消息,这个消息包含的就是机器人的期望前进速度和转向速度。

再整理下思路:move_base收到goal以后,将目标goal通过基于actionlib的client(客户端)向服务器发送,服务器根据你的tf关系以及发布的odom消息不断反馈机器人的状态(feedbackcall)到客户端, 让move_base做路径规划和控制twist。

知道了move_base的这些外围消息接口以后,move_base的运行还需要一些内部的配置参数,如机器人的最大最小速度,已经路径规划时的最大转弯半径等等,这些参数配置在《Ros by Example 1》的8.1.2节有详细介绍。关于move_base更详细的介绍请点击官网wiki教程

至此,我们已经熟悉了move_base的各种接口,它订阅了什么消息,会发布什么消息都已经清楚了。因此让move_base控制实际的机器人最主要的就是要解决实际机器人如何发布这些消息给move_base,以及如何接受move_base发出的消息。

2. Twist 消息转化为机器人左右轮期望速度。

首先,假设move_base能够正常工作了,它将把控制命令Twist发布到cmd_vel这个主题上。我们现在来解决如何利用这个Twist消息来对机器人进行控制。

在ROS by example 一书中的第七章开头就规定了机器人自身的坐标系系统,如下图。注意两个坐标系的建立都是右手坐标系,左图中的右手就是机器人本身,x轴就是前进的方向,垂直于两轮之间的轴连线,Y轴就是两个轮之间的轴连线。右图表示机器人的旋转坐标系,大拇指指向Z轴,逆时针方向为正值。

清楚了坐标系以后,再来看看Twist这个消息里包含的是什么东西。

使用ctrl + alt + t 打开一个新的终端以后,输入如下命令,就可以查看Twist的消息类型了。

rosmsg show geometry_msgs/Twist  

其中linear 的x就是代表前进方向的速度,单位为m/s。angular 的z就代表机器人的绕中心旋转的角速度,单位为 弧度/s (rad/s)。

因此,我们只要在自己写的中间通信层程序中订阅cmd_twist这个主题(topic),就可以收到move_base发出的命令了。 下面给出一个如何订阅cmd_twist主题的demo。

首先在你之前建立的package的scripts文件夹下,笔者的是 beginner_tutorials/scripts文件夹,将下列代码复制进去,保存为your_filename.py。保存以后记得要chmod一下,让这个文件成为可执行的节点,具体操作如下。

roscd beginner_tutorials
cd scripts
chmod +x lis_cmdvel.py  

程序代码:

#!/usr/bin/env python
#refernence: http://answers.ros.org/question/29706/twist-message-example-and-cmd_vel/
import roslib; roslib.load_manifest(‘beginner_tutorials‘)
import rospy
import tf.transformations
from geometry_msgs.msg import Twist  

def callback(msg):
    rospy.loginfo("Received a /cmd_vel message!")
    rospy.loginfo("Linear Components: [%f, %f, %f]"%(msg.linear.x, msg.linear.y, msg.linear.z))
    rospy.loginfo("Angular Components: [%f, %f, %f]"%(msg.angular.x, msg.angular.y, msg.angular.z))  

    # Do velocity processing here:
    # Use the kinematics of your robot to map linear and angular velocities into motor commands
#    v_l = ...
#    v_r = ...  

    # Then set your wheel speeds (using wheel_left and wheel_right as examples)
#    wheel_left.set_speed(v_l)
#    wheel_right.set_speed(v_r)  

def listener():
    rospy.init_node(‘cmd_vel_listener‘)
    rospy.Subscriber("/cmd_vel", Twist, callback)#/cmd_vel
    rospy.spin()  

if __name__ == ‘__main__‘:
    listener()  

执行这些操作以后,这个文件就可以用rosrun指令执行了。

rosrun beginner_tutorials lis_cmdvel.py  

注意这个demo里的每当有Twist消息时,就会调用callback这个函数,callback这个函数里就是我们要处理的内容。这里只是简单的打印收到的消息,还没有对消息进行处理。

机器人期望的前进速度linear.x和转弯速度angular.z都由move_base输出了,那么如何将他们转化成机器人左右轮的期望速度呢?关于如何转化为左右轮的期望速度,我先贴出自己程序中的源代码部分,下面这三个函数是一个属于同一个类:

def callback(self,msg ):  

    cmd_twist_rotation =  msg.angular.z #
    cmd_twist_x  = msg.linear.x
    cmd_twist_y =  msg.linear.y #这个一般为0  

    #将twist消息转化为左右轮各自的期望速度
    wheelspeed = self.odom_to_speed(cmd_twist_x, cmd_twist_y,cmd_twist_rotation)
    print ‘msg:‘, msg                #打印得到的twist消息
    print wheelspeed                 #打印转化后的速度   

    #蓝牙串口发送到DSP  wheelspeed[0]左轮速度, wheelspeed[1]右轮速度
    self.blue_tooth_send([wheelspeed[0], self.speed_kp, self.speed_ki,  wheelspeed[1]])     

def odom_to_speed(self, cmd_twist_x =0, cmd_twist_y=0,cmd_twist_rotation=0):
    ‘一般情况下,linear_y = 0 所以只需关注twist.linear.x 和 twist.angle.z的转换‘
    #这部分本来还有一段,关于twist.linear.y不为0时,如何转化的程序,Lz自己写的,实际可运行,但是不知道是否正确,所以这里删掉了。  

    cent_speed = cmd_twist_x        #前进的速度,即两轮的中心速度
    #将 指定的转速twist.angular.z 转化为左右轮的差速
    yawrate2 = self.yawrate_to_speed(cmd_twist_rotation)     

    Lwheelspeed = cent_speed - yawrate2/2
    Rwheelspeed = cent_speed + yawrate2/2  

    return Lwheelspeed, Rwheelspeed  

def yawrate_to_speed(self, yawrate):
    if yawrate > 0:
        theta_to_speed = 0.0077 #右转系数
    else:
        theta_to_speed = 0.0076  #左转系数  

    #yawrate :rad/s *0.02表示 20ms内应该转多少弧度,/0.0076是把 要转的弧度转化为左右轮速度差
    x = (yawrate * 0.02) / theta_to_speed
    return   x  

这一段程序里最主要的是如何将指定的转速转化为两轮的差速。主程序中订阅了cmd_vel主题,一旦收到move_base发出的twist消息,就调用callback函数进行转化。如果linear.y 不为0,说明小车要沿着y轴运动,这会导致两轮的差速,但是对于两轮控制的移动机器人,twist.linear.y = 0 是在move_base的配置文件base_local_planner_params.yaml中有明确指定,所以不需关注linear.y的转换:

max_vel_y = 0.0 #zero for a differential drive robot
min_vel_y = 0.0  

也就是只要关注前进速度linear.x和旋转速度angular.z的转换。

在直线行驶时,前进速度linear.x就是左右轮的期望速度。最主要的是将转速转化为左右轮的差速,一个轮子转的快,一个轮子转的慢,就有了转速。

下面介绍如何将指定的转速转化为两轮差速:

1.dsp采样的是单位时间内的码盘值,将码盘值转化为左右轮速度值后(Lwheelspeed,Rwheelspeed)通过串口发送给电脑端。

2.关于航迹推演(Odometry) 的公式中有一个关于如何有左右轮差速转化为旋转速度的计算公式。即yaw_rate = (Rwheelspeed - Lwheelspeed) / d .其中d为两轮间的间距,得到的转速单位rad/s。(如果不知道什么是Odometry 方法,可以点击这里。)或者也可以看看这个还有这个链接。直接用这个公式可以计算,但是在测量这个公式中的d的时候有测量误差。因此,楼主这里采用的拟合的方法得到这个差速到转速之间的转换系数。具体操作如下:

先从0度开始逆时钟旋转小车(角速度为正),分别记下转到pi/2,pi,pi*3/2,2pi时两轮差速的累计值,(即右轮速度减去左轮速度的累计值)。思路是:两轮差速乘以系数为转速,两轮差速累计值乘以系数就是旋转的角度。因此多次记下这些数据后,拟合就能得到得到特定的差速值到对应角度之间的转换关系。

如楼主的数据如下:

角度                 pi/2          pi             3/2*pi       2*pi

差速累计和       209.21      415          620.54     825.6

208.8       414.1       611.49     812.39

由于是线性关系,我们进行拟合以后得到这个转换系数为0.0077,拟合曲线如图,在实际操作中我记录了5组数据:

顺时针也可以采用这个系数,但是笔者,了防止左右轮机械上的差异导致这个系数不同,对顺时针也单独拟合了一次,得到0.0076。

右轮减去左轮的差速转化为角速度或者角度的系数有了,反过来,就可以将指定的旋转速度得到左右轮差速。

将指定的转速twist.angular.z * 0.02得到一个速度控制周期内(DSP底层设定的速度采样时间为20ms)应该旋转的角度量,这个角度量除以前面的系数就得到了单位控制周期内两轮之间速度的差异值。这就是上面程序中yawrate_to_speed()函数的计算思路。最后将这个速度的差异值/2,分别添加在中心速度上就分别得到了左右轮的期望速度。

现在完成了从cmd_vel twist 发送到电机这一部分的程序,在下一篇博客中,将介绍如何将介绍如何将电机左右轮的速度发布出来,让move_base接收到。

时间: 2024-09-28 03:16:58

move_base 控制机器人(1)的相关文章

move_base 控制机器人(2)

在这一篇文章中,将主要介绍如何将DSP上采集到的速度转化为Odom,即左右轮速度转化为机器人离起点的x,y坐标和机器人的朝向角yaw,让move_base可以订阅到这个信息并做出相应的路径规划.在wiki论坛上有一个很详细的例程是关于如何发布Odometry信息的,希望大家先仔细阅读.在这个程序里,它把转化好的Odom信息发布到了两个地方,第一个是广播了tf关系,即每次机器人移动以后,/odom坐标系和/base_linke的关系,(关于为什么要发布这tf关系,见第三篇博文):第二个是将消息发布

ROS探索总结(十九)——如何配置机器人的导航功能

1.概述 ROS的二维导航功能包,简单来说,就是根据输入的里程计等传感器的信息流和机器人的全局位置,通过导航算法,计算得出安全可靠的机器人速度控制指令.但是,如何在特定的机器人上实现导航功能包的功能,却是一件较为复杂的工程.作为导航功能包使用的必要先决条件,机器人必须运行ROS,发布tf变换树,并发布使用ROS消息类型的传感器数据.同时,为了让机器人更好的完成导航任务,开发者还要根据机器人的外形尺寸和性能,配置导航功能包的一些参数. 2.硬件要求 尽管导航功能包设计得尽可能通用,但是仍然对机器人

在ROS中开始自主机器人仿真 - 3 让turtlebot自主导航

我们已经在gazebo中实现了机器人的仿真,而且能够控制机器人的运动, 查看机器人所感知到的信息, 包括lasercan, 图像信息, 深度信息, 点云, 也包括没有提到的速度信息. 这里,我们建立用ROS navigation stack 导航功能包ROS navigation stack 导航功能包 , 进行机器人地图构建与导航. part 2.1: 让turtlebot自主导航 1 创建地图 使用下面的命令,借助键盘遥控机器人创建精确详尽的地图. 加载Gazebo仿真环境 roslaunc

在ROS中开始自主机器人仿真 - 2 让turtlebot跑起来

借助ROS的工具箱让turtlebot在gazebo中运行起来. part 1.1: 让turtlebot跑起来 1. 在gazebo中显示机器人 roslaunch turtlebot_gazebo turtlebot_world.launch 默认加载了一个playground 的world文件. 2. 用键盘进行控制机器人 roslaunch turtlebot_teleop keyboard_teleop.launch --screen Moving around: u i o j k

ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse

ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. 提供ROS接口的3D软件比较多,本章以最典型的Gazebo介绍为主,从Player/Stage/Gazebo发展而来,现在独立的机器人仿真开发环境,目前2016年最新版本Gazebo7.1配合ROS(kinetic)使用. 补充内容:http://blo

ROS机器人程序设计(原书第2版)补充资料 (捌) 第八章 导航功能包集入门 navigation

ROS机器人程序设计(原书第2版)补充资料 (捌) 第八章 导航功能包集入门 navigation 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. 本章三个非常重要概念:TF,SLAM,AMCL.务必掌握. 补充内容:http://blog.csdn.net/zhangrelay/article/details/50299417 第216页: 简介本章要点. 第217页: 导航综合功能包组成架构等. 补充如下: 目录 配置并使用导航功能

在ROS中开始自主机器人仿真 - 4 建立自己的自主机器人URDF模型

要建立自己的自主机器人,首先,必须要建立自己的机器人模型,URDF(Unified Robot Description Format)模型. part 3 建立自主机器人URDF模型 机器人URDF模型主要由两个文件组成:.xacro 是主文件,包含URDF项,包括关节,连杆:.gazebo包含gazebo的具体信息以便在gazebo中仿真. 例子请见:How to Build a Differential Drive Simulation 以下工程的源码下载地址请见: http://downl

仓库机器人可以替你完成家务-中国机器人信息网

OpenAI是由Elon Musk等诸多硅谷大亨联合建立的人工智能非营利组织.研发的一些仓库机器人正在学习如何完成家务活,致力于让仓库机器人替你完成家务. 在成立之初仅是为了进行人工智能研究,而现在正在对Fetch Robotics生产的机器人重新编程.Fetch Robotics是一家提供自动化仓库配套设备的公司.OpenAI进行的研究是给这些机器人装备软件使其能自主学习. OpenAI的研究反映出,与其在硬件上突破,不如在软件和机器学习领域的创新能更好地提升机器人的能力.Fetch Robo

raspberry pi 机器人

从小对机器人非常感兴趣,正好身边有一个raspberry pi,平时就当Linux的服务器练练命令行,写写脚本.这次打算把raspberry pi的强大的GPIO都利用起来,做个小机器人. 首先从网上买了机器人相关的配件,主要是驱动机器人移动的电机.L298N电机驱动板.HC-SR04超声波距离探测传感器.机器人车身等配件.用来制作机器人的是raspberry pi B+.此型号一共有40个GPIO口,足以满足入门型机器人的制作要求. 以下是我连接L298N电机驱动板和HC-SR04距离传感器的