【一】、在 ROS 和 mbed 的环境下准备驱动二轮差分底盘

一、在使用 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 
#include 

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 MBED程序,都需要加上这两个头文件

2.

#include 

在这里的发布者要发布的消息为字符串,因此使用该头文件
根据不同发布的消息类型,选择不同的头文件,常见的头文件如下:

#include 
#include 
#include 
#include 
#include 

其中最常用的是

#include 

因为电机的转动普遍采用 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

若一切运行正常则会得到如下截图

【一】、在 ROS 和 mbed 的环境下准备驱动二轮差分底盘_第1张图片

使用 rqt_graph 查看节点和主题的关系

$rosrun rqt_graph rqt_graph

运行后便会看到如下图片

【一】、在 ROS 和 mbed 的环境下准备驱动二轮差分底盘_第2张图片

从上面的图片可以得到的信息是:mbed 上的一个节点作为发布者,发布消息到 chatter 主题。
以上两种方法是常用的查看节点与主题情况的工具

三、在 mbed 下驱动直流电机

由于电机驱动时的电流比较大,因此驱动电机时需要借助 H 桥的辅助,在这里博主使用的是 DRV8833

【一】、在 ROS 和 mbed 的环境下准备驱动二轮差分底盘_第3张图片

mbed 里面已经有很多已经编写好的库,我们可以直接导入这些库到我们的代码中
https://developer.mbed.org/users/simon/code/Motor_HelloWorld/

【一】、在 ROS 和 mbed 的环境下准备驱动二轮差分底盘_第4张图片

点击右上角的橙色按钮即可导入 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 
#include 

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 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 库。

你可能感兴趣的:(ros学习)