第三方中间件 ROS¶
1. 数据交互流程概述¶

获取仿真感知数据:ROS API 负责从 SimOne 仿真平台中收集感知数据。
数据转换:收集到的仿真感知数据被转换成标准的 ROS 消息格式。
发布消息到 ROS Topic:转换后的数据被发布到指定的 ROS 话题(Topic)上供进一步使用。
驾驶算法订阅处理:驾驶算法模块订阅这些话题,并将数据传入规控/感知模块,进行算法训练和处理。
发布控制消息:算法处理后,生成的控制消息被发布到仿真主车控制话题上。
通信闭环完成控制:ROS API 捕捉这些控制消息,并将其作为参数传入 SimOne 仿真主车的动力学节点。这样便驱动了仿真场景中主车的具体行动。
算法验证和调试:驾驶算法可以选择订阅特定的话题消息来验证局部模块的准确性。此外,通过在 ROS 环境中建立一个闭环系统,可以实现对驾驶算法整体性能的综合验证。
2. 数据通信流程简图¶

3. 软件环境¶
编程语言:C++
4. 编译环境¶
4.1 ROS Msg 消息转换¶
将 SimOne API 数据格式转为 ROS 可发布/订阅的标准数据格式。
编写 ROS msg 消息文件
根据 SimOne API 接口数据,参照 C++数据类型与 ROS msg 数据类型的映射关系,编写对应的 ROS API msg 消息文件。
创建 ROS 工程 Workspace
执行以下命令创建 ROS 工程 Workspace:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
创建功能包
执行以下命令
cd ~/catkin_ws/src
catkin_create_pkg <package_name> roscpp std_msgs
添加 msg 消息文件至功能包
将编写好的 msg 消息文件放入功能包的指定目录下:
mkdir ~/catkin_ws/src/<package_name>/msg
添加功能依赖
在 ~/catkin_ws/src/<package_name>/package.xml 文件中添加功能依赖:
<build_dependmessage_generation</build_depend<exec_dependmessage_runtime</exec_depend
修改 CMakeLists.txt
在 ~/catkin_ws/src/<package_name>/CMakeLists.txt 文件中添加必要的编译选项,以支持自定义消息的编译。
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_generation
)
add_message_files(FILES
<ROS API msg 消息文件 .msg>
)
generate_messages(DEPENDENCIES
std_msgs
)
catkin_package(
CATKIN_DEPENDS roscpp std_msgs message_runtime
)
编译功能包
返回到 catkin_ws 目录并编译功能包:
cd ~/catkin_ws
catkin_make
编译整个工作空间
为确保整个工作空间构建成功,再次执行:
cd ~/catkin_ws
catkin_make
检查 C++头文件
检查 msg 文件生成的 C++头文件是否位于以下目录中:
~/catkin_ws/devel/include/<package_name>/
将生成的 C++头文件整合至 ROS API 工程
将第 9 步生成的 C++头文件融入 ROS API 工程,以便在工程中使用自定义消息。
4.2 ROS 接口示例工程目录结构¶
ROS/
├── CMakeLists.txt # 工程编译脚本
├── gen_make_debug.sh # debug 工程编译环境生成脚本
├── gen_make_release.sh # release 工程编译环境生成脚本
├── include # 工程头文件
├── lib # 工程依赖库
├── run # ROS API 节点可执行程序生成目录
└── src # ROS API 工程源文件
4.3 ROS 接口示例工程编译¶
编译 ROS 接口工程需要完成以下几个步骤:
执行编译脚本:
对于调试模式,运行
gen_make_debug.sh脚本。对于发布模式,运行
gen_make_release.sh脚本。
进入构建目录:
对于调试构建,请使用
cd build_debug命令进入构建目录。对于发布构建,请使用
cd build_release命令进入构建目录。
开始构建项目:
在命令行中输入
make命令开始构建过程。构建完成后,ROS API 节点程序将生成在run/trans_node_ros路径下。
5. 运行 ROS 通信节点¶
要启动并运行 ROS API 节点,请按照以下步骤操作:
启动 ROS 核心:
在命令行中输入
roscore来启动 ROS 核心服务。
执行 ROS API 节点程序:
运行
trans_node_ros程序。程序启动时,将根据config.ini配置文件中的参数来初始化设置。config.ini 运行参数配置文件
[BridgeIO] Sim-One API 客户端连接设置 BridgeIO_IP=10.66.9.111 SimOne BridgeIO 节点 IP [HostVehicle] Sim-One 仿真主车设置 Vehicle_ID=0 Sim-One 仿真主车 ID [Sensor] Sim-One 传感器通信配置 IMG_IP=10.66.9.244 图像数据 UDP 接收端 IP IMG_PORT=13944 图像数据 UDP 接收端 Port PCD_IP=10.66.9.244 点云数据 UDP 接收端 IP PCD_PORT=6699 点云数据 UDP 接收端 Port PCD_PORT_INFO=7788 点云数据 UDP 接收端 InfoPort [ROS] ROS 消息配置 GPS_Topic=/gps Gps 消息发布 Topic GroundTruth_Topic=/ground_truth 感知物体真值消息发布 Topic Image_Topic=/image 图像数据消息发布 Topic PointCloud_Topic=/point_cloud 点云数据消息发布 Topic Radar_Topic=/radar_detection 毫米波雷达数据消息发布 Topic Sensor_Topic=/sensor_detection 目标及传感器真值数据消息发布 Topic LaneInfo_Topic=/lane_info 感知车道/车道线数据消息发布 Topic CTL_Topic=/control 主车控制(油门/刹车/方向)数据消息订阅 Topic POSE_CTL_Topic=/pose_control 主车控制(离散点)数据消息订阅 Topic
6. 消息验证¶
6.1 运行 SimOne 测试案例¶
SimOne 仿真端操作
启动 SimOne,新建测试案例
新建测试主车(加载相关传感器,配置控制系统为 手动 / API 控制)
运行案例(选择主车为该主车)
ROS 端操作
运行 SimOne ROS Bridge
启动第三方算法
6.2 图像数据验证¶
使用
rviz可视化工具订阅Image Topic,以显示实时的图像数据。
6.3 点云数据验证¶
通过
rviz订阅PointCloud Topic,观察点云图像的实时更新。


