已解决【ROS】roslaunch打开串口报错open_port /dev/ttyUSB0 ERROR!

1 问题描述

在roslaunch节点时,终端报错打开串口失败:
在这里插入图片描述

open_port /dev/ttyUSB0 ERROR!

但是在终端查找串口设备的时候是可以识别到USB0的:

ls /dev/tty*

输出上述命令可以看到会有ttyUSB0,因此问题在于能识别到串口但是无法打开

2 原因分析

在终端中输出命令查看串口设备权限:

cat /dev/ttyUSB0

终端输出:

................permission deny!

定位问题是串口没有可执行权限

3 解决方法

光用chmod +x是不稳定的,因为这样只是给设备短暂的赋予权限,当重新开关机和重新插拔串口设备时,串口的权限可能就会失效了,因此要配置给串口设备赋予永久权限

3.1 创建规则文件

1 前往规则文件夹:

cd /etc/udev/rules.d/

2 创建权限规则文件:

sudo touch 70-ttyUSB.rules

3 修改规则文件可编辑文件:

sudo chmod 666 70-ttyUSB.rules

3.2 添加规则

1 在终端中使用vim打开文件:

vim 70-ttyUSB.rules

2 按 i 后可以进行文件编辑

3 在文件中添加规则:

KERNEL=="ttyUSB*", OWNER="root", GROUP="root", MODE="0666" 

4 按Esc,输出:wq保存文件并退出

5 重启系统完成给串口设备赋予永久权限

参考文章:【笔记】Ubuntu永久获得串口权限

#include <ros/console.h> #include <ros/ros.h> #include <serial/serial.h> #include <iostream> #include <std_msgs/String.h> #include <std_msgs/Empty.h> #include <std_msgs/ByteMultiArray.h> serial::Serial sp;// 回调函数 void write_callback(const std_msgs::String::ConstPtr& msg) { ROS_INFO_STREAM("Writing to serial port " << msg->data); sp.write(msg->data); } int main(int argc, char** argv) { ros::init(argc, argv, "serial_port_servos"); ros::NodeHandle nnode; ros::Subscriber write_sub = nnode.subscribe("write", 1000, write_callback); ros::Publisher read_pub = nnode.advertise<std_msgs::ByteMultiArray>("read", 1000); serial::Timeout to = serial::Timeout::simpleTimeout(100); // 设置要打开串口名称 sp.setPort("/dev/ttyUSB0"); // 设置串口通信的波特率 sp.setBaudrate(9600); // 串口设置timeout sp.setTimeout(to); try { // 打开串口 sp.open(); } catch(serial::IOException& e) { ROS_ERROR_STREAM("Unable to open port."); return -1; } // 判断串口是否打开成功 if(sp.isOpen()) { ROS_INFO_STREAM("/dev/ttyUSB0 is opened."); } else { return -1; } ros::Rate loop_rate(500); while(ros::ok()) { // 获取缓冲区内的字节数 size_t n = sp.available(); if(n != 0) { ROS_INFO_STREAM("Reading from serial port"); uint8_t buffer[1024]; // 读出数据 n = sp.read(buffer, n); std_msgs::ByteMultiArray data; for(int t = 0; i < n; i++) { uint8_t byte; sscanf(&buffer[i], "%2hhx", &byte); data.data.push_back(byte); read_pub.publish(data); /* for(int i = 0; i < n; i++) { // 16进制的方式打印到屏幕 std::cout << std::hex << (buffer[i] & 0xff) << " "; } std::cout << std::endl; // 把数据发送回去 sp.write(buffer, n); */ } ros::spinOnce(); loop_rate.sleep(); } // 关闭串口 sp.close(); return 0; }
05-27
这段代码中的一个错误是在for循环中使用了未定义的变量i,应该将其改为t。另外,还有以下几点需要注意: 1. 在将缓冲区中读取到的数据转换成16进制格式时,应该使用n来控制循环次数,而不是使用i,因为i的值已经在循环中被改变了。 2. 在将每个字节转换成16进制格式时,应该使用"%02x",而不是"%2hhx",因为"%02x"可以保证输出的16进制数始终为两位,如不足两位则在前面补0。 修改后的代码如下: ```cpp #include <ros/console.h> #include <ros/ros.h> #include <serial/serial.h> #include <iostream> #include <std_msgs/String.h> #include <std_msgs/Empty.h> #include <std_msgs/ByteMultiArray.h> serial::Serial sp; void write_callback(const std_msgs::String::ConstPtr& msg) { ROS_INFO_STREAM("Writing to serial port " << msg->data); sp.write(msg->data); } int main(int argc, char** argv) { ros::init(argc, argv, "serial_port_servos"); ros::NodeHandle nnode; ros::Subscriber write_sub = nnode.subscribe("write", 1000, write_callback); ros::Publisher read_pub = nnode.advertise<std_msgs::ByteMultiArray>("read", 1000); serial::Timeout to = serial::Timeout::simpleTimeout(100); // 设置要打开串口名称 sp.setPort("/dev/ttyUSB0"); // 设置串口通信的波特率 sp.setBaudrate(9600); // 串口设置timeout sp.setTimeout(to); try { // 打开串口 sp.open(); } catch(serial::IOException& e) { ROS_ERROR_STREAM("Unable to open port."); return -1; } // 判断串口是否打开成功 if(sp.isOpen()) { ROS_INFO_STREAM("/dev/ttyUSB0 is opened."); } else { return -1; } ros::Rate loop_rate(500); while(ros::ok()) { // 获取缓冲区内的字节数 size_t n = sp.available(); if(n != 0) { ROS_INFO_STREAM("Reading from serial port"); uint8_t buffer[1024]; // 读出数据 n = sp.read(buffer, n); std_msgs::ByteMultiArray data; for(int t = 0; t < n; t++) { uint8_t byte; sscanf(&buffer[t], "%02x", &byte); data.data.push_back(byte); } read_pub.publish(data); } ros::spinOnce(); loop_rate.sleep(); } // 关闭串口 sp.close(); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值