imu得到串口数据

2019-12-23  本文已影响0人  送分童子笑嘻嘻

imu_driver.cc

//
// Created by cai on 19-10-8.
//

#include "imu_driver.h"
#include "common.h"
#include <math.h>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

//数据的处理我是放在子线程还是放在主线程呢,雷达人家是放在子线程,所以我也放子线程,主线程就干拷贝的事吧
namespace cartographer {
    namespace src {

        imuDriver::imuDriver() :
                _serial(0) {
            //正确数量
            head_num = 2;
            com_num = 1;
            data_num = 14;
            IMU_node_buf = new IMU_DATA_PACKAGE();
            // vector<IMU_DATA> *testimu = new vector<IMU_DATA>;
            vector<IMU_DATA> testimu;

        }

        imuDriver::~imuDriver() {

            if (_serial) {
                if (_serial->isOpen()) {
                    _serial->flush();
                    _serial->closePort();
                }
            }

            if (_serial) {
                delete _serial;
                _serial = NULL;
            }
            if (IMU_node_buf) {
                delete IMU_node_buf;
                IMU_node_buf = NULL;
            }
            _thread.join();
        }


//处理具体数据
        void imuDriver::dealData(IMU_DATA &data, vector<uint8_t> &datapackage) {
            //cout << "imuDriver::dealData" << endl;

            for (int i = 0; i < data_num / 2; ++i) {
                int8_t a = (int8_t) datapackage[(2 * i)];
                int8_t b = (int8_t) datapackage[(2 * i) + 1];
                int16_t new_ac_int;
                //这个强转会出问题
                //bc是后面的,所以要加判断
                int16_t bc;
                if (b < 0) {
                    uint8_t b8 = (1 << 7) + b;
                    bc = (int16_t) b8;
                    bc += (1 << 7);
                } else {
                    bc = (int16_t) b;
                }
                int16_t ac = (int16_t) a;
                new_ac_int = (ac << 8);
                new_ac_int += bc;
                float new_ac = (float) (new_ac_int);
                new_ac /= 100;
               // cout << new_ac << "____";
                if (i == 0) {
                    data.XLH = new_ac;
                } else if (i == 1) {
                    data.YLH = new_ac;
                } else if (i == 2) {
                    data.ZLH = new_ac;
                } else if (i == 3) {
                    data.XAH = new_ac;
                } else if (i == 4) {
                    data.YAH = new_ac;
                } else if (i == 5) {
                    data.ZAH = new_ac;
                } else if (i == 6) {
                    data.YawAH = new_ac;
                }
            }
            //cout << "imuDriver::dealData" << endl;
        }

        void imuDriver::dealAllData(uint8_t *source, size_t t, IMU_DATA_PACKAGE *package) {
            //判断是否开始一个帧,数据流失怎么办,只要读到FH就要从头开始,每次读一大段数据,没有校验位
            cout << "begin dealAllData" << endl;
            int head_isok = is_no;
            int com_isok = is_no;
            int data_is_right = 0;
            int now_head_num = 0;
            int now_com_num = 0;
            int now_data_num = 0;
            //当前包中相应数据的数量
            //用长度来校验,数据位是14个字节,只要命令帧后不是14个字节,这个数据包就丢掉
            vector<uint8_t> datapackage;
            for (int i = 0; i < t; ++i) {
                if (source[i] == FH && now_data_num == 0) {
                    datapackage.clear();
                    if (i >= 1 && source[i - 1] == FH) {
                        head_isok = is_ok;
                    } else {
                        head_isok = is_no;
                    }
                } else if (source[i] == ComNum && now_data_num == 0) {
                    if (i >= 2 && source[i - 1] == FH) {
                        com_isok = is_ok;
                    } else {
                        com_isok = is_no;
                    }
                } else if (source[i] == Len && now_data_num == 0) {
                    continue;
                } else {
                    //校验位进这个逻辑
                    if (now_data_num == 14) {
                        now_data_num = 0;
                        continue;
                    }
                    if (com_isok == is_ok && head_isok == is_ok) {
                        now_data_num++;
                        //装数据的包,默认数据是14个
                        datapackage.push_back(source[i]);
                        if (now_data_num == data_num) {
                            IMU_DATA data;
                            dealData(data, datapackage);
                            testimu.push_back(data);
                        }
                    }

                }

            }

        };

