串口通信
本次任务通过ROS实现TX2串口的收发任务,软件开发环境采用的是kDevelop。
环境搭建
- 创建工作空间
wangwen@wangwen-desktop:~$ mkdir -p ~/Robot_developer/src
wangwen@wangwen-desktop:~$ cd ~/Robot_developer/src/
wangwen@wangwen-desktop:~/Robot_developer/src$ catkin_init_workspace
wangwen@wangwen-desktop:~/Robot_developer/src$ cd ~/Robot_developer/
wangwen@wangwen-desktop:~/Robot_developer$ catkin_make
wangwen@wangwen-desktop:~/Robot_developer$ source devel/setup.bash
wangwen@wangwen-desktop:~/Robot_developer$ echo $ROS_PACKAGE_PATH
- 创建功能包
wangwen@wangwen-desktop:~/Robot_developer$ cd ~/Robot_developer/src
wangwen@wangwen-desktop:~/Robot_developer/src$ catkin_create_pkg serial_communication std_msgs rospy roscpp sensor_msgs geometry_msgs tf seril
此时我们已经成功的创建了serial_communication的功能包,在退回工作空间根目录之前,我们需要先打开CMakeLists.txt文件,此文件记录了功能包的编译规则,我们需要对此文件进行修改方可进行后续步骤,其中依赖包seril,是ros官方的串口开发包,使用起来十分方便,使用之前先通过sudo apt-get install ros-< melodic >-serial安装到系统上。
打开功能包的CMakeLists.txt
$ sudo gedit ~/Robot_developer/src/serial_communication/CMakeLists.txt
#这是需要更改的地方,可要在文件中找到对应的地方,在此基础上对其进行修改或添加
add_compile_options(-std=c++11)
include_directories( include ${catkin_INCLUDE_DIRS})
generate_messages(
DEPENDENCIES
std_msgs
sensor_msgs
geometry_msgs
tf
serial
catkin_package(
# INCLUDE_DIRS include
LIBRARIES serial_communication
CATKIN_DEPENDS geometry_msgs roscpp rospy sensor_msgs std_msgs tf serial
)
include_directories( include ${catkin_INCLUDE_DIRS})
add_executable(serial_communication_pub
src/serial_communication_pub.cpp)
target_link_libraries(serial_communication_pub ${catkin_LIBRARIES})
add_executable(serial_communication_sub
src/serial_communication_sub.cpp)
target_link_libraries(serial_communication_sub ${catkin_LIBRARIES})
**学会修改CmakeList.s十分重要 **
- 开发环境搭建
习惯了豪华版的visual studio开发,一上来看kDevelop感觉有点low。
篇幅原因我就不再这里一一对其进行介绍如何进行环境的搭建,大家可以看看好多其他博主的介绍,在这里我只给大家说说可能会在其中踩到坑:
1、在许多博客中会说点击打开工程,选中工作空间中的CmakeList.s,你会发现这个文件是灰色的,根本选择不了。
解决方法:是选中工作空间的src文件夹。
2、在进行Build之前,在功能包中创建一个c++文件,我在CmakeList.s写的是serial.cpp, 创建完成后写入一个基本"Hello World"模板程序.
3、Build成功后会如下图所显示,然后我问进行Execute,
从add中选中我们的Target然后…
最终执行结果如下:
至此可以说我们的软件开发环境已经搭建完成,下面进行程序开发阶段
程序开发
通过建立publish和subscribe建立起在消息之间的通信,在程序中我们建立一个publish的节点”serial_communication_pub“来检测来自串口的信息,一点检测到有内容从串口输入后,publish会将信息采集并进行信息的发布,信息一旦发布,subscribe会得到信息发布的信号,并立即获取publish的内容,然后再将内容发送到输入的串口
程序代码已经附上…
#include "serial_communication/communication.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "serial_communication_pub");
ros::NodeHandle nh;
myserial::Myserial communication;
ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter",1000);
if(!communication.Serial_init())
{
ROS_ERROR("Serial initialized failed!");
return 0;
}
std::string Recbuf;
ros::Rate loop_rate(5);
while(ros::ok())
{
// ROS_INFO("NIHAO");
if(ser.available())
{
ROS_INFO_STREAM("Reading from serial port");
Recbuf=ser.read(ser.available());
std::cout << Recbuf<<std::endl;
std_msgs::String msg;
std::stringstream ss;
ss << Recbuf;
msg.data = ss.str();
chatter_pub.publish(msg);
}
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
#ifndef COMMUNICATION_H
#define COMMUNICATION_H
#include <ros/ros.h>
#include <ros/time.h>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <std_msgs/String.h>
#include <serial/serial.h>
serial::Serial ser; //声明串口对象
//CRC16-MODBUS校验
typedef unsigned char uchar;
typedef unsigned int uint;
uchar crcBuff1200[] = {};
namespace myserial
{
class Myserial
{
public:
bool Serial_init();
private:
};
bool Myserial::Serial_init()
{
try
{
ser.setPort("/dev/ttyTHS2");
ser.setBaudrate(115200);
serial::Timeout to = serial::Timeout::simpleTimeout(1000);
ser.setTimeout(to);
ser.open();
}
catch(serial::IOException& e)
{
ROS_ERROR_STREAM("Unable to open Serial Port!");
return false;
}
if(ser.isOpen())
{
ROS_INFO_STREAM("Serial Port initialized");
return true;
}
else
{
return false;
}
}
}
#endif
#include "serial_communication/communication.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
std::cout << msg->data.c_str() << std::endl;
ser.write(msg->data.c_str());
}
int main(int argc, char**argv)
{
ros::init(argc,argv,"serial_communication_sub");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("chatter",1000,chatterCallback);
myserial::Myserial transform;
if(!transform.Serial_init())
{
ROS_ERROR("Serial initialized failed!");
return 0;
}
ros::spin();
return 0;
}