6.4 结构化数据验证¶
执行以下命令来配置环境并监听 ROS 话题以输出实时数据:
source ~/catkin_ws/devel/setup.bash
rostopic echo /gps

7. 接口¶
通过 Sim-One API 获取仿真感知数据
主车Gps消息回调
bool SetGpsUpdateCB(void(*cb)(const char* mainVehicleId, SimOne_Data_Gps *pGps));
获取仿真感知物体真值回调
bool SetGroundTruthUpdateCB(void(*cb)(const char* mainVehicleId, SimOne_Data_Obstacle *pObstacle));
获取摄像头图像数据回调
bool SetStreamingImageUpdateCB(const char* ip, unsigned short port, void(*cb)(SimOne_Streaming_Image *pImage));
获取激光雷达点云数据回调
bool SetStreamingPointCloudUpdateCB(const char* ip, unsigned short port, unsigned short infoPort, void(*cb)(SimOne_Streaming_Point_Cloud *pPointCloud));
获取毫米波雷达目标信息回调
bool SetRadarDetectionsUpdateCB(void(*cb)(const char* mainVehicleId, const char* sensorId, SimOne_Data_RadarDetection *pDetections));
获取目标及传感器真知数据回调
bool SetSensorDetectionsUpdateCB(void(*cb)(const char* mainVehicleId, const char* sensorId, SimOne_Data_SensorDetections *pGroundtruth));
获取感知车道与车道线数据回调
bool GetSensorLaneInfo(const char* mainVehicleId, const char* sensorId, SimOne_Data_LaneInfo *pLaneInfo);
通过 ROS Publisher 将感知消息发布到相应 Topic 上
发布Gps消息
pub_gps = handle_gps.advertise<msg_gen::gps>(gps_topic.c_str(), 1);
pub_gps_p->publish(gps_d);
发布仿真感知物体真值消息
pub_ground_truth = handle_ground_truth.advertise<msg_gen::obstacle>(ground_truth_topic.c_str(), 1);
pub_ground_truth_p->publish(obstacle_d);
发布摄像头图像数据消息
pub_image = handle_image.advertise<sensor_msgs::Image>(image_topic.c_str(), 1);
pub_image_p->publish(img_d);
发布激光雷达点云数据消息
pub_point_cloud = handle_point_cloud.advertise<sensor_msgs::PointCloud2>(point_cloud_topic.c_str(), 1);
pub_point_cloud_p->publish(point_cloud_d);
发布毫米波雷达目标信息
pub_radar = handle_radar.advertise<msg_gen::radardetection>(radar_topic.c_str(), 1);
pub_radar_p->publish(radar_detection_d);
发布目标及传感器真值消息
pub_sensor = handle_sensor.advertise<msg_gen::sensordetections>(sensor_topic.c_str(), 1);
pub_sensor_p->publish(sensor_detections_d);
发布感知车道/车道线消息
pub_laneinfo = handle_laneinfo.advertise<msg_gen::laneinfo>(lane_info_topic.c_str(), 1);
pub_laneinfo_p->publish(lane_info_d);
通过 ROS Subscriber 订阅主车控制相关 Topic
订阅主车控制消息(离散点 控制)
sub_ctl = handle_ctl.subscribe(ctl_topic.c_str(), 1, &ros_trans_node::rcv_ctl_cb, this);
订阅主车控制消息(油门/刹车/方向 控制)
sub_pose_ctl = handle_pose_ctl.subscribe(pose_ctl_topic.c_str(), 1, &ros_trans_node::rcv_pose_ctl_cb, this);
通过 Sim-One API 设置主车控制参数
根据离散点设置主车位置
SimOneAPI::SetPose(0, &pose_ctl);
设置主车控制参数
SimOneAPI::SetDrive(vehicle_id.c_str(), pCtrl.get());