1.os_arduino_bridge 文件描述

 

├── README.md
├── ros_arduino_bridge                      # metapackage (元包)
│   ├── CMakeLists.txt
│   └── package.xml
├── ros_arduino_firmware                    #固件包,更新到Arduino
│   ├── CMakeLists.txt
│   ├── package.xml
│   └── src
│       └── libraries                       #库目录
│           ├── MegaRobogaiaPololu          #针对Pololu电机控制器,MegaRobogaia编码器的头文件定义
│           │   ├── commands.h              #定义命令头文件
│           │   ├── diff_controller.h       #差分轮PID控制头文件
│           │   ├── MegaRobogaiaPololu.ino  #PID实现文件
│           │   ├── sensors.h               #传感器相关实现,超声波测距,Ping函数
│           │   └── servos.h                #伺服器头文件
│           └── ROSArduinoBridge            #Arduino下位机部分,可以根据自己搭建的下位机进行修改
│               ├── commands.h              #定义命令
│               ├── diff_controller.h       #差分轮PID控制头文件
│               ├── encoder_driver.h        #编码器驱动头文件,定义插脚(pins)
│               ├── encoder_driver.ino      #编码器驱动实现, 读取编码器数据,重置编码器等
│               ├── motor_driver.h          #电机驱动头文件
│               ├── motor_driver.ino        #电机驱动实现,初始化控制器,设置速度
│               ├── ROSArduinoBridge.ino    #核心功能实现,
│               ├── sensors.h               #传感器头文件及实现
│               ├── servos.h                #伺服器头文件,定义插脚,类
│               └── servos.ino              #伺服器实现
├── ros_arduino_msgs                        #消息定义包
│   ├── CMakeLists.txt
│   ├── msg                                 #定义消息
│   │   ├── AnalogFloat.msg                 #定义模拟IO浮点消息
│   │   ├── Analog.msg                      #定义模拟IO数字消息
│   │   ├── ArduinoConstants.msg            #定义常量消息
│   │   ├── Digital.msg                     #定义数字IO消息
│   │   └── SensorState.msg                 #定义传感器状态消息
│   ├── package.xml
│   └── srv                                 #定义服务
│       ├── AnalogRead.srv                  #模拟IO输入
│       ├── AnalogWrite.srv                 #模拟IO输出
│       ├── DigitalRead.srv                 #数字IO输入
│       ├── DigitalSetDirection.srv      #数字IO设置方向
│       ├── DigitalWrite.srv                #数字IO输入
│       ├── ServoRead.srv                   #伺服电机输入
│       └── ServoWrite.srv                  #伺服电机输出
└── ros_arduino_python                      #ROS相关的Python包,用于上位机,树莓派等开发板或电脑等。
    ├── CMakeLists.txt
    ├── config                              #配置目录
    │   └── arduino_params.yaml             #定义相关参数,我们需要对此修改才能使用。由arduino.launch调用
    ├── launch
    │   └── arduino.launch                  #启动文件
    ├── nodes
    │   └── arduino_node.py                 #python文件,实际处理节点,由arduino.launch调用,即可单独调用。
    ├── package.xml
    ├── setup.py
    └── src                                 #Python类包目录
        └── ros_arduino_python
            ├── arduino_driver.py           #Arduino驱动类
            ├── arduino_sensors.py          #Arduino传感器类
            ├── base_controller.py          #基本控制类,订阅cmd_vel话题,发布odom话题
            └── __init__.py                 #类包默认空文件

2.安装

2.1下载安装ros_arduino_bridge

cd ~/catkin_ws/src
git clone https://github.com/hbrobotics/ros_arduino_bridge.git 

2.2编译

 

cd ..
catkin_make

实际上,编译完成后并不能直接控制小车,还需要匹配串口,修改设置文件
在ubuntu终端输入(查看串口号)

dmesg | grep ttyS*

可以看到你的串口情况,比如我的上位机和下位机就是通过 /dev/ttyACM0 连接的。
接下来修改配置文件arduino_params.yaml,比如说我的就位于
~/catkin_ws/src/ros_arduino_bridge/ros_arduino_python/config,打开:

cd ~/catkin_ws/src/ros_arduino_bridge/ros_arduino_python/config
vim arduino_params.yaml
# For a direct USB cable connection, the port name is typically
# /dev/ttyACM# where is # is a number such as 0, 1, 2, etc
# For a wireless connection like XBee, the port is typically
# /dev/ttyUSB# where # is a number such as 0, 1, 2, etc.

port: /dev/ttyUSB0            #你要修改的部分,改为arduino板和上位机连接的串口号
baud: 57600
timeout: 0.1

rate: 50
sensorstate_rate: 10

use_base_controller: True     #你要修改的部分 改为True
base_controller_rate: 10

# For a robot that uses base_footprint, change base_frame to base_footprint
base_frame: base_link

