
如何发布接收消息这篇文档只回答一件事如何用 SpireMS 在 Python 和 C 里发布、订阅消息。目标人能快速照着跑通AI 能直接提取代码和步骤示例尽量短示例不依赖你本地特定的视频或图片文件1. 先决条件1.1 启动 Core先启动Core只需要启动一次smscore如果你是源码开发环境也可以直接python-mspirems.core1.2 Python 环境推荐在项目根目录执行python-mpipinstall-e.如果你只是使用已发布版本python-mpipinstallspirems1.3 C 环境先安装 C SDKcdspirems_cppmkdir-pbuildcdbuild cmake..sudomakeinstall如果系统还没有 OpenCV 和 CMakesudoaptupdatesudoaptinstall-ycmake libopencv-dev2. Python最常用的发布与订阅Python 常用导入fromspiremsimportPublisher,Subscriber,def_msgfromspiremsimportcvimg2sms,sms2cvimg,tensor2sms,sms2tensor2.1 字符串消息消息类型std_msgs::String发布importtimefromspiremsimportPublisher,def_msg pubPublisher(/demo/string,std_msgs::String)try:whileTrue:msgdef_msg(std_msgs::String)msg[data]hello spiremspub.publish(msg)time.sleep(1.0)exceptKeyboardInterrupt:pub.kill()订阅fromspiremsimportSubscriberdefcallback(msg):print(recv:,msg[data])subSubscriber(/demo/string,std_msgs::String,callback)sub.join()2.2 压缩图像消息消息类型sensor_msgs::CompressedImage适合普通图像传输跨机器传输对带宽比较敏感的场景发布importtimeimportcv2importnumpyasnpfromspiremsimportPublisher,cvimg2sms pubPublisher(/demo/image,sensor_msgs::CompressedImage)try:whileTrue:imgnp.zeros((480,640,3),dtypenp.uint8)cv2.putText(img,SpireMS,(180,240),cv2.FONT_HERSHEY_SIMPLEX,2.0,(0,255,0),3)msgcvimg2sms(img,frame_idcamera)pub.publish(msg)time.sleep(0.05)exceptKeyboardInterrupt:pub.kill()订阅importcv2fromspiremsimportSubscriber,sms2cvimgdefcallback(msg):imgsms2cvimg(msg)cv2.imshow(compressed image,img)cv2.waitKey(1)subSubscriber(/demo/image,sensor_msgs::CompressedImage,callback)sub.join()2.3 共享内存图像消息消息类型memory_msgs::RawImage适合本机大图像低延迟传输高频图像流注意共享内存消息主要用于 Linux / macOS 本机进程间传输发送端和接收端需要在同一台机器上发布importtimeimportcv2importnumpyasnpfromspiremsimportPublisher pubPublisher(/demo/raw_image,memory_msgs::RawImage)try:whileTrue:imgnp.zeros((720,1280,3),dtypenp.uint8)cv2.circle(img,(640,360),120,(255,0,0),-1)cv2.putText(img,SHM,(560,370),cv2.FONT_HERSHEY_SIMPLEX,2.0,(255,255,255),3)msgpub.cvimg2sms_mem(img)pub.publish(msg)time.sleep(0.02)exceptKeyboardInterrupt:pub.kill()订阅importcv2fromspiremsimportSubscriber,sms2cvimgdefcallback(msg):imgsms2cvimg(msg)cv2.imshow(raw image,img)cv2.waitKey(1)subSubscriber(/demo/raw_image,memory_msgs::RawImage,callback)sub.join()2.4 共享内存 Tensor消息类型memory_msgs::Tensor适合模型输入输出任意维度数组图像张量、特征图、点云特征等发布importtimeimportnumpyasnpfromspiremsimportPublisher,tensor2sms pubPublisher(/demo/tensor,memory_msgs::Tensor)try:whileTrue:tensor(np.random.rand(3,224,224)*255).astype(np.float32)msgtensor2sms(tensor,demo_tensor_mem)pub.publish(msg)time.sleep(0.05)exceptKeyboardInterrupt:pub.kill()订阅fromspiremsimportSubscriber,sms2tensordefcallback(msg):tensorsms2tensor(msg)print(shape:,tensor.shape,dtype:,tensor.dtype,mean:,float(tensor.mean()))subSubscriber(/demo/tensor,memory_msgs::Tensor,callback)sub.join()2.5 任意类型消息最简单的“任意结构消息”写法是使用std_msgs::Null。它的含义是不强约束字段你可以按需扩展字段。发布importtimefromspiremsimportPublisher,def_msg pubPublisher(/demo/any,std_msgs::Null)cnt0try:whileTrue:msgdef_msg(std_msgs::Null)msg[cnt]cnt msg[name]spiremsmsg[ok]Truemsg[pos][1.0,2.0,3.0]msg[meta]{source:python,version:1}pub.publish(msg)cnt1time.sleep(1.0)exceptKeyboardInterrupt:pub.kill()订阅fromspiremsimportSubscriberdefcallback(msg):print(msg)subSubscriber(/demo/any,std_msgs::Null,callback)sub.join()2.6 任意预定义类型消息如果你要发送已经定义好的消息建议优先用def_msg()初始化再写字段。例如geometry_msgs::PosefromspiremsimportPublisher,def_msg pubPublisher(/demo/pose,geometry_msgs::Pose)msgdef_msg(geometry_msgs::Pose)msg[position][x]1.0msg[position][y]2.0msg[position][z]3.0msg[orientation][x]0.0msg[orientation][y]0.0msg[orientation][z]0.0msg[orientation][w]1.0pub.publish(msg)3. C最常用的发布与订阅常用头文件#includesms_core.h3.1 字符串消息发布#includesms_core.hintmain(){sms::Publisherpub(/demo/string_cpp,std_msgs::String);while(true){nlohmann::json msgsms::def_msg(std_msgs::String);msg[data]hello spirems from cpp;pub.publish(msg);sms::msleep(1000);}return0;}订阅#includeiostream#includesms_core.hvoidcallback(nlohmann::json msg){std::coutrecv: msg[data]std::endl;}intmain(){sms::Subscribersub(/demo/string_cpp,std_msgs::String,callback);sub.join();return0;}3.2 压缩图像消息发布#includeopencv2/opencv.hpp#includesms_core.hintmain(){sms::Publisherpub(/demo/image_cpp,sensor_msgs::CompressedImage);while(true){cv::Mat imgcv::Mat::zeros(480,640,CV_8UC3);cv::putText(img,SpireMS C,cv::Point(120,240),cv::FONT_HERSHEY_SIMPLEX,1.5,cv::Scalar(0,255,0),3);nlohmann::json msgsms::cvimg2sms(img);pub.publish(msg);sms::msleep(50);}return0;}订阅#includeopencv2/opencv.hpp#includesms_core.hvoidcallback(nlohmann::json msg){cv::Mat imgsms::sms2cvimg(msg);cv::imshow(compressed image cpp,img);cv::waitKey(1);}intmain(){sms::Subscribersub(/demo/image_cpp,sensor_msgs::CompressedImage,callback);sub.join();return0;}3.3 共享内存图像消息发布#includeopencv2/opencv.hpp#includesms_core.hintmain(){sms::mem_init();sms::Publisherpub(/demo/raw_image_cpp,memory_msgs::RawImage);while(true){cv::Mat imgcv::Mat::zeros(720,1280,CV_8UC3);cv::rectangle(img,cv::Rect(300,180,680,360),cv::Scalar(255,0,0),-1);cv::putText(img,SHM CPP,cv::Point(430,380),cv::FONT_HERSHEY_SIMPLEX,2.0,cv::Scalar(255,255,255),3);nlohmann::json msgpub.cvimg2sms_mem(img);pub.publish(msg);sms::msleep(20);}return0;}订阅#includeopencv2/opencv.hpp#includesms_core.hvoidcallback(nlohmann::json msg){cv::Mat imgsms::sms2cvimg(msg);cv::imshow(raw image cpp,img);cv::waitKey(1);}intmain(){sms::mem_init();sms::Subscribersub(/demo/raw_image_cpp,memory_msgs::RawImage,callback);sub.join();return0;}3.4 共享内存 Tensor发布#includevector#includesms_core.hintmain(){sms::mem_init();sms::Publisherpub(/demo/tensor_cpp,memory_msgs::Tensor);while(true){std::vectorfloatdata(3*4,0.0f);for(size_t i0;idata.size();i){data[i]static_castfloat(i);}nlohmann::json msgsms::tensor2sms(data.data(),{3,4},demo_tensor_cpp_mem);pub.publish(msg);sms::msleep(1000);}return0;}订阅#includeiostream#includevector#includesms_core.hvoidcallback(nlohmann::json msg){std::vectorfloattensor_data;std::vectorinttensor_shape;sms::sms2tensor(msg,tensor_data,tensor_shape);std::coutshape: [;for(size_t i0;itensor_shape.size();i){std::couttensor_shape[i](i1tensor_shape.size()?:, );}std::cout], firsttensor_data[0]std::endl;}intmain(){sms::mem_init();sms::Subscribersub(/demo/tensor_cpp,memory_msgs::Tensor,callback);sub.join();return0;}3.5 任意类型消息发布#includesms_core.hintmain(){sms::Publisherpub(/demo/any_cpp,std_msgs::Null);intcnt0;while(true){nlohmann::json msgsms::def_msg(std_msgs::Null);msg[cnt]cnt;msg[name]spirems_cpp;msg[ok]true;msg[pos]{1.0,2.0,3.0};msg[meta]{{source,cpp},{version,1}};pub.publish(msg);sms::msleep(1000);}return0;}订阅#includeiostream#includesms_core.hvoidcallback(nlohmann::json msg){std::coutmsg.dump(2)std::endl;}intmain(){sms::Subscribersub(/demo/any_cpp,std_msgs::Null,callback);sub.join();return0;}4. C 最小 CMakeLists.txt如果你想把上面的 C 示例直接编译运行可以使用下面这个最小CMakeLists.txtcmake_minimum_required(VERSION 3.10) project(spirems_demo) find_package(OpenCV REQUIRED) find_package(SpireMS REQUIRED) add_executable(str_sender str_sender.cpp) target_include_directories(str_sender PRIVATE ${SpireMS_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS}) target_link_libraries(str_sender ${SpireMS_LIBS} ${OpenCV_LIBS})编译mkdir-pbuildcdbuild cmake..make-j5. 如何选择消息类型5.1 文本、小数据优先用std_msgs::Stringstd_msgs::Numberstd_msgs::Boolean5.2 已定义结构化消息优先用geometry_msgs::*sensor_msgs::*spirecv_msgs::*写法先def_msg(消息类型)再按字段赋值5.3 本机大图像/大 Tensor优先用memory_msgs::RawImagememory_msgs::Tensor特点延迟更低拷贝更少只适合同机共享内存场景5.4 暂时没有固定结构优先用std_msgs::Null适合调试快速验证临时自由字段消息6. 最常见问题6.1No module named spirems建议python-mpipinstall-e.或者在项目根目录运行PYTHONPATH. python your_script.py6.2 共享内存消息收不到先检查发送端和接收端是否在同一台机器是否使用了memory_msgs::RawImage/memory_msgs::TensorLinux / macOS 下共享内存扩展是否正常6.3 图像能发但显示不出来先检查接收端是否调用了sms2cvimg(msg)cv2.imshow()后是否调用了cv2.waitKey(1)发送消息类型是否和订阅类型一致7. 仓库内可参考的现成示例Pythontest/string_sender_test.pytest/string_receiver_test.pytest/image_sender_test.pytest/image_receiver_test.pytest/share_mem_sender_test.pytest/share_mem_receiver_test.pytest/any_sender_test.pytest/any_receiver_test.pyspirems/demo/tensor_mem_pub_demo.pyspirems/demo/tensor_mem_sub_demo.pyCspirems_cpp/demo/str_sender_test.cppspirems_cpp/demo/str_receiver_test.cppspirems_cpp/demo/image_sender_test.cppspirems_cpp/demo/share_mem_sender_test.cppspirems_cpp/demo/share_mem_receiver_test.cppspirems_cpp/demo/tensor_mem_sender_test.cppspirems_cpp/demo/tensor_mem_receiver_test.cpp8. 一句话总结小消息直接Publisher def_msg Subscriber图像跨机sensor_msgs::CompressedImage大图像本机memory_msgs::RawImage张量本机memory_msgs::Tensor临时自由结构std_msgs::Null照着上面的最小示例复制运行即可。