        size_t imuDriver::doProcessSimple(vector<IMU_DATA> *package) {
            //清空合宿据
            package->clear();
            //拷贝数据
            for (int j = 0; j < this->testimu.size(); ++j) {
                package->push_back(testimu[j]);
            }
            unsigned long i = package->size();
            if (i > 0) {
                //拷贝到数据后就赋值
                testimu.clear();
                return true;
            } else {
                return false;
            }
        }

        result_t imuDriver::getDatafromSerial(uint8_t *data, size_t size) {
            if (!m_isConnected) {
                return RESULT_FAIL;
            }
            size_t r;
            //这个循环的逻辑是让_serial把数据读完
            cout << " getDatafromSerial size=" << size << endl;
            while (size) {
                r = _serial->read(data, size);
                cout << "r = _serial->read(data, size); r=" << r << endl;
                if (r < 1) {
                    return RESULT_FAIL;
                }
                size -= r;
                data += r;
            }
            return RESULT_OK;
        }

        result_t imuDriver::connect(const char *port_path, uint32_t baudrate) {
            SerialBaudrate = baudrate;
            port = string(port_path);
            ScopedLocker lk(_serial_lock);
            //看来换了接口,序列没创建成功
            cout << "port=" << port << endl;
            cout << "SerialBaudrate=" << SerialBaudrate << endl;

            if (!_serial) {
                _serial = new Serial(port, SerialBaudrate,
                                     Timeout::simpleTimeout(4000));
            }
            //错误定位在串口没有打开
            if (!_serial->open()) {
                cout << "serial can not connect" << endl;
                return RESULT_FAIL;
            } else {
                cout << "serial can  connect" << endl;
            }
            trans_delay = _serial->getByteTime();
            m_isConnected = true;

//        delay(50);
//        clearDTR();

            return RESULT_OK;
        }

        bool imuDriver::turnOn() {
            cout << "begin turnOn" << endl;
            // start scan...
            result_t op_result = this->startGet();

            if (!IS_OK(op_result)) {
                fprintf(stderr, "[imuDriver] Failed to start scan mode: %x\n", op_result);
                return false;
            }
            return true;
        }

        result_t imuDriver::startGet() {
            cout << "begin startGet" << endl;
            result_t ans;
            ans = this->createThread();
            return ans;

        }

        result_t imuDriver::createThread() {
            cout << "begin createThread" << endl;
            _thread = CLASS_THREAD(imuDriver, cacheScanData);

            if (_thread.getHandle() == 0) {
                m_isGetting = false;
                return RESULT_FAIL;
            }

            m_isGetting = true;
            return RESULT_OK;
        }

        int imuDriver::cacheScanData() {
            cout << "begin cacheScanData" << endl;
            while (true) {
                ScopedLocker l(_serial_lock);
                flush();
                size_t t = 200;
                uint8_t recvBuffer[t];
                result_t ans = getDatafromSerial(recvBuffer, t);
                if (ans < 0) {
                    cout << "getDatafromSerial Fail" << endl;
                    return RESULT_FAIL;
                }
                //cout << "recvBuffer=" << recvBuffer << endl;
                dealAllData(recvBuffer, t, IMU_node_buf);
                cout << "behind dealAllData then testimu.size()=" << testimu.size() << endl;
            }
            if (testimu.size() > 0) {
                return RESULT_OK;
            } else {
                return RESULT_FAIL;
            }
        }

        void imuDriver::flush() {
            if (!m_isConnected) {
                return;
            }

            if (_serial) {
                _serial->flush();
            }

            delay(30);
        }