# === 这部分是车子的参数,比如轮子直径(单位:米),减速比,编码器信息等,根据你自己的车子来修改
wheel_diameter: 0.066        #车轮直径(米)
wheel_track: 0.1             #轮距(米)。(驱动轮中心之间的距离)
encoder_resolution: 8384     #from Pololu for 131:1 motors
gear_reduction: 1.0          #减速比
motors_reversed: False       #反转车轮旋转方向

# === PID 部分,控制轮速,修改到车子能够根据命令走直线且速度稳定
Kp: 20                       #PID参数:比例
Kd: 12                       #PID参数:微分
Ki: 0                        #PID参数:积分
Ko: 50                       #PID参数:输出
accel_limit: 0.5             #轮速变化最大的加速度

# === Sensor definitions.  Examples only - edit for your robot.
#     Sensor type can be one of the follow (case sensitive!):
#      * Ping
#      * GP2D12
#      * Analog
#      * Digital
#      * PololuMotorCurrent
#      * PhidgetsVoltage
#      * PhidgetsCurrent (20 Amp, DC)


# ===附加到Arduino的传感器字典
sensors: {
  #motor_current_left:   {pin: 0, type: PololuMotorCurrent, rate: 5},
  #motor_current_right:  {pin: 1, type: PololuMotorCurrent, rate: 5},
  #ir_front_center:      {pin: 2, type: GP2D12, rate: 10},
  #sonar_front_center:   {pin: 5, type: Ping, rate: 10},
  arduino_led:          {pin: 13, type: Digital, rate: 5, direction: output}
}
  1. 解释代码
  • 接口设置

    • 接口要么是/dev/ttyACM0,要么是/dev/ttyUSB0,视情况而定
    • 其中MegaRobogaiaPololu的Arudino sketch默认是以57600的波特率连接的。
  • 轮询速率

    • 跳出ROS loop运行的速率主要就取决于这个速率参数(默认为50Hz),这个默认值足以满足大多数情况。在任何情况下,它应该至少与你的传感器的最大速率(下面我们会说到)一样快才行
    • sensorstate_rate决定了多久发布一个所有传感器的集合列表,每个传感器也以各自的速率在各自的主题上发布消息。
    • use_base_controller参数默认为False。你可以把它设置为True(假设你有文中所要求的硬件设施)。
    • 设置PID参数base_controller_rate参数决定了多久发布一次里程计读取信息。
  • 定义传感器

    • sensors参数按照定义了传感器的名字和参数的字典(可任意指定,传感器的名字也会成为那个传感器所对应主题的名字)
    • 四个最重要的参数分别是:pin,type,rate,direction。
    • rate定义了你每秒想轮询一次那个传感器多少次。例如,一个电压传感器可能每秒仅仅被轮询一次(或者仅仅每两秒一次),而一个声呐传感器可能每秒被轮询20次。
    • type必须是列表中被列出来的(注意区分大小写!)。
    • direction默认是input,所以如果你想将它定义为output,就将这个direction单独设为output。
    • 在上面的例子中,Arduino LED(pin13)将会以每秒两次的速率被点亮或熄灭。
  • 设置Drivetrain(驱动系统)和PID参数

    • 为了使用基础控制器(base controller),你必须去掉它的注释并且设置机器人的drivetrain和PID参数
    • 示例中drivetrain参数是直径6英寸的驱动轮,距离11.5英寸
    • 注意在ROS中使用米作为距离单位,所以一定要换算单位
    • 示例中的编码器的分辨率(每转的tick数)规格来自于Pololu 131:1电动机。为你的电动机/编码器组合设置合理的数值
    • 如果你的轮子可以向后转,那么就把motors_reversed设置为true,否则的话就设置为False
    • PID参数比较难设置,你可以先按照示例中的值设置。但是在你第一次发送转弯命令的时候,架空小车测试。

给配置文件改个名,改成my_arduino_params.yaml

mv arduino_params.yaml my_arduino_params.yaml

2.3.下位机

从github下载的代码中包含对应的arduino mega2560下位机程序,严格按照原作者推荐安装下位机的话就可以直接使用,否则就要做对应修改。

3.测试

环境设置

3.1串口监视器

英文是both NL $ CR 中文是回车换行

命令使用例子

  • 如果你想从模拟引脚pin3读取数据,就发送这个命令: a 3
  • 你想改变数字引脚pin3的模式为OUTPUT,就发送这个命令: c 3 1
  • 得到目前编码器的计数,就发送这个命令:e
  • 让机器人以每秒20个encoder ticks的速度向前移动,就发送这个命令:m 20 20
  • 这些命令有些需要有对应的参数,比如a 3中3代表模拟引脚3

 

3.2  传感器的数据

  1. 看所有传感器的数据
$ rostopic echo /arduino/sensor_state
  1. 查看任何指定的传感器数据
$ rostopic echo /arduino/sensor/sensor_name

例如:有一个叫做ir_front_center的传感器,查看相应的数据

