ROS MELODIC 多線程 發佈與訂閱

ROS  MELODIC  多線程 發佈與訂閱

這裏我只把代碼貼出來,裏面使用的boost::bind函數在傳指針或引用參數時,會傳不過去,試了很多遍了,網上查了很多資料也不行,這裏使用bind函數把回調函數傳給 node.advertise  或者node.subscribe 函數時,會有問題,會報no match 錯誤,個人C++也學得不很很好,所以這裏只用試試的心態,勿噴。。這裏只貼代碼,沒有什麼註釋,代碼可以運行,CMakeFile.txt 我就不加了,僅供參考。。

dbh_thread.h

#ifndef DBH_THREAD_H__
#define DBH_THREAD_H__

#include <ros/ros.h>
#include <ros/forwards.h>
#include <boost/thread.hpp>
#include <sstream>

#include <std_msgs/UInt16.h>
#include <std_msgs/String.h>

#define TP_SET_L_SPD "mtr_set_L_speed"        // 設置電機左右輪速度
#define TP_SET_R_SPD "mtr_set_R_speed"

#define TP_SET_EN "mtr_set_en"            // 電機使能
#define TP_SET_IO "mtr_set_io"            // 電機IO
#define TP_CLR_ALM "mtr_clr_alm"          // 清除電機警告

#define TP_GET_ENC_L "mtr_get_L_enc"      // 獲取左右輪編碼器
#define TP_GET_ENC_R "mtr_get_R_enc"

#define TP_GET_IO "mtr_get_io"
#define TP_GET_BAT "mtr_get_batt"        // 電池
#define TP_GET_ALM "mtr_get_alm"

#define TIME_DUR_1HZ    1
#define TIME_DUR_5HZ    0.2
#define TIME_DUR_10HZ   0.1
#define TIME_DUR_30HZ   0.03

class dbh_thread{
public:
    // 實始多多個進程
    dbh_thread(){
        sub_L_spd = nh.subscribe(TP_SET_L_SPD, 50, &dbh_thread::set_L_speed_cb, this);
        sub_R_spd = nh.subscribe(TP_SET_R_SPD, 50, &dbh_thread::set_R_speed_cb, this);
        sub_clr_alm = nh.subscribe(TP_CLR_ALM, 50, &dbh_thread::clr_alm_cb, this);
        sub_set_io = nh.subscribe(TP_SET_IO, 50, &dbh_thread::set_io_cb, this);
        sub_set_en = nh.subscribe(TP_SET_EN, 50, &dbh_thread::set_en_brk_cb, this);

        // 發佈者
        pub_L_enc = nh.advertise<std_msgs::UInt16>(TP_GET_ENC_L, 1000, 
                            boost::bind(&dbh_thread::L_enc_conn, this, _1 ),
                            boost::bind(&dbh_thread::L_enc_discon, this, _1)  );
        pub_R_enc = nh.advertise<std_msgs::UInt16>(TP_GET_ENC_R, 1000, 
                            boost::bind(&dbh_thread::R_enc_conn, this, _1), 
                            boost::bind(&dbh_thread::R_enc_discon, this,  _1 )  );
        pub_get_batt = nh.advertise<std_msgs::UInt16>(TP_GET_BAT, 1000, 
                            boost::bind(&dbh_thread::get_batt_conn,this, _1 ), 
                            boost::bind(&dbh_thread::get_batt_discon,this,  _1 )  );
        pub_get_io = nh.advertise<std_msgs::UInt16>(TP_GET_IO, 1000, 
                            boost::bind(&dbh_thread::get_io_conn,this, _1 ), 
                            boost::bind(&dbh_thread::get_io_discon,  this, _1 )  );
        pub_get_alm = nh.advertise<std_msgs::UInt16>(TP_GET_ALM, 1000, 
                            boost::bind(&dbh_thread::get_alm_conn,this, _1 ), 
                            boost::bind(&dbh_thread::get_alm_discon, this,  _1)  );
        
        //  初始化定器,定時發佈消息
        tm_L_enc = nh.createTimer(ros::Duration(TIME_DUR_1HZ),                              //  TIME_DUR_30HZ
                            boost::bind(&dbh_thread::L_enc_tm_cb,this, _1 ), false, false);
        tm_R_enc = nh.createTimer(ros::Duration(TIME_DUR_1HZ),                              //  TIME_DUR_30HZ
                            boost::bind(&dbh_thread::R_enc_tm_cb,this, _1 ), false, false);
        tm_get_batt = nh.createTimer(ros::Duration(TIME_DUR_1HZ),                          //  TIME_DUR_1HZ
                            boost::bind(&dbh_thread::get_batt_tm_cb,this, _1 ), false, false);
        tm_get_io = nh.createTimer(ros::Duration(TIME_DUR_1HZ),                              //  TIME_DUR_10HZ
                            boost::bind(&dbh_thread::get_io_tm_cb,this, _1 ), false, false);
        tm_get_alm = nh.createTimer(ros::Duration(TIME_DUR_1HZ),                           //  TIME_DUR_10HZ
                            boost::bind(&dbh_thread::get_alm_tm_cb,this, _1 ), false, false);                                              
    }