        void imuDriver::setDTR() {
            if (!m_isConnected) {
                return;
            }

            if (_serial) {
                _serial->flush();
                _serial->setDTR(1);
            }

        }

        void imuDriver::clearDTR() {
            if (!m_isConnected) {
                return;
            }

            if (_serial) {
                _serial->flush();
                _serial->setDTR(0);
            }
        }
    }
}

imu_driver.h

//
// Created by cai on 19-10-6.
//

#ifndef SRC_IMU_DRIVER_H
#define SRC_IMU_DRIVER_H
#include <stdlib.h>
#include "serial.h"
#include "locker.h"
#include "thread.h"
#include "imu_protocol.h"
#include <string>
#endif //SRC_IMU_DRIVER_H
using namespace std;
namespace cartographer {
    namespace src {

        class imuDriver {
        public:
            /**
            * A constructor.
            * A more elaborate description of the constructor.
            */
            imuDriver();

            /**
            * A destructor.
            * A more elaborate description of the destructor.
            */
            virtual ~imuDriver();

            /**/
            void getRealData(const uint8_t a, const uint8_t b, uint16_t *new_ac);

            /**/
            void dealData(IMU_DATA &data, vector<uint8_t> &datapackage);

            /*
             * 将串口读取到的原始数据转换为可以赋给ros节点的数据
             * */
            void dealAllData(uint8_t *test, size_t t, IMU_DATA_PACKAGE *package);

            /*获得ros节点可用的数据包*/
            size_t doProcessSimple(vector<IMU_DATA> *ppackage);

            /*从串口缓存获取数据*/
            result_t getDatafromSerial(uint8_t *data, size_t size);

            /*连接串口*/
            result_t connect(const char *port_path, uint32_t baudrate);

            /*从子线程的串口中获得数据*/
            bool turnOn();

            /*开始获得接受数据*/
            result_t startGet();

            /*开启线程获得数据*/
            result_t createThread();

            /*线程中缓存数据的方法*/
            int cacheScanData();

            /*清空缓存区的数据*/
            void flush();

            /*拷贝缓存中的数据*/
            result_t copyBuffData(IMU_DATA_PACKAGE *nodebuffer);

            /*DTR是data terminal ready*/
            void setDTR();

            /**/
            void clearDTR();


            bool m_isGetting;   ///< 扫图状态
            IMU_DATA_PACKAGE *IMU_node_buf;  ///< 激光点信息
            vector<IMU_DATA> testimu;
        private:
            Serial *_serial;            ///< 串口
            //正确数量
            int head_num;
            int com_num;
            int data_num;
            string port;
            int SerialBaudrate;
            IMU_DATA *data;
            Locker _serial_lock;        ///< 串口锁
            Locker _lock;                ///< 线程锁
            Thread _thread;                ///< 线程id
            int trans_delay;
            bool m_isConnected = true;

        };
    }
}

imu_protocol.h

#pragma once

#include "v8stdint.h"
#include <vector>

#define SUNNOISEINTENSITY 0xff
#define GLASSNOISEINTENSITY 0xfe

#if defined(_WIN32)
#pragma pack(1)
#endif
/*
 * 指令说明
 * */
#define FH 0xAA
#define ComNum 0x02
#define Len 0x0E
#define is_ok 1
#define is_no 0
//imu数据
struct IMU_DATA {
    //X轴加速度H
    float XLH;
    //Y轴加速度H
    float YLH;
    //Z轴加速度H
    float ZLH;
    //X轴角速度H
    float XAH;
    //Y轴角速度H
    float YAH;
    //Z轴角速度H
    float ZAH;
    //Yaw偏航角H
    float YawAH;
};

struct IMU_DATA_PACKAGE {
    //! Array of laser point
    std::vector<IMU_DATA> data;
};

struct node_packages {
    uint16_t package_Head;
    uint16_t package_com;
    uint16_t XLH;
    uint16_t YLH;
    uint16_t ZLH;
    uint16_t XAH;
    uint16_t YAH;
    uint16_t ZAH;
    uint16_t YawAH;
} ;

