Kobuki(turtlebot底盘)通信方式

来源:互联网 发布:淘宝退货程序 编辑:程序博客网 时间:2024/04/28 04:59

    当Kobuki_nodelet被运行时,自动跳转到onInit()函数,函数中建立KobukiRos类的新对象,并调用其init() 函数,在KobukiRos类的init()函数中,定义了若干个用于接收ROS话题的subscriber,若干个用于发布底盘传感器数据的publisher。并且启动了Kobuki这个驱动类的初始化函数。

    最后启动KobukiRos对象的update()函数,用于检测底盘的各种状态,比如底盘的连接状态,电池状态,轮子是否接触地面等等。

 

Turtlebot的运行机制总结如下:

    启动minimal.launch之后,启动Kobuki_nodelet节点,新建两个类对象,一是用于底盘和ROS通信类KobukiRos(桥梁),一个是底盘的驱动类Kobuki(心脏)。

通信类中定义了用于接收ROS命令话题的接收者,接收如/cmd_vel等话题。接收者接收到话题消息后,通过回调函数,将ROS通用格式的数据转换为底盘可用格式的数据,并调用驱动类的函数接口,通过串口给底盘单片机发送数据,实现对底盘的操控。

通信类中还定义了用于发布底盘状态话题的发布者,如发送/sensors/imu_data的话题。通信类通过驱动类的函数接口获得原始传感器数据,将其转换为ROS通用数据格式,由发布者发送给ROS上层,来实现反馈功能。

最后,Kobuki_nodelet启动了一套完整的监测机制,用于监测底盘的各种异常状态。

 

参考源码:

kobuki_nodelet.cpp:(实现Kobuki_nodelet类)

https://github.com/yujinrobot/kobuki/blob/indigo/kobuki_node/src/nodelet/kobuki_nodelet.cpp

 

kobuki_ros.hpp:

https://github.com/yujinrobot/kobuki/blob/indigo/kobuki_node/include/kobuki_node/kobuki_ros.hpp

kobuki_ros.cpp:(实现KobukiRos类,相当于桥梁)

https://github.com/yujinrobot/kobuki/blob/indigo/kobuki_node/src/library/kobuki_ros.cpp

 

subscriber_callbacks.cpp:(实现回调函数,ROS数据格式和底盘数据格式的转换)

https://github.com/yujinrobot/kobuki/blob/indigo/kobuki_node/src/library/subscriber_callbacks.cpp

 

kobuki.hpp:

https://github.com/yujinrobot/kobuki_core/blob/indigo/kobuki_driver/include/kobuki_driver/kobuki.hpp

kobuki.cpp:(实现Kobuki类,驱动类,相当于心脏)

https://github.com/yujinrobot/kobuki_core/blob/indigo/kobuki_driver/src/driver/kobuki.cpp

 

 

 

 

 

 

 

详细跳转机制:(以/cmd_vel为例)

    在Kobuki_nodelet.cpp中,首先新建KobukiRos类对象。然后调用KobukiRos的init()初始化函数,在这个函数中,声明了许多发布者和订阅者,下面以/cmd_vel话题为例,继续深入。

    velocity_command_subscriber= nh.subscribe(std::string("commands/velocity"), 10,&KobukiRos::subscribeVelocityCommand, this);

    当有/cmd_vel话题发布时,这个发布者的回调函数自动被调用,即进入KobukiRos::subscribeVelocityCommand()中。

    在回调函数中,其将数据发送给驱动类Kobuki的函数中:

    kobuki.setBaseControl(msg->linear.x, msg->angular.z);

    kobuki.setBaseControl这个函数通过调用diff_driver类(差速轮驱动)的setVelocityCommands()函数,将/cmd_vel话题的Twist类型数据转换为左右轮速,并保存在vector容器中。

    注意,diff_driver::setVelocityCommands()并没有直接将左右轮速通过串口发送给底盘,而是保存在vector<double>类型的私有成员point_velocity之中。

 

    为什么没有直接通过串口传输呢,那传输步骤在哪呢?我们接着来看,以上的步骤其实仅仅是一个线程,我们再来看看另外的线程。

   

    继续回到KobukiRos的init()初始化函数,除了声明了发布者和订阅者用于接收发布数据,同时也调用了驱动类Kobuki的init()初始化函数。

    在驱动类Kobuki的init()初始化函数中,初始了串口,并设置了一些必要信息,最后进入了Kobuki::spin()循环函数。

    在spin()函数中,首先判断了是否打开了串口,如果没打开就打开并设置串口。确认完毕之后,先做读操作,然后做写操作。在写操作中,调用了sendBaseControlCommand(),在这个函数中,先调用了上面讲过的diff_driver::velocityCommands()函数,将转换好的数据设置在Kobuki类的vector<double>类型的私有成员velocity_commands中。最后调用sendCommand()函数,终于在里面看到了串口写操作的相关代码!!!

0 0
原创粉丝点击