imu得到串口数据

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;
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容