    //  發佈者回調
    void set_L_speed_cb(const std_msgs::UInt16 &msg);
    void set_R_speed_cb(const std_msgs::UInt16 &msg);
    void set_en_brk_cb(const std_msgs::UInt16 &msg);
    void set_io_cb(const std_msgs::UInt16 &msg);
    void clr_alm_cb(const std_msgs::UInt16 &msg);

    void L_enc_tm_cb(const ros::TimerEvent &tmEvt);
    void L_enc_conn(const ros::SingleSubscriberPublisher &pub);
    void L_enc_discon(const ros::SingleSubscriberPublisher &pub);

    void R_enc_tm_cb(const ros::TimerEvent &tmEvt);        // 定時器加回調
    // 有訂閱者與發佈者連接時的回調, 回調裏面會打開定時器,定時發佈消息
    void R_enc_conn(const ros::SingleSubscriberPublisher &pub);    
    // 有訂閱者與發佈者斷開連接時的回調, 回調裏面會暫時定時器,暫停定時發佈消息
    void R_enc_discon(const ros::SingleSubscriberPublisher &pub);

    void get_batt_tm_cb(const ros::TimerEvent &tmEvt);
    void get_batt_conn(const ros::SingleSubscriberPublisher &pub);
    void get_batt_discon(const ros::SingleSubscriberPublisher &pub);

    void get_io_tm_cb(const ros::TimerEvent &tmEvt);
    void get_io_conn(const ros::SingleSubscriberPublisher &pub);
    void get_io_discon(const ros::SingleSubscriberPublisher &pub);

    void get_alm_tm_cb(const ros::TimerEvent &tmEvt);
    void get_alm_conn(const ros::SingleSubscriberPublisher &pub);
    void get_alm_discon(const ros::SingleSubscriberPublisher &pub);

//private:
    ros::NodeHandle nh;

    ros::Subscriber sub_L_spd;
    ros::Subscriber sub_R_spd;
    ros::Subscriber sub_clr_alm;
    ros::Subscriber sub_set_io;
    ros::Subscriber sub_set_en;

    ros::Publisher pub_L_enc;
    ros::Publisher pub_R_enc;
    ros::Publisher pub_get_batt; 
    ros::Publisher pub_get_io; 
    ros::Publisher pub_get_alm; 

    ros::Timer tm_L_enc;
    ros::Timer tm_R_enc;
    ros::Timer tm_get_batt;
    ros::Timer tm_get_io;
    ros::Timer tm_get_alm;

}; //End of class SubscribeAndPublish

#undef TP_SET_L_SPD
#undef TP_SET_R_SPD 

#undef TP_SET_EN 
#undef TP_SET_IO 
#undef TP_CLR_ALM

#undef TP_GET_ENC_L 
#undef TP_GET_ENC_R 

#undef TP_GET_IO
#undef TP_GET_BAT 

#undef TIME_DUR_1HZ
#undef TIME_DUR_5HZ    
#undef TIME_DUR_10HZ   
#undef TIME_DUR_30HZ   

#endif // !DBH_THREAD_H__

dbh_thread.cpp


#include <ros/ros.h>
#include <sstream>
#include <boost/thread.hpp>
#include <std_msgs/UInt16.h>
#include "motor.h"
#include "dbh_thread.h"
// pub_test(pub, code, 1);
void pub_test(ros::Publisher & pub, std_msgs::UInt16  &code, uint16_t data){
    code.data = data;
    pub.publish(code);
}

void dbh_thread::set_L_speed_cb(const std_msgs::UInt16 &msg){
    ROS_INFO("set_L_speed_cb [%x]", msg.data);
    //ros::Rate loop_rate(30); 

    motor_set_L_speed(msg.data);
    //loop_rate.sleep();
}

