本文涉及的内容都是针对四轮小车的,如果你的是两轮或者其他形式的小车,请参考其他文章。当然如果你感兴趣的话,本文也有一定的参考价值。另外,本文的内容仅供参考,如有错误,望各位不吝赐教。

目录

  • 目录
  • 运动学分析
  • 计算车轮转速
  • 代码实现
  • 硬件连接
  • 测试你的代码
  • 后记
  • 参考资料

运动学分析

在用代码实现之前,我们最好先简单了解一下相关的原理。这种4WD轮式机器人准确的说是采用所谓”滑动控制“(Skid-steer Drive),这是一种类似于差速控制(Differential Drive)的运动方式。

NOTE:具体可以参考我的相关博文:机器人差速驱动方式(Differential Drive)和 机器人滑动转向驱动方式(Skid-steer Drive)。

参考阿克曼(Ackerman)转向几何学原理,即在汽车转向时4个轮胎都近似围绕一个中心点旋转以保证汽车的行驶稳定性,但是由于四轮差速转向小车没有转向机构,很难保证这一点,而且,小车转向时很容易和地面发生滑移。把汽车的形心作为质心,并且忽略路面情况变化等的影响,可得出四轮差速转向小车的运动学模型如下图所示。

在该图中α1\alpha_1、α2\alpha_2分别为前左轮和后左轮,前右轮和后右轮的转角;2L2L为左右轮距离;2K2K为前后轮轴距;vv和ww分别为车子质心的线速度和角速度,V1V_1,V2V_2,V3V_3,V4V_4分别为各个轮中心的实际运动方向。
根据上图可以得出各速度的和转动角度的关系:

V1=w⋅R1=w⋅Ksinα1

V_1=w\cdot R_1=w\cdot \frac{K}{\sin \alpha_1}

V2=w⋅R2=w⋅Ksinα2

V_2=w\cdot R_2=w\cdot \frac{K}{\sin \alpha_2}

V3=V1=w⋅Ksinα1

V_3=V_1=w\cdot \frac{K}{\sin \alpha_1}

V4=V2=w⋅Ksinα2

V_4=V_2=w\cdot \frac{K}{\sin \alpha_2}

由公式Vy=V⋅cosαV_y=V\cdot \cos \alpha可得:

V1y=V1cosα1=w⋅Ktanα1=w(R−L)

V_1y=V_1\cos \alpha_1=\frac{w\cdot K}{\tan \alpha_1}=w(R-L)

V2y=V2cosα2=w⋅Ktanα2=w(R+L)

V_2y=V_2\cos \alpha_2=\frac{w\cdot K}{\tan \alpha_2}=w(R+L)

V3y=V3cosα1=w⋅Ktanα1=w(R−L)

V_3y=V_3\cos \alpha_1=\frac{w\cdot K}{\tan \alpha_1}=w(R-L)

V4y=V4cosα2=w⋅Ktanα2=w(R+L)

V_4y=V_4\cos \alpha_2=\frac{w\cdot K}{\tan \alpha_2}=w(R+L)
式中, R=vwR=\frac{v}{w}。
则电机的角速度为:

wn=Vny⋅ir,n=1,2,3,4

w_n=\frac{V_ny\cdot i}{r}, n=1,2,3,4
式中, ii为电动机的减速比,rr为车轮的半径。电机的转速可以根据 n=w2πn=\frac{w}{2\pi}得到。

计算车轮转速

在明白了转向原理之后,我们可以根据实际小车的尺寸算出我们要的数据。我使用的小车的各项参数如下:

  • 前后轮轴距2K=168mm2K=168mm
  • 左右轮距离2L=266mm2L=266mm
  • 车轮直径r=130r=130
  • 电动机减速比1:301:30
    在这里我们需要各个轮子的转速,我们指定小车转向的角速度ww为5rad/s5rad/s,转向半径RR为100mm100mm。由上面的公式便可得出各个轮子的转速:

    n1=n3=18.3m/s

    n_1=n_3=18.3m/s

    n2=n4=116.1m/s

    n_2=n_4=116.1m/s

代码实现

首先我们要包含所需要的头文件:

#include <AFMotor.h>
#include <ros.h>
#include <geometry_msgs/Twist.h>

其中AFMotor.h驱动电动机驱动板(我所用的是L293D)的头文件,另外两个请参考ROS的wiki文档。

//setting each motor
AF_DCMotor rightFront(3);
AF_DCMotor leftFront(4);
AF_DCMotor leftBack(1);
AF_DCMotor rightBack(2);

设置每个电机在驱动板上对应的接口。

//x轴方向的速度
double lin_vel = 0.0;
//y轴方向的速度
double ang_vel = 0.0;
int cmd_ctrl = 0;
//注册ROS节点
ros::NodeHandle nh;
//回调函数
void motor_cb(const geometry_msgs::Twist& vel)
{lin_vel = vel.linear.x;ang_vel = vel.angular.z;cmd_ctrl = 1 * lin_vel + 3 * ang_vel;
}
//设置订阅的消息类型和发布的主题
ros::Subscriber<geometry_msgs::Twist> sub("/turtle1/cmd_vel", motor_cb);

