boost多線程與mavlink協議結合實現消息收發
本文將實現boost庫創建多線程,利用mavlink協議進行數據鏈消息打包、解包,解放了很多數據解析的工作,不得不佩服
mavlink協議功能的強大。
boost創建多線程
#include "datalink_base.h"
using namespace std;
using namespace boost;
config_t config;
int main() {
std::cout << "mavlink_datalink start ok." << std::endl;
boost::thread_group threadGroup;
config.uart_name = "/dev/ttyUSB0";
config.baud = 1;
threadGroup.create_thread(thread_send_msg);
threadGroup.create_thread(thread_recv_msg);
threadGroup.join_all();
return 0;
}
頭文件定義
#ifndef MAVLINK_DATALINK_DATALINK_BASE_H
#define MAVLINK_DATALINK_DATALINK_BASE_H
#include <iostream>
#include <string>
#include <boost/thread.hpp>
#include <boost/thread/lock_factories.hpp>
#include <boost/thread/condition.hpp>
using namespace std;
typedef struct config_ {
string uart_name;
int baud;
}config_t;
extern config_t config;
extern void thread_recv_msg(void);
extern void thread_send_msg(void);
#endif
串口類定義
#ifndef MAVLINK_DATALINK_SERIALPORT_HPP
#define MAVLINK_DATALINK_SERIALPORT_HPP
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include "mavlink.h"
using namespace std;
class SerialPort {
public:
SerialPort(string uart_name, speed_t baudrate){
uartName = uart_name;
speedBaud = baudrate;
}
public:
int open_serial_dev() {
int fd_ = 0;
if(uartName.length() == 0){
cout << "devName is NULL." << endl;
return -1;
}
fd_ = open(uartName.c_str(), O_RDWR);
if(fd_ < 0){
fd = fd_;
cout << uartName << " is opened failed." << endl;
return -1;
}else{
fd = fd_;
cout << uartName << " is opened ok." << endl;
}
return fd_;
}
int close_serial()
{
close(fd);
}
void serial_init()
{
if(fd < 0){
cout << "serial_init failed ." << endl;
return;
}
struct termios options;
tcgetattr(fd, &options);
options.c_cflag |= ( CLOCAL | CREAD );
options.c_cflag &= ~CSIZE;
options.c_cflag &= ~CRTSCTS;
options.c_cflag |= CS8;
options.c_cflag &= ~CSTOPB;
options.c_iflag |= IGNPAR;
options.c_iflag &= ~(ICRNL | IXON);
options.c_oflag = 0;
options.c_lflag = 0;
options.c_cflag |= CBAUDEX;
cfsetispeed(&options, speedBaud);
cfsetospeed(&options, speedBaud);
tcsetattr(fd,TCSANOW,&options);
cout << "serial_init ok." << endl;
}
int read_message(mavlink_message_t &message){
int result = 0;
uint8_t ch;
mavlink_status_t status;
uint8_t msgReceived = false;
result = read(fd, &ch, 1);
if(result > 0){
msgReceived = mavlink_parse_char(MAVLINK_COMM_0, ch, &message, &status);
if ( (lastStatus.packet_rx_drop_count != status.packet_rx_drop_count) )
{
printf("ERROR: DROPPED %d PACKETS\n", status.packet_rx_drop_count);
unsigned char v= ch;
fprintf(stderr,"%02x ", v);
}
lastStatus = status;
}
return msgReceived;
}
int send_msg_to_uart(uint8_t * buffer, uint16_t len){
if(len < 0 || len > 512){
return -1;
}
for(int i = 0; i < len; i++){
write(fd, &buffer[i], 1);
}
return 0;
}
public:
string uartName;
speed_t speedBaud;
int fd;
mavlink_status_t lastStatus;
};
#endif
數據鏈發送線程
#include "datalink_base.h"
#include "SerialPort.hpp"
#include "mavlink.h"
using namespace std;
using namespace boost;
void thread_send_msg(void){
bool success;
bool received_all = false;
mavlink_message_t msg ;
mavlink_mission_count_t mission_count;
uint8_t buffer[512] = {};
uint16_t nbytes = 0;
uint8_t system_id = 10;
uint8_t component_id = 100;
std::cout << "thread_send_msg start ok." << endl;
SerialPort serialPort(config.uart_name, B115200);
serialPort.open_serial_dev();
serialPort.serial_init();
mission_count.target_component = 0;
while(1){
mission_count.count = 10;
mission_count.target_system = 2;
mission_count.target_component++;
mission_count.mission_type = 3;
mavlink_msg_mission_count_encode(system_id, component_id, &msg, &mission_count);
nbytes = mavlink_msg_to_send_buffer(buffer, &msg);
serialPort.send_msg_to_uart(buffer, nbytes);
cout << "send msg frame ok." << endl;
sleep(1);
}
}
數據鏈接受線程
#include "datalink_base.h"
#include "SerialPort.hpp"
#include "mavlink.h"
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
void read_messages(SerialPort * serial_port);
void thread_recv_msg(void){
std::cout << "thread_recv_msg start ok." << endl;
bool success;
bool received_all = false;
std::cout << "thread_send_msg start ok." << endl;
SerialPort serialPort(config.uart_name, B115200);
serialPort.open_serial_dev();
serialPort.serial_init();
while(1){
read_messages(&serialPort);
}
}
void read_messages(SerialPort * serial_port){
bool success = false;
bool received_all = false;
int sysid;
int compid;
mavlink_heartbeat_t heartbeat;
mavlink_mission_count_t missionCount;
while ( !received_all) {
mavlink_message_t message;
success = serial_port->read_message(message);
if (success) {
sysid = message.sysid;
compid = message.compid;
cout << "sysid:" << sysid << " compid:" << compid << endl;
switch (message.msgid) {
case MAVLINK_MSG_ID_HEARTBEAT:
mavlink_msg_heartbeat_decode(&message, &heartbeat);
break;
case MAVLINK_MSG_ID_MISSION_COUNT:
mavlink_msg_mission_count_decode(&message, &missionCount);
cout << "mission_type:" << boost::lexical_cast<std::string>((int)missionCount.mission_type)
<< " count:" << boost::lexical_cast<std::string>(missionCount.count)
<< " target_system:" << boost::lexical_cast<std::string>((int)missionCount.target_system)
<< " target_component:" << boost::lexical_cast<std::string>((int)missionCount.target_component) << endl;
break;
}
}
}
return;
}
實驗結果