void dbh_thread::set_R_speed_cb(const std_msgs::UInt16 &msg){
    ROS_INFO("set_R_speed_cb [%x]", msg.data);
    //ros::Rate loop_rate(30); 

    motor_set_R_speed(msg.data);
    //loop_rate.sleep();
}

void dbh_thread::set_en_brk_cb(const std_msgs::UInt16 &msg){
    ROS_INFO("set_en_brk_cb [%x]", msg.data);
    //ros::Rate loop_rate(30); 

    motor_set_enable(msg.data);
    // loop_rate.sleep();
}

void dbh_thread::set_io_cb(const std_msgs::UInt16 &msg){
    ROS_INFO("set_io_cb [%x]", msg.data);
    // ros::Rate loop_rate(30); 

    motor_set_io(msg.data);
    // loop_rate.sleep();
}

void dbh_thread::clr_alm_cb(const std_msgs::UInt16 &msg){
    ROS_INFO("clr_alm_cb [%x]", msg.data);
    motor_clr_alarm(msg.data);
}

void dbh_thread::L_enc_tm_cb(const ros::TimerEvent &tmEvt){
    std_msgs::UInt16  code;
    ROS_INFO("L_enc_tm_cb");
    if(motor_get_L_encode(&code.data)){
        pub_L_enc.publish(code);
    }
    pub_test(pub_L_enc, code, 1);
}

void dbh_thread::L_enc_conn(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("L_enc_conn");
    tm_L_enc.start();
} 

void dbh_thread::L_enc_discon(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("L_enc_discon");
    tm_L_enc.stop();
}

void dbh_thread::R_enc_tm_cb(const ros::TimerEvent &tmEvt){
    std_msgs::UInt16  code;
    ROS_INFO("R_enc_tm_cb");
    if(motor_get_R_encode(&code.data)){
        pub_R_enc.publish(code);
    }
    pub_test(pub_R_enc, code, 2);
}

void dbh_thread::R_enc_conn(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("R_enc_conn");
    tm_R_enc.start();
} 

void dbh_thread::R_enc_discon(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("R_enc_discon");
    tm_R_enc.stop();
}

void dbh_thread::get_batt_tm_cb(const ros::TimerEvent &tmEvt){
    std_msgs::UInt16  code;
    ROS_INFO("get_batt_tm_cb");
    if(motor_get_batt(&code.data)){
        pub_get_batt.publish(code);
    }
    pub_test(pub_get_batt, code, 3);
}

void dbh_thread::get_batt_conn(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("get_batt_conn");
    tm_get_batt.start();
} 

void dbh_thread::get_batt_discon(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("get_batt_discon");
    tm_get_batt.stop();
}

void dbh_thread::get_io_tm_cb(const ros::TimerEvent &tmEvt){
    std_msgs::UInt16  code;
    ROS_INFO("get_io_tm_cb");
    if(motor_get_io(&code.data)){
        pub_get_io.publish(code);
    }
    pub_test(pub_get_io, code, 4);
}

void dbh_thread::get_io_conn(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("get_io_conn");
    tm_get_io.start();
} 

void dbh_thread::get_io_discon(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("get_io_discon");
    tm_get_io.stop();
}

void dbh_thread::get_alm_tm_cb(const ros::TimerEvent &tmEvt){
    std_msgs::UInt16  code;
    ROS_INFO("get_alm_tm_cb");
    if(motor_get_alarm(&code.data)){
        pub_get_alm.publish(code);
    }
    pub_test(pub_get_alm, code, 5);
}

void dbh_thread::get_alm_conn(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("get_alm_conn");
    tm_get_alm.start();
} 

void dbh_thread::get_alm_discon(const ros::SingleSubscriberPublisher &pub){
    ROS_INFO("get_alm_discon");
    tm_get_alm.stop();
}

main.cpp

#include <ros/ros.h>
#include <pthread.h>
#include "dbh_thread.h"

int main(int argc, char **argv)
{
    //初始化節點
    ros::init(argc, argv, "dbh_serial_node");
    ros::Time::init();    // 這句看見ros demo 代碼裏面 在使用 ros::Duration(0.1)之前進行了初始化
                          // 加上在說
    //聲明節點句柄
    //ros::NodeHandle nh;

    dbh_thread thread;

    ros::MultiThreadedSpinner s; // 使用多線程
    ros::spin(s);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章