这一部分的作用主要是订阅相关的控制消息。

void setup() {nh.initNode();nh.subscribe(sub);// Turn on all 4 motorsrightFront.setSpeed(200);rightFront.run(RELEASE);leftFront.setSpeed(200);leftFront.run(RELEASE);leftBack.setSpeed(200);leftBack.run(RELEASE);rightBack.setSpeed(200);rightBack.run(RELEASE);
}

初始化节点、车轮速度等。

void loop() {nh.spinOnce();switch (cmd_ctrl){case 2: {Serial.print("Go Forward!\n");//delay(1000);rightFront.setSpeed(116);leftFront.setSpeed(116);leftBack.setSpeed(116);rightBack.setSpeed(116);rightFront.run(FORWARD);leftFront.run(FORWARD);leftBack.run(FORWARD);rightBack.run(FORWARD);delay(1000);rightFront.run(RELEASE);leftFront.run(RELEASE);leftBack.run(RELEASE);rightBack.run(RELEASE);break;}case -2:{Serial.print("Go Backward!\n");//delay(1000);rightFront.setSpeed(116);leftFront.setSpeed(116);leftBack.setSpeed(116);rightBack.setSpeed(116);rightFront.run(BACKWARD);leftFront.run(BACKWARD);leftBack.run(BACKWARD);rightBack.run(BACKWARD);delay(1000);rightFront.run(RELEASE);rightBack.run(RELEASE);leftFront.run(RELEASE);leftBack.run(RELEASE);break;}case 6:{Serial.print("Turn Left!\n");//delay(1000);rightFront.setSpeed(116);rightFront.run(FORWARD);rightBack.setSpeed(116);rightBack.run(FORWARD);leftFront.setSpeed(18);leftFront.run(BACKWARD);leftBack.setSpeed(18);leftBack.run(BACKWARD);delay(1000);rightFront.run(RELEASE);rightBack.run(RELEASE);leftFront.run(RELEASE);leftBack.run(RELEASE);break;}case -6:{Serial.print("Turn Right!");//delay(1000);rightFront.setSpeed(18);rightFront.run(BACKWARD);rightBack.setSpeed(18);rightBack.run(BACKWARD);leftFront.setSpeed(116);leftFront.run(FORWARD);leftBack.setSpeed(116);leftBack.run(FORWARD);delay(1000);rightFront.run(RELEASE);rightBack.run(RELEASE);leftFront.run(RELEASE);leftBack.run(RELEASE);break;}default:{//delay(1000);rightFront.run(RELEASE);rightBack.run(RELEASE);leftFront.run(RELEASE);leftBack.run(RELEASE);delay(1000);    break;}
}rightFront.run(RELEASE);rightBack.run(RELEASE);leftFront.run(RELEASE);leftBack.run(RELEASE);cmd_ctrl = 0;
}

当接收到右转消息时,内轮速度设为18,外轮速度设置为116;左转同理。

硬件连接

将电机驱动板L293D和Arduino板的相应接口(数字一一对应)通过杜邦线连接起来,具体针脚连接方式如下:

如果只想使用直流/步进电机应该连接以下引脚:

  • 数字端口11:直流电机#1/步进#1(PWM)
  • 数字端口 3:直流电机#2/步进#1(PWM)
  • 数字端口 5:直流电机#3/步进#2(PWM)
  • 数字端口 6:直流电机#4/步进#2(PWM)

如果要控制直流/步进电机应该增加以下引脚:

  • 数字引脚4:DIR CLK触发
  • 数字引脚7:DIR EN指令的允许端EN
  • 数字引脚8:DIR SER
  • 数字引脚12:DIR ATCH中断连接

另外,GND、5V引脚必须也要连接,否则的话就无法稳定地控制直流电动机。

具体接线图如下所示:

NOTE:当然如果你的Arduino上不连接其他传感器的话,你可以直接将L293D直接”骑“到Arduino板子上,即所有对应的引脚都连接起来,这种方法比较简单但是所有的引脚都被占用了。

测试你的代码

首先在你的Arduino编译并上传写好的代码,然后运行下面的命令以指定串口来连接Arduino板。
note:在运行节点之前别忘了启动节点管理器(roscore)。

rosrun rosserial_python serial_node.py /dev/ttyACM0

最后一个参数要根据你在Arduino IDE中选择的串口而定,这里我们使用的是ACM0。
接着运行:

rosrun turtlesim turtle_teleop_key

使用方向键你就可以自由地控制你的机器人了。

后记

本文只是介绍实现对差速轮式机器人的简单控制,无法实现精准的控制。如要更深入的学习请参考ROS的官方wiki。本文中的示例代码可以在这里下载。

参考资料

  1. 杨俊驹,林睿,等.轮式移动机器人运动控制系统研究与设计[J].苏州大学:现代电子技术,2016,39(2):23-27.
  2. ROS Wiki: rosserial_arduino Tutorials
  3. adafruit.com: Using DC Motors


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

在ROS中通过Arduino实现对4WD轮式机器人的简单控制相关推荐

  1. python中load_iris_在python中利用KNN实现对iris进行分类的方法

    如下所示: from sklearn.datasets import load_iris iris = load_iris() print iris.data.shape from sklearn.c ...

  2. Keycloak简单几步实现对Spring Boot应用的权限控制,程序员Java基础案例教程

    关注并星标 码农小胖哥,第一时间获取相关干货文章. 客户端 === 相信不少同学用过微信开放平台.蚂蚁开放平台.首先我们需要在这些开放平台上注册一个客户端以获取一套类似用户名和密码的凭证.有的叫app ...

  3. ROS中阶笔记(八):机器人SLAM与自主导航—机器人自主导航

    ROS中阶笔记(八):机器人SLAM与自主导航-机器人自主导航 文章目录 1 ROS中的导航框架 1.1 move_base 1.1.1 基于move_base的导航框架 1.1.2 安装 1.2.3 ...

  4. ROS中阶笔记(六):机器人感知—机器语音

    ROS中阶笔记(六):机器人感知-机器语音 文章目录 1 语音识别理论 2 常用语音功能包 3 科大讯飞SDK 3.1 使用前提 3.2 语音听写 3.3 语音合成 3.4 智能语音助手 4 参考资料 ...

  5. ROS中阶笔记(七):机器人SLAM与自主导航—SLAM功能包的使用

    ROS中阶笔记(七):机器人SLAM与自主导航-SLAM功能包的使用 文章目录 1 机器人必备条件 1.1 硬件要求 1.2 深度信息 1.2.1 激光雷达 1.2.2 kinect 1.3 里程计信 ...

  6. ROS中阶笔记(五):机器人感知—机器视觉

    ROS中阶笔记(五):机器人感知-机器视觉 文章目录 1 ROS中的图像数据 1.1 二维图像 1.1.1 安装安装usb_cam 1.1.2 显示图像数据 1.2 三维图像(kinect) 2 摄像 ...

  7. ROS中阶笔记(四):机器人仿真—Gazebo物理仿真环境搭建(重点)

    ROS中阶笔记(四):机器人仿真-Gazebo物理仿真环境搭建(重点) 文章目录 1 ros_control 1.1 ros_control安装 2 Gazebo仿真步骤(重点) 2.1 配置物理仿真 ...

  8. ROS中阶笔记(三):机器人仿真—ArbotiX+rviz功能仿真

    ROS中阶笔记(三):机器人仿真-ArbotiX+rviz功能仿真 文章目录 01 机器人URDF模型优化-xacro模型文件 1.1 xacro模型文件 1.2 xacro使用方法 1.3 模型显示 ...

  9. ROS中阶笔记(二):机器人系统设计—URDF机器人建模

    ROS中阶笔记(二):机器人系统设计-URDF机器人建模 文章目录 01 URDF理论 1.1 什么是URDF 1.2 模型< robot > 1.2.1 < link > e ...

最新文章

  1. 谢文睿:西瓜书 + 南瓜书 吃瓜系列 5. 决策树
  2. Dubbo源码学习总结系列三 dubbo-cluster集群模块
  3. 得到按钮句柄后如何点集_RepPoint:可形变卷积生成的目标轮廓点集
  4. ubuntu7.10中的apache的一些设置
  5. Redis 5.0.8+常见面试题(单线程还是多线程、先更新缓存还是数据库、雪崩穿透击穿解决办法...)
  6. Number Sequence hdu1005
  7. matlab 多属性权重,多属性决策的权重确定方法及matlab 程序
  8. 【流程发现算法概述】
  9. win10u盘被写保护怎么解除_磁盘被写保护怎么解除,小编告诉你如何解决U盘磁盘被写保护...
  10. BZOJ3505 CQOI2014数三角形(组合数学)
  11. YUV420P像素数据编码为JPEG图片
  12. vmstate内存事件详解
  13. Mybatis学习笔记(上)
  14. BZOJ4598: [Sdoi2016]模式字符串
  15. 反馈纠错机制在学习中的重要性
  16. bing词典案例分析
  17. Google Chrome 66 稳定版更新:修复四大严重安全漏洞
  18. H5 canvas pc 端米字格 写字板
  19. Sanic 接收前端post 提交的json数据
  20. Chrome 键盘快捷键

热门文章

  1. 做app兼容性测试时如何挑选机型
  2. Flask(1) | Flask的部署
  3. 关于利用RD client远程电脑,和输入法的一些问题
  4. php音乐链接,用PHP获取虾米音乐网的下载链接_php
  5. JavaScript Promise 教程 - 如何在 JS 中解决或拒绝 Promise
  6. 数据结构单链表实现班级考勤管理系统
  7. AI种黄瓜大赛,微软击败腾讯、英特尔夺冠
  8. 初步14-字母及编码
  9. SubSurface 和SubSurface Profile
  10. Google Earth Engine(GEE)——利用MODIS 的叶面积指数影像掩膜dem批量下载