基于ros---一个完整的实现topic 发布和监听的类和msg的简单使用(使用c++)

首先,需要把ID_Data.msg拷贝到当前包的msg目录内,当然可以直接新建ID_Data.msg文件在msg目录内其内容只有两行如下:
 int32 id
int16[8] data 
然后在CmakeList.txt中添加如下msg编译信息。
 add_message_files(
   [...]
   ID_Data.msg
   [...]
 )
and make sure follow setup:
catkin_package(
  ...
  CATKIN_DEPENDS message_runtime ...
  ...)
这样ros会自动识别msg文件,生成ID_Data.h头文件。若要使用已定义的发布和接收类需要包含如下
#include "beginner_tutorials/ID_Data.h"//using for notie event
其中beginner_tutorials是我ID_Data.msg所在的不同的包要做修改,完整的实现的类如下
class notice_pub_sub
{
public:
    boost::function<void (const beginner_tutorials::ID_Data::ConstPtr&)> notice_pub_sub_msgCallbackFun;


    notice_pub_sub();
    void notice_pub_sub_listener();
    void notice_pub_sub_pulisher(beginner_tutorials::ID_Data id_data);
    void notice_display(beginner_tutorials::ID_Data notice_msg,bool set);
    void notice_sub_spinner(char set);


private:
    ros::NodeHandle notice_handle;
    ros::Subscriber notice_subscriber;
    ros::Publisher notice_publisher;
    ros::SubscribeOptions notice_ops;
    ros::AsyncSpinner *notice_spinner;
    ros::CallbackQueue notice_callbackqueue;
    void notice_msgCallback(const beginner_tutorials::ID_Data::ConstPtr &notice_msg);
};


notice_pub_sub::notice_pub_sub()
{
    notice_pub_sub_msgCallbackFun=boost::bind(&notice_pub_sub::notice_msgCallback,this,_1);
    notice_ops=ros::SubscribeOptions::create<beginner_tutorials::ID_Data>(
                "/notice",
                1,
                notice_pub_sub_msgCallbackFun,
                ros::VoidPtr(),
                &notice_callbackqueue
                );
    notice_subscriber=notice_handle.subscribe(notice_ops);
    notice_spinner=new ros::AsyncSpinner(1,&notice_callbackqueue);


    notice_publisher=notice_handle.advertise<beginner_tutorials::ID_Data>("/notice",1);
}


void notice_pub_sub::notice_pub_sub_listener()
{


}


void notice_pub_sub::notice_pub_sub_pulisher(beginner_tutorials::ID_Data id_data)
{
    notice_publisher.publish(id_data);
}


void notice_pub_sub::notice_display(beginner_tutorials::ID_Data notice_msg,bool set)
{


    if(set)
    {
        printf("REC Notice message,ID: %u,Data: ",notice_msg.id);
        for(char i=0;i<8;i++)
        {
            printf("%u ",notice_msg.data[i]);
            if(i==7) printf("\n");
        }


    }


}
void notice_pub_sub::notice_msgCallback(const beginner_tutorials::ID_Data::ConstPtr ¬ice_msg)
{


    beginner_tutorials::ID_Data notice_message;
    notice_message.id=0;
    for(char i=0;i<8;i++)notice_message.data[i]=0;


    notice_message.id=notice_msg->id;
    for(char i=0;i<8;i++)notice_message.data[i]=notice_msg->data[i];


    notice_pub_sub::notice_display(notice_message,true);//是否显示当前接受到的数据


    if(notice_message.id==1 && notice_message.data[0]==1)//close flag
    {
        close_hand_flag=true;//个人数据接收的处理,请替换
    }
    if(notice_message.id==1 && notice_message.data[0]==0)//open flag
    {
        open_hand_flag=true;//个人数据接收的处理,请替换
    }


}

void notice_pub_sub::notice_sub_spinner(char set)
{
    if(set==1)
        notice_spinner->start();
    if(set==0)
        notice_spinner->stop();
}


使用时先定义类,然后定义数据,注意类的定义不能放在while(ros::ok()){...}循环内,定义完成后,在该片段程序末尾调用notice_test.notice_sub_spinner(1)即可启动回调进程,类似开始在此处处理接受中断,不调用该语句则不会触发notice_msgCallback()中的处理,定义示例如下:
notice_pub_sub notice_test;
beginner_tutorials::ID_Data notice_data_pub;//定义数据类型,最后在定义后进行初始化0操作。
notice_data_pub.id=0;
for(int i=0;i<8;i++)notice_data_pub.data[i]=0;
数据的监听处理都在notice_msgCallback()中实现,示例代码中我定义了两个全局标志,使用时应该注意替换我自己的处理逻辑。
数据发送的过程如下,先填充数据内容,然后调用类成员进行数据广播发送
notice_data_pub.id=1;
notice_data_pub.data[0]=2;
notice_test.notice_pub_sub_pulisher(notice_data_pub);
需要使用ROS中的C++ API来实现话题订阅和UDP数据转发。以下是一个简单的示例程序: ```cpp #include <ros/ros.h> #include <std_msgs/String.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUFLEN 512 #define PORT 8888 int main(int argc, char **argv) { ros::init(argc, argv, "udp_forwarder"); ros::NodeHandle nh; // Create a UDP socket int udp_socket; if ((udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { ROS_ERROR("Failed to create UDP socket"); return 1; } // Configure the UDP socket struct sockaddr_in udp_addr; memset((char *)&udp_addr, 0, sizeof(udp_addr)); udp_addr.sin_family = AF_INET; udp_addr.sin_port = htons(PORT); udp_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(udp_socket, (struct sockaddr *)&udp_addr, sizeof(udp_addr)) == -1) { ROS_ERROR("Failed to bind UDP socket"); return 1; } // Subscribe to the ROS topic ros::Subscriber sub = nh.subscribe("my_topic", 1000, [](const std_msgs::String::ConstPtr& msg) { // Send the message over UDP struct sockaddr_in dest_addr; memset((char *)&dest_addr, 0, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(PORT); dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (sendto(udp_socket, msg->data.c_str(), msg->data.length(), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) == -1) { ROS_ERROR("Failed to send UDP packet"); } }); ros::spin(); return 0; } ``` 在这个示例中,我们使用一个名为“my_topic”的ROS话题来接收数据。当有新的数据到达时,我们将其转发到UDP端口8888上的127.0.0.1。注意,我们在发送数据之前需要先创建一个UDP套接字并进行绑定。在程序退出时,我们使用ros::spin()来保持节点的活动状态,以确保我们能够接收到所有的ROS消息。 为了编译这个程序,您需要在CMakeLists.txt文件中添加以下内容: ``` add_executable(udp_forwarder src/udp_forwarder.cpp) target_link_libraries(udp_forwarder ${catkin_LIBRARIES}) ``` 然后,您可以使用catkin_make命令来编译程序。当您运行这个程序时,它将开始订阅“my_topic话题,并将所有接收到的消息转发到UDP端口8888上的127.0.0.1。您可以在需要接收这些数据的其他节点上运行一个UDP监听器来接收这些数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值