ros的全局把握

控制系统的架构:

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

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

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

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

1. move_base package的系统介绍:

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


           

图中我们可以看到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的运行还需要一些内部的配置参数,如机器人的最大最小速度,已经路径规划时的最大转弯半径等等,关于move_base更详细的介绍请点击官网wiki教程

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

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

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

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

[plain]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. 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一下,让这个文件成为可执行的节点,具体操作如下。

[plain]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. roscd beginner_tutorials  
  2. cd scripts  
  3. chmod +x lis_cmdvel.py  

程序代码:

[python]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. #!/usr/bin/env python  
  2. #refernence: http://answers.ros.org/question/29706/twist-message-example-and-cmd_vel/  
  3. import roslib; roslib.load_manifest('beginner_tutorials')  
  4. import rospy  
  5. import tf.transformations  
  6. from geometry_msgs.msg import Twist  
  7.   
  8. def callback(msg):  
  9.     rospy.loginfo("Received a /cmd_vel message!")  
  10.     rospy.loginfo("Linear Components: [%f, %f, %f]"%(msg.linear.x, msg.linear.y, msg.linear.z))  
  11.     rospy.loginfo("Angular Components: [%f, %f, %f]"%(msg.angular.x, msg.angular.y, msg.angular.z))  
  12.   
  13.     # Do velocity processing here:  
  14.     # Use the kinematics of your robot to map linear and angular velocities into motor commands  
  15. #    v_l = ...  
  16. #    v_r = ...  
  17.   
  18.     # Then set your wheel speeds (using wheel_left and wheel_right as examples)  
  19. #    wheel_left.set_speed(v_l)  
  20. #    wheel_right.set_speed(v_r)  
  21.   
  22. def listener():  
  23.     rospy.init_node('cmd_vel_listener')  
  24.     rospy.Subscriber("/cmd_vel", Twist, callback)#/cmd_vel  
  25.     rospy.spin()  
  26.       
  27. if __name__ == '__main__':  
  28.     listener()  
执行这些操作以后,这个文件就可以用rosrun指令执行了。

[plain]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. rosrun beginner_tutorials lis_cmdvel.py  

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

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

[python]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. def callback(self,msg ):  
  2.   
  3.     cmd_twist_rotation =  msg.angular.z #  
  4.     cmd_twist_x  = msg.linear.x   
  5.     cmd_twist_y =  msg.linear.y #这个一般为0  
  6.       
  7.     #将twist消息转化为左右轮各自的期望速度  
  8.     wheelspeed = self.odom_to_speed(cmd_twist_x, cmd_twist_y,cmd_twist_rotation)          
  9.     print 'msg:', msg                #打印得到的twist消息  
  10.     print wheelspeed                 #打印转化后的速度   
  11.       
  12.     #蓝牙串口发送到DSP  wheelspeed[0]左轮速度, wheelspeed[1]右轮速度          
  13.     self.blue_tooth_send([wheelspeed[0], self.speed_kp, self.speed_ki,  wheelspeed[1]])     
  14.   
  15. def odom_to_speed(self, cmd_twist_x =0, cmd_twist_y=0,cmd_twist_rotation=0):  
  16.     '一般情况下,linear_y = 0 所以只需关注twist.linear.x 和 twist.angle.z的转换'  
  17.     #这部分本来还有一段,关于twist.linear.y不为0时,如何转化的程序,Lz自己写的,实际可运行,但是不知道是否正确,所以这里删掉了。  
  18.       
  19.     cent_speed = cmd_twist_x        #前进的速度,即两轮的中心速度  
  20.     #将 指定的转速twist.angular.z 转化为左右轮的差速  
  21.     yawrate2 = self.yawrate_to_speed(cmd_twist_rotation)     
  22.       
  23.     Lwheelspeed = cent_speed - yawrate2/2  
  24.     Rwheelspeed = cent_speed + yawrate2/2  
  25.       
  26.     return Lwheelspeed, Rwheelspeed  
  27.   
  28. def yawrate_to_speed(self, yawrate):  
  29.     if yawrate > 0:  
  30.         theta_to_speed = 0.0077 #右转系数  
  31.     else:  
  32.         theta_to_speed = 0.0076  #左转系数  
  33.       
  34.     #yawrate :rad/s *0.02表示 20ms内应该转多少弧度,/0.0076是把 要转的弧度转化为左右轮速度差      
  35.     x = (yawrate * 0.02) / theta_to_speed     
  36.     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的转换:

[python]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. max_vel_y = 0.0 #zero for a differential drive robot  
  2. min_vel_y = 0.0  

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

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

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

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

       2.关于航迹推演(Odometry) 的公式中有一个关于如何有左右轮差速转化为旋转速度的计算公式。即yaw_rate = delta_t*(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 发送到电机这一部分的程序。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值