$ rostopic echo /arduino/sensor/ir_front_center
  1. 使用rxqrt来将这系列数据用图像的形式表示出来

rxplot -p 60 /arduino/sensor/ir_front_center/range

 

3.3 查看里程

 

启动之前,千万不要打开Arduino IDE 的串口监视器,因为串口监视器会与该节点争夺串口资源

roscore
roslaunch ros_arduino_python arduino.launch

成功后提示:灯会不停闪

Connecting to Arduino on port /dev/ttyUSB0 ...
Connected at 57600
Arduino is ready.
[INFO] [1602326761.912710]: Connected to Arduino on port /dev/ttyUSB0 at 57600 baud
[INFO] [1602326761.920105]: arduino_led {'direction': 'output', 'type': 'Digital', 'rate': 5, 'pin': 13} published on topic /arduino/sensor/arduino_led
Updating PID parameters
[INFO] [1602326761.945121]: Started base controller for a base of 0.2969m wide with 8384 ticks per rev
[INFO] [1602326761.946747]: Publishing odometry data at: 10.0 Hz using base_link as base frame

 

报错1

RLException: [arduino.launch] is neither a launch file in package [ros_arduino_python] nor is [ros_arduino_python] a launch file name
The traceback for the exception was written to the log file

 

source ~/.bashrc

报错2

ImportError: No module named ros_arduino_python.arduino_driver
这时候ros重新安装,命令都点一下,不用卸载

 

如果拒绝连接

sudo chmod 777 /dev/ttyUSB0
sudo usermod -aG dialout yys

 如果缺少库serial

sudo pip install pyserial

 

打开新终端,发布Twist消息来控制机器人的运行,如:
 

rostopic pub /cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

或者

rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.1, y: 0, z: 0}, angular: {x: 0, y: 0, z: -0.5}}'

 

rostopic pub 这个命令会把message发送到指定的topic

-r 这个选项是让rostopic循环发布message,然后退出,-1是一次

/cmd_vel这个是message要发布到的topic的名字

geometry_msgs/Twist 这个是发布message到topic的时候要使用的消息类型

-- 这个就是告诉选项解析器,后面如果再出现“-”就不要管了,不是选项了。

'[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]' 最后一部分就是参数了,就是对应之前获得的数据类型写的。

运行此命令,机器人会原地打转,那么就将motors_reversed 参数改为与之前相反的值, 用如下命令查看odom的信息,此信息会不断的变化

rostopic echo /odom

 显然很多人不太喜欢小车的行走信息只是一串串数字,那样看起来太不直观了,幸好ros提供这样的工具rqt_plot,可以图形化显示这些信息,新开一个终端,输入:

rosrun rqt_plot rqt_plot

会出现以下一个窗口,把需要显示的里程计topic输入左上角窗口,例如/odom/pose/pose/orientation就会把这些信息以曲线的形式显示出来,当然这里只是一个使用rqt_plot的例子,位置信息显然不适合这样显示出来,但各位可以修改ros_arduino_bridge的base_controller.py这个文件,将小车的速度以一个话题的形式发布出来,这样也方便大家调节PID参数。

 

至此机器人已经可以按照Twist消息进行控制,但是使用rostopic pub 为cmd_vel话题发送控制信息显然很麻烦。这里我们改为使用键盘来控制小车。

3.4 ROS服务

  1. digital_set_direction-设置数字引脚的方向
rosservice call /arduino/digital_set_direction pin direction
  • 这里pin是引脚数字,direction为0代表输入,1代表输出。
  1. digital_write-给数字引脚发送高低电平(LOW为0,HIGH为1)
rosservice call /arduino/digital_write pin value
  • 同样,这里pin是引脚数字,value是电平高低(LOW为0,HIGH为1)。
  1. servo_write-设置伺服机位置
rosservice call /arduino/servo_write id pos
  • 这里id是伺服机的索引号(定义在Arduino sketch中的servos.h)并且pos是以弧度为单位(0-3.14),头文件servos.h中具体是这样写的:
byte servoInitPosition [N_SERVOS] = { 90, 90 }; // [0, 180] degrees
  1. servo_read -读取伺服机的位置
rosservice call /arduino/servo_read id

5.使用键盘控制小车

安装键盘控制程序,可以直接安装在小车的workspace里面

cd ~/catkin_ws/src
git clone https://github.com/ros-teleop/teleop_twist_keyboard.git 

 

catkin_make

 

启动小车后,再启动键盘控制:

rosrun teleop_twist_keyboard teleop_twist_keyboard.py

 接下来就可以直接使用键盘来控制小车了

 

6.关系图

新终端,执行:

rqt_graph

 

 node only

使用键盘发布命令就是代替rostopic pub的作用给cmd_vel发布控制信息,这样就方便了不少,当然这本质上仍然是一个简单的项目教程,就类似ros上的小乌龟教学项目,只不过是实物化了。即使如此,一个ros小车作为平台,是可以进行很多后续项目的开发的,可以说是既简单又重要了。