imu_test_main.cc

//
// Created by cai on 19-10-5.
//
#include "serial.h"
#include "cartographer/cartographer_ros/sensor_msg.h"
#include <sstream>
#include "string"
#include "imu_driver.h"
#include "imu_protocol.h"
#include <iostream>
using namespace std;
namespace cartographer {
    namespace src {

        Serial *ser; //声明串口对象
    }
}

int main(int argc, char *argv[]) {
    string port = "/dev/ttyUSB0";
    int baudrate = 115200;
//初始化节点
    printf("imu_nodeimu_nodeimu_nodeimu_nodeimu_node\n");
    printf("imu_nodeimu_nodeimu_nodeimu_nodeimu_node\n");
    printf("imu_nodeimu_nodeimu_nodeimu_nodeimu_node\n");
    printf("imu_nodeimu_nodeimu_nodeimu_nodeimu_node\n");
    //声明节点句柄
    //发布主题, 消息格式使用sensor_msg::Imu标准格式(topic名称,队列长度)
    cartographer::src::imuDriver *imu_driver = new cartographer::src::imuDriver();
    result_t connect = imu_driver->connect(port.c_str(), baudrate);
    if (connect < 0) {
        cout << "IMU can not connect" << endl;
    }
    //开启子线程从串口获得数据然后存到缓存中
    size_t ret = imu_driver->turnOn();
    cout << "ret=" << ret << endl;
    if (!ret) {
        cout << "Failed to start scan mode!!!"  << endl;
        return 0;
    }
    //消息发布频率
    while (1) {
        //cout << "ros::ok()"<<endl;
        vector<IMU_DATA> *package = new vector<IMU_DATA>();
        imu_driver->doProcessSimple(package);
        //cout << "package.size()=" << package->size() << endl;
        for (int i = 0; i < package->size(); ++i) {
            IMU_DATA imu_data;

            //imu_data.header.stamp = ros::Time::now();
            //imu_data.header.frame_id = "laser_frame";
            //imu_data.header.frame_id = "imu_link";
//            float orientation_y = (float)(*package)[i].YawAH;
//
//            float angular_velocity_x = (float)(*package)[i].XAH;
//            float angular_velocity_y = (float)(*package)[i].YAH;
//            float angular_velocity_z = (float)(*package)[i].ZAH;
//
//            float linear_acceleration_x = (float)(*package)[i].XLH;
//            float linear_acceleration_y = (float)(*package)[i].YLH;
//            float linear_acceleration_z = (float)(*package)[i].ZLH;
            ///////////////////////////////////////////////////////////////////
            imu_data.YawAH = (float)(*package)[i].YawAH;

            imu_data.XAH = (float)(*package)[i].XAH;
            imu_data.YAH = (float)(*package)[i].YAH;
            imu_data.ZAH = (float)(*package)[i].ZAH;

            imu_data.XLH = (float)(*package)[i].XLH;
            imu_data.YLH = (float)(*package)[i].YLH;
            imu_data.ZLH = (float)(*package)[i].ZLH;

//            imu_data.orientation.y = 0;
//
//            imu_data.angular_velocity.x = 0;
//            imu_data.angular_velocity.y = 0;
//            imu_data.angular_velocity.z = 0;
//
//            imu_data.linear_acceleration.x = 2;
//            imu_data.linear_acceleration.y = 2;
//            imu_data.linear_acceleration.z = 9;

            cout << imu_data.YawAH <<"______";
            cout << imu_data.XAH <<"______";
            cout << imu_data.YAH <<"______";
            cout << imu_data.ZAH <<"______";
            cout << imu_data.XLH <<"______";
            cout << imu_data.YLH <<"______";
            cout << imu_data.ZLH <<"______";
            cout<< endl;
//            cout << "---------------------"<<endl;
            //发布topic
        }
        delete (package);
        package = NULL;
        //处理ROS的信息,比如订阅消息,并调用回调函数
    }

    return 0;
}

上一篇 下一篇

猜你喜欢

热点阅读