You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过已创建的ROS节点实现外部C程序向rostopic发布数据?

解决方案

你可以根据现有程序的可修改程度,选择以下三种可行方案实现需求:

方案1:进程间通信适配(无需大幅修改原有C程序)

这种方案适用于不想修改原有ADSB采集C程序核心逻辑的场景,通过进程间传输的方式把数据传递到ROS节点处理:

  • 首先在原有C程序中,将输出的ADSB数据按约定好的结构化格式(比如固定字段分隔的字符串、二进制结构体)输出到标准输出,或写入Unix域套接字、命名管道
  • 在你已创建的ROS发布节点中,持续读取C程序输出的结构化数据,解析后填充到mavros/ADSBVehicle消息字段中,调用publish()接口直接发布即可
  • 如果用匿名管道实现流程最简单,直接在启动时通过shell管道将两个程序绑定即可,示例启动命令:
./你的ADSB采集程序 | rosrun 你的功能包名 你的ROS发布节点名

附C++ ROS节点读取标准输入的核心代码片段:

#include <ros/ros.h>
#include <mavros/ADSBVehicle.h>
#include <iostream>

int main(int argc, char** argv) {
    ros::init(argc, argv, "adsb_publisher");
    ros::NodeHandle nh;
    // *注意latch设为false,避免旧消息缓存,对应你之前遇到的3秒延迟问题*
    ros::Publisher pub = nh.advertise<mavros::ADSBVehicle>("/mavros/adsb/in", 10, false);
    
    std::string line;
    // 持续读取管道输入的ADSB数据
    while (ros::ok() && std::getline(std::cin, line)) {
        mavros::ADSBVehicle msg;
        // 这里按你约定的格式解析line,填充msg的各个字段,比如ICAO地址、经纬度、高度、速度等
        // 示例:msg.header.stamp = ros::Time::now();
        // msg.icao_address = ...;
        pub.publish(msg);
        ros::spinOnce();
    }
    return 0;
}

方案2:C程序功能直接集成进ROS节点(性能最优)

如果可以修改原有C程序的工程结构,推荐直接将C代码集成到ROS节点中,完全省去进程间通信的开销和不稳定因素:

  • 将原有C程序的ADSB采集相关函数封装成独立的C语言库,对外暴露初始化、读取单帧ADSB数据的接口
  • 在ROS C++节点中链接该C库,调用接口直接获取ADSB数据,填充消息后发布即可
  • 注意C代码引用C接口时需要用extern "C"包裹头文件引用,避免C名称修饰导致链接失败:
extern "C" {
#include "你的ADSB采集库头文件.h"
}

方案3:共享内存传输(适合高吞吐量场景)

如果你的ADSB数据输出频率很高,前两种方案满足不了延迟要求,可以用共享内存实现跨进程数据传输,在C程序和ROS节点中分别挂载同一块共享内存空间,C程序写入数据后通过信号量通知ROS节点读取即可。

额外注意事项

  • 消息的时间戳尽量用数据采集的实际时间,如果拿不到采集时间再用ROS节点读取数据的当前时间填充

内容的提问来源于stack exchange,提问作者Francisco Zacarias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:45:03