一、在使用 ROS 和 mbed 驱动二轮差分底盘前,建议先浏览以下网站
① ROS 的 wiki 教程: http://wiki.ros.org/ROS/Tutorials
② mbed 的推荐教程:https://learn.sparkfun.com/tutorials/mbed-starter-kit-experiment-guide/experiment-1-blink-an-led
③ ros 与 mbed 串行通信的教程:http://wiki.ros.org/rosserial_mbed/Tutorials
二、在 mbed 下编写一个简单的 ROS 发布者
#include"mbed.h"
#include <ros.h>
#include <std_msgs/String.h>
ros::NodeHandle nh;
std_msgs::String str_msg;
ros::Publisher pub_chatter("chatter", &str_msg);
char hello[13] = "hello world!";
DigitalOut led = LED1;
int main() {
nh.initNode();
nh.advertise(pub_chatter);
while (1) {
led = !led;
str_msg.data = hello;
pub_chatter.publish( &str_msg );
nh.spinOnce();
wait_ms(1000);
}
}
代码解释:
1.
#include"mbed.h"
#include <ros.h>
作为每个ROS MBED程序,都需要加上这两个头文件
2.
#include <std_msgs/String.h>
在这里的发布者要发布的消息为字符串,因此使用该头文件
根据不同发布的消息类型,选择不同的头文件,常见的头文件如下:
#include <geometry_msgs/Twist.h>
#include <std_msgs/String.h>
#include <std_msgs/Bool.h>
#include <std_msgs/Float32.h>
#include <sensor_msgs/Range.h>
其中最常用的是
#include <geometry_msgs/Twist.h>
因为电机的转动普遍采用 Twist 数据类型来发布
3.
ros::NodeHandle nh;
实例化节点句柄,允许程序创建发布者和订阅者。此外,节点句柄还负责串口通信。
4.
std_msgs::String str_msg;
定义该字符串数据类型的一个变量
5.
ros::Publisher pub_chatter("chatter", &str_msg);
用主题名称“chatter”来实例化一个Publisher,Publisher的第二个参数是对要用于发布的消息实例的引用。
6.
char hello[13] = "hello world!";
定义一个将要发布的数据的数组变量
7.
DigitalOut led = LED1;
初始化 mbed 上的引脚
8.
nh.initNode();
初始化ROS节点句柄
9.
nh.advertise(pub_chatter);
在 chatter 主题上发布消息
10.
str_msg.data = hello;
给 str_msg 变量赋值
11.
pub_chatter.publish( &str_msg );
发布者发布 str_msg 变量的消息
12.
nh.spinOnce();
不断循环
13.
wait_ms(1000);
等待1s
关键代码
ros::NodeHandle nh;
std_msgs::String str_msg;
ros::Publisher pub_chatter("chatter", &str_msg);
nh.initNode();
nh.advertise(chatter);
str_msg.data = hello;
pub_chatter.publish( &str_msg );
nh.spinOnce();
运行代码
$roscore
$rosrun rosserial_python serial_node.py /dev/ttyACM0
$rostopic echo chatter
若一切运行正常则会得到如下截图
使用 rqt_graph 查看节点和主题的关系
$rosrun rqt_graph rqt_graph
运行后便会看到如下图片
从上面的图片可以得到的信息是:mbed 上的一个节点作为发布者,发布消息到 chatter 主题。
以上两种方法是常用的查看节点与主题情况的工具
三、在 mbed 下驱动直流电机
由于电机驱动时的电流比较大,因此驱动电机时需要借助 H 桥的辅助,在这里博主使用的是 DRV8833
mbed 里面已经有很多已经编写好的库,我们可以直接导入这些库到我们的代码中
https://developer.mbed.org/users/simon/code/Motor_HelloWorld/
点击右上角的橙色按钮即可导入 DC motor 这个程序到我们的在线编译器中
修改 mebed 官网的 DC motor 代码之 Motor.cpp
#include "Motor.h"
#include "mbed.h"
Motor::Motor(PinName pwm, PinName fwd):
_pwm(pwm), _fwd(fwd) {
// Set initial condition of PWM
_pwm.period(0.001);
_pwm = 0;
_fwd = 0;
}
void Motor::speed(float speed) {
_fwd = (speed > 0.0) ? 1 : 0 ;
_pwm = abs(speed);
}
修改 mebed 官网的 DC motor 代码之 Motor.h
#ifndef MBED_MOTOR_H
#define MBED_MOTOR_H
/** Interface to control a standard DC motor
* with an H-bridge using a PwmOut and 2 DigitalOuts
*/
class Motor {
public:
/** Create a motor control interface
* @param pwm A PwmOut pin, driving the H-bridge enable line to control the speed
* @param fwd A DigitalOut, set high when the motor should go forward
*/
Motor(PinName pwm, PinName fwd);
/** Set the speed of the motor
* @param speed The speed of the motor as a normalised value between -1.0 and 1.0
*/
void speed(float speed);
protected:
PwmOut _pwm;
PwmOut _fwd;
};
#endif
修改 mebed 官网的 DC motor 代码之 main.cpp
#include "mbed.h"
#include "Motor.h"
#include <ros.h>
#include <geometry_msgs/Twist.h>
Motor A(p21, p22);
Motor B(p23, p24);
ros::NodeHandle nh;
void messageCb(const geometry_msgs::Twist& msg)
{
if (msg.angular.z == 0 && msg.linear.x == 0)
{
A.speed(0);
B.speed(0);
}
else
{
if (msg.angular.z < 0)
{
A.speed(0.5);
B.speed(-0.5);
wait_ms(20);
A.speed(0);
B.speed(0);
}
else if (msg.angular.z > 0)
{
A.speed(-0.5);
B.speed(0.5);
wait_ms(20);
A.speed(0);
B.speed(0);
}
else if (msg.linear.x < 0)
{
A.speed(-0.5);
B.speed(-0.5);
wait_ms(20);
A.speed(0);
B.speed(0);
}
else if (msg.linear.x > 0)
{
A.speed(0.5);
B.speed(0.5);
wait_ms(20);
A.speed(0);
B.speed(0);
}
}
}
ros::Subscriber<geometry_msgs::Twist> sub("/turtle1/cmd_vel", &messageCb);
int main() {
nh.initNode();
nh.subscribe(sub);
while (1)
{
nh.spinOnce();
wait_ms(1);
}
}
由于设想在是 ROS 下驱动二轮差分底盘的,所以就要在 mbed 里添加 ROS 库,具体步骤如下:
在 mbed 在线编译器中对着我们的工程右键→ Import Library… → From URL… →
然后将 [ https://developer.mbed.org/users/garyservin/code/ros_lib_indigo/ ] 括号里面的
内容复制到 Source URL 中 →最后点击 Import 即可导入ROS 库。