当我们使用ROS的时候,如果条件运行的话,肯定不仅仅只希望在碰不到摸不着的仿真环境中控制机器人,我们往往更希望能够真实地控制机器人,但是ROS和机器人上的嵌入式系统中总是隔着几道屏障,包括软件上的和硬件上的,软件上的屏障可以通过使用ros_control
来跨越,当然你也可以自己编写自己的robot_control来实现与ros_control相同的功能,这篇博文暂时不讲软件这部分的屏障,我们来聊聊跨越硬件上的屏障的一种方式——串口,看完本篇博文,你将了解到如何使用串口让ROS的信息跨过山和大海,来到你的嵌入式系统上。
ros_serial
官方wiki
sudo apt install ros-kinetic-serial
try
{
//设置串口属性,并打开串口
ros_serial.setPort("/dev/ttyUSB0");
ros_serial.setBaudrate(115200);
serial::Timeout to = serial::Timeout::simpleTimeout(1000);
ros_serial.setTimeout(to);
ros_serial.open();
}
catch (serial::IOException& e)
{
ROS_ERROR_STREAM("Unable to open port ");
}
if(ros_serial.isOpen())
{
ROS_INFO("Serial Port initialized");
}
else
{
ROS_ERROR_STREAM("Serial Port fails");
}
pSendBuf
是发送缓存区的地址,len
是发送字符串的长度
if(ros_serial.isOpen())
{
ros_serial.write(pSendBuf,len); /* 用串口发送出去 */
}
上面的内容都是一些很简单的操作,相关的资料也很多,我就不多讲了。
至于这部分,在Linux下操作USB时经常会遇到的权限问题:
首先,Linux与Windows不同,Linux将硬件设备视为一个文件,在/dev
路径下,你可以看到很多像这样的文件:
这些文件实际上的访问这些硬件设备的端口,我们在Linux下将通过访问这些文件来访问对应的硬件设备,综上所述,/dev
路径下的东西很重要,既然这么重要,Linux这么可能让你随随便便的使用呢?
在没有任何处理的前提下,你在代码中操作这些文件,一般只会被没有权限的错误甩一脸。
那么,我们该怎么办呢?
sudo chmod a+rw /dev/ttyUSB0
这种方法最简单粗暴,但是同时缺点也很明显,就是每次运行代码前都得先执行一次这条命令。如果你不嫌麻烦,那么后面两种方法可以忽略掉
使用udev
规则:
sudo gedit /etc/udev/rules.d/70-ttyusb.rules
先创建一个udev
规则文件
再将下面这句添加到文件中
KERNEL=="ttyUSB[0-9]*", MODE="0666"
这就可以将ttyUSB(0~9)十个设备全开了权限
缺点:没有建立一个特定设备对应的特定映射,会出现偶尔找不到设备的现象,比如你在代码打开ttyUSB0
,然而在/dev
只有一个ttyUSB1
udev
的另一种写法:
首先用lsusb查看USB转串口芯片的idVendor和idProduct
lsusb
我现在插入了一个CH340,执行命令后可以在终端中看到下面这条信息
这表示了CH340的idVendor和idProduct分别为:la86和7523
每一个不同厂家的设备会有一个不同的idVendor和idProduct,我们可以利用这一点来实现设备的识别,不过要是同时出现两个同类设备,这个方法就gg了。比如同时插入两个CH340
KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0777", SYMLINK+="mcu_uart"
这时,将方法1中那个文件的内容改为上面这行,保存,注销。
然后将我们的代码改为:
try
{
//设置串口属性,并打开串口
ros_serial.setPort("/dev/mcu_uart");
ros_serial.setBaudrate(115200);
serial::Timeout to = serial::Timeout::simpleTimeout(1000);
ros_serial.setTimeout(to);
ros_serial.open();
}
catch (serial::IOException& e)
{
ROS_ERROR_STREAM("Unable to open port ");
}
if(ros_serial.isOpen())
{
ROS_INFO("Serial Port initialized");
}
else
{
ROS_ERROR_STREAM("Serial Port fails");
}
嗯~一劳永逸