ROS发布者publisher编程实现:从话题通信原理到工程实践

1. 先把发布者讲透:ROS话题通信到底在做什么

1.1 标题里提到的publisher,解决的是什么问题

做ROS基础学习的人,走到“发布者publisher编程实现”这一步,基本已经把ROS的核心抽象建立起来了:节点是独立进程,节点之间不直接调用函数,而是通过话题、服务、动作这些机制通信。而“发布者”是几乎所有ROS程序里最常用、也最好上手的一种角色——它的工作就是在一个话题上,按照设定的频率、把特定类型的消息发出去,供其他节点订阅处理。

举个贴近生活的例子:气象站就是一个发布者,它不管有没有人听天气预报、不管听众是谁,只管每隔一段时间把温度、湿度、风向这些数据发布到“天气频道”上;收音机则是订阅者,只要调到同一个频道,就能持续收到数据。ROS里的发布者也一样,它只负责把话“说出去”,不需要知道谁在听、听到了有没有用。这种“发布—订阅”的解耦设计,是ROS能支撑复杂机器人系统的基础。

这一节的内容,就是带着大家亲手写一个这样的发布者节点。我们从一个最简单的速度发布程序入手,让它周期性地往cmd_vel话题上发布机器人的运动速度指令,跑通“写代码—编译—启动节点—查看数据”的完整链路。整个过程适合ROS基础学习者、刚接触机器人开发的初学者,以及需要快速上手编写ROS节点的开发者。

1.2 官方教程之外,我为什么建议先搞懂这三个底层概念

很多朋友跟着官方教程跑过一遍turtlesim的发布者例子,代码能跑起来,但问起“为什么这么写”往往说不清楚。我特别建议在动手写代码之前,先把三个底层概念在脑子里立起来,后面写任何发布者都会顺很多。

第一个概念是节点和话题的关系。节点是ROS图(Graph)中的计算单元,话题是节点与节点之间的“运输管道”。发布者节点会在Master(在ROS 1中负责注册和路由)上完成注册,声明“我将在某个话题上发布某种类型的消息”,然后Master会把这个信息同步给所有订阅该话题的其他节点。发布者自己靠ros::Publisher对象持有话题的身份信息,只要这个对象还在,节点就会一直向话题写数据,不依赖任何接收方存在。

第二个概念是消息类型决定了数据的形状。ROS话题之所以能跨语言、跨平台传输,靠的是消息的“自描述”特性——每个消息类型都有一份字段定义,比如常见的geometry_msgs/Twist,它包含两个Vector3字段linear(线速度)和angular(角速度),每个字段又包含x、y、z三个分量。消息类型不匹配,数据根本发不出去,这也是新手最容易踩的坑。

第三个概念是发布频率和缓冲区。发布不是“一次性倒出数据”,而是按时间节拍持续刷新。频率太高浪费CPU和带宽,太低了又会让订阅方拿到过时数据。advertise时候选的队列长度决定了发送端暂时缓存多少条未发出的消息,这个数不是越大越好,后面我会细说。

这三个概念一旦打通,发布者代码里那几行看似机械的API调用,每个参数就都有针对性了——你是在用代码表达“我要在哪个话题、以什么频率、发出什么形状的数据”这个完整意图。

2. 动手前的准备:消息类型与代码框架

2.1 核心细节:从定义消息到发布对象的完整链路

一个发布者程序,本质上要完成四件事:初始化节点、创建发布者对象、构造消息数据、按频率循环发布。用C++写是这样,用Python写逻辑也一样,我下面以C++为例把链路拆开讲。

首先是初始化。ros::init(argc, argv, "node_name")这一行,除了把节点名注册进ROS网络,还可以顺带接收命令行里的重映射参数、私有参数等,所以一定要处理argc和argv。节点名在整个ROS图中是唯一的,如果两个节点起了同一个名字,后启动的会把先启动的踢掉。

然后是创建发布者对象。ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 10);这句里的nh是节点句柄(ros::NodeHandle),它负责和Master通信、维护订阅和发布关系。advertise是“广播”的意思:节点向Master注册自己,声明要往cmd_vel话题发布Twist类型消息。第二个参数10就是队列长度——当发布频率比订阅方的处理速度快时,消息会在一个队列里排队等待,队列满了之后,最旧的消息会被丢弃,保证系统不会无限堆积内存。对cmd_vel这种高频控制话题,10到100之间的队列长度都是合理选择。

再往下是构造消息。geometry_msgs::Twist msg;然后给msg.linear.x、msg.angular.z赋值。这里要理解ROS的消息是嵌套结构:Twist由两个Vector3类型字段组成,而linear.x和linear.y默认是0,不算自动初始化,必须在循环里显式赋值,否则每次发布的数据会不稳定。

最后是循环发布。常见写法是固定频率循环,核心代码如下:

ros::Rate loop_rate(10); while (ros::ok()) { msg.linear.x = 0.2; msg.angular.z = 0.1; pub.publish(msg); loop_rate.sleep(); }

ros::Rate是专门用来控制循环频率的类,loop_rate.sleep()会计算出距离下一次循环需要的时间,然后休眠到那个时刻,实现近似固定的发布周期。ros::ok()则是在节点被Ctrl+C终止、Master关停或发生异常时返回false,优雅退出循环。

2.2 工程上怎么组织:package、CMakeLists与依赖关系

代码写得再漂亮,工程组织不对也编译不过、跑不起来。一个标准的ROS发布者包,至少要包含以下内容:

  • CMakeLists.txt:声明包依赖、定义可执行文件目标、指定链接库
  • package.xml:描述包的元信息、依赖列表
  • src/:存放源码
  • 可选msg/、srv/、launch/目录

我用catkin_create_pkg创建新包时,一定会把依赖一次性带全。比如这个例子需要roscpp(C++客户端库)、geometry_msgs(消息类型)、std_msgs(标准消息,在很多例子里会用到)。命令如下:

catkin_create_pkg beginner_publisher roscpp geometry_msgs std_msgs

如果是老手,写包之前会先看一眼发布者发布消息的类型定义头文件和源码,确认依赖项没漏。依赖错了会直接体现在编译阶段,最常见的报错是找不到头文件,比如fatal error: geometry_msgs/Twist.h: No such file or directory——十有八九是geometry_msgs没写进package.xml的<build_depend>和<exec_depend>里,或者CMakeLists.txt的find_package少了这个模块。

CMakeLists.txt里还有两个非常关键的宏:add_executable和target_link_libraries。前者把源码编译成可执行目标,后者把catkin库链接进去。很多人会漏掉add_dependencies,导致自定义消息尚未生成就去编译,报出一堆“类型未定义”的错误。标准写法是:

add_executable(publisher_node src/publisher_node.cpp) target_link_libraries(publisher_node ${catkin_LIBRARIES}) add_dependencies(publisher_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

这里add_dependencies做的事情是:在编译publisher_node之前,先确保消息类型和依赖库的生成步骤执行完毕。用了自定义消息之后这一步尤其重要,否则你会被“看起来没错但就是编译失败”折磨很久。

3. 手把手实现一个发布者节点

3.1 完整代码:一个可以“抄作业”的最小实现

为了贴近实际使用场景,我这里写一个发布cmd_vel速度话题的完整示例。它的逻辑非常简单:每隔0.1秒向话题发布一次“线速度0.2、角速度0.1”的指令,就像你在用一个遥控器,以固定节奏把前进和转向的信号发给机器人底盘。

#include <ros/ros.h> #include <geometry_msgs/Twist.h> int main(int argc, char** argv) { ros::init(argc, argv, "velocity_publisher"); ros::NodeHandle nh; ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 10); ros::Rate loop_rate(10); while (ros::ok()) { geometry_msgs::Twist msg; msg.linear.x = 0.2; msg.linear.y = 0.0; msg.linear.z = 0.0; msg.angular.x = 0.0; msg.angular.y = 0.0; msg.angular.z = 0.1; pub.publish(msg); ROS_INFO("Publishing velocity: linear.x = %.2f, angular.z = %.2f", msg.linear.x, msg.angular.z); loop_rate.sleep(); } return 0; }

这里有一个细节值得展开:在while循环内部定义msg对象,而不是在循环外定义然后反复覆盖。这种写法的好处是每次发布的数据都是完全重新构造的,不会因为上一次循环的残留数据而出错。虽然对Twist这种简单类型影响不大,但当消息类型变大、字段多起来之后,“循环内构造”能避免很多隐蔽的数据污染问题。

Python版本也非常短,逻辑完全一致,适合快速验证想法:

#!/usr/bin/env python3 import rospy from geometry_msgs.msg import Twist def main(): rospy.init_node("velocity_publisher") pub = rospy.Publisher("cmd_vel", Twist, queue_size=10) rate = rospy.Rate(10) while not rospy.is_shutdown(): msg = Twist() msg.linear.x = 0.2 msg.angular.z = 0.1 pub.publish(msg) rate.sleep() if __name__ == "__main__": main()

Python接口和C++的差别在于:rospy.Publisher需要显式指定queue_size,不写会直接报错(这在较新的ROS发行版中是硬性要求),因为Python的发布队列如果不限长度,内存会随着时间增长。C++用advertise的第二个参数是默认参数,但Python这里省不了。

3.2 编译与运行:从源码到话题数据的完整流程

代码写完之后,建议先做一次catkin_make到工作空间里。流程我实测过很多遍,最顺的顺序是:打开终端,进入工作空间根目录,执行catkin_make,然后source devel/setup.bash。如果之前已经编译过、只改了一个文件,可以用catkin_make --pkg beginner_publisher加快编译速度,只处理这一个包。

编译输出里关注两类信息:一是有没有error,有的话会终止编译;二是看有没有生成devel/lib/beginner_publisher/publisher_node这个可执行文件。这一步过了,说明代码语法和链接都没问题。

运行之前,先启动roscore。这行命令会启动Master、参数服务器和日志节点,是整个ROS网络的管理中枢。新开一个终端执行:

roscore

再开一个终端,先source环境,然后rosrun运行节点:

source ~/catkin_ws/devel/setup.bash rosrun beginner_publisher publisher_node

正常时,终端里会每隔0.1秒打印一行Publishing velocity: linear.x = 0.20, angular.z = 0.10。如果看到这个输出,说明节点已经在正常运行、数据已经发到cmd_vel话题上了。再开第三个终端,用rostopic echo验证一下订阅端能收到什么:

rostopic echo /cmd_vel

这条命令会实时打印出每条消息的完整字段内容,看到linear.x: 0.2、angular.z: 0.1、--这样的分隔行,整个发布链路的验证就闭环了。

3.3 用rqt_graph验证发布关系是否建立

代码能跑通不代表发布关系已经正确建立。要直观看到ROS图里的节点和话题拓扑,最实用的看板工具是rqt_graph。运行方式很简单:

rqt_graph

界面里会画出当前ROS网络中的所有节点、话题以及它们之间的连线。我们的例子正常情况下会看到两个节点框:一个是/velocity_publisher,一个是/rostopic_xxxx(rostopic echo对应的临时节点);中间连线的标签上写着/cmd_vel。

很多新手一开始启动节点时不看这张图,等到多节点协同出错时一头雾水。我建议从第一个节点开始就养成看rqt_graph的习惯。它有几种显示模式,在左上角的“Groups”下拉菜单里可以切换成“Nodes only”或“Topics only”。有一次我在调试时发现发布者和订阅者明明话题名一模一样,但图上就是没有连线,最后发现是两台机器上的ROS_MASTER_URI配置不同,Master不是同一个,节点之间根本互相看不见。这种问题不看图,排查一晚上都未必找得到。

4. 实操阶段最容易踩的坑

4.1 常见问题与排查方法速查

我在带人入门和调试自己的机器人时,整理了一张高频问题表,这里直接分享出来。

症状可能原因解决办法
ros::init后程序闪退没启动roscore,或ROS_MASTER_URI指错了Master先启roscore,用roscore终端确认Master地址;检查环境变量echo $ROS_MASTER_URI
编译报“找不到geometry_msgs/Twist.h”包依赖没加完整,或工作空间没编译消息库package.xml补依赖,CMakeLists.txt在find_package里加geometry_msgs;重新catkin_make
能编译但rosrun找不到节点没source devel/setup.bash,或包名写错进工作空间根目录执行source devel/setup.bash;用rospack find核对包路径
节点起来了,rostopic list看不到话题名发布者还在启动阶段,或节点崩溃退出观察终端有没有打印advertised日志;用rqt_graph看连线关系
rostopic echo收不到数据话题名不一致,或发布频率为0核对发布者代码里advertise的话题名和echo的参数是否一字不差;检查loop_rate是否设成了0
发布频率不稳定循环里做了耗时操作,阻塞了sleep把耗时逻辑移出循环;或者减少发布频率,确保单次循环耗时远小于发布周期

其中“话题名不一致”出现的概率最高。ROS话题名是字符串匹配,一个前导斜杠、一个拼写错误、一个下划线差异,都会导致订阅失败,而且多数时候不报任何错误。cmd_vel和/cmd_vel其实指向的话题也不同——前者是相对名称,会被节点的命名空间影响;后者是全局名称,绝对定位。看不懂两者的区别,建议从_``_这个细节开始研究,比背API有用得多。

还有个隐蔽问题:节点启动后,ros::ok()返回false了,但代码里没有正确处理。比如在命令行窗口里Ctrl+C了,ROS会自动把ros::ok()置为false,循环正常退出,但如果你在后面还写了ros::spinOnce()和loop_rate.sleep(),而且没有判断,程序可能在退出信号之后还会休眠一段时间,造成看起来“关不掉”的假象。严谨的用法是循环里尽早检查退出条件,在ros::ok()为false时不要继续执行任何发布、清理操作。

4.2 调试剑客:用rostopic和rqt_console快速定位问题

除了经典的rostopic echo,还有几个工具值得从第一天就练熟。

rostopic list:列出当前所有话题,检查自己的话题有没有出现在列表里。如果出现了但没有数据,用rostopic hz查看话题的发布频率;如果频率是0,说明发布循环卡住或根本没在跑。

rostopic hz /cmd_vel:统计每秒收到的消息数量。我们的代码设定10Hz,实测通常会显示10.xx左右,差得多就说明系统调度出了问题。注意hz工具本身也会产生订阅负载,在低配设备上测出来的频率会比实际低,所以看到9.8、9.5这类值不必紧张。

rostopic type /cmd_vel:查看话题的消息类型。如果显示geometry_msgs/Twist,说明类型匹配;如果显示unknown,说明这个话题还没有任何节点在发布,发布者并没有真正运行。

rqt_console:查看日志和警告。发布者用ROS_INFO打的日志会出现在这里,错误、警告也会有对应级别的记录。把它和终端叠加使用,可以避免因终端日志滚动太快而漏掉关键信息。

我用这些工具处理过最经典的一类场景:机器人运动时快时慢,检查发布频率发现是10Hz,但实际消息里有时滞。最终用rostopic delay(或者对比回放)发现是队列太长、消息积压导致机器人拿到的指令滞后。把queue_size从100调低到10,问题立刻消失。这个“小参数”在实战里影响重大。

5. 从一个发布者到一套系统的经验心得

写完第一个发布者之后,很多人就以为学会ROS话题通信了——实际上这只是拿到了入场券。我的体会是,发布者的编程实现虽然代码量不多,但它是整个ROS开发中最关键的地基之一,因为机器人几乎所有行为最终都要落到“某个节点把指令发出去”这个动作上。

5.1 发布者风格:频率、队列和实时性之间的平衡

发布者在工程上不仅仅是“能发消息”,更关键的是把话题的节奏、频率、实时性设计好。控制类话题一般需要较高的频率,比如机器人的速度指令往往10Hz到50Hz,底盘控制器才能平滑响应;而状态类话题如电量、温度,1Hz甚至0.1Hz都足够,发布得太频繁只会浪费CPU和带宽。

对应地,队列长度的选择也不是拍脑袋。控制话题建议用较小的队列,保证收到的是最新的指令,避免积压过期的速度数据导致机器人动作延迟;日志、传感器采集这类低速但重要的数据,队列可以大一些,防止瞬时拥堵造成丢数据。我在实际项目中遵循一个原则:宁可丢掉旧数据,也要保证新数据的及时性,这一点对实时控制至关重要。

命令频率和队列长度一旦确定,如果发现机器人响应迟缓,我都建议先回头检查这两个参数,不要急着改底层的滤波和控制算法。

5.2 关于命名空间、多发布者和代码组织的一些体会

多节点协同工作时,命名空间的重要性会迅速凸显。同一个话题,发布者A在/robot1/cmd_vel上发布,发布者B在/robot2/cmd_vel上发布,如果不小心用了全局话题名,它们就会互相干扰。正确做法是在启动文件(launch文件)里给每个节点指定ns参数,或者在代码里用私有句柄(~开头的话题名)让话题自动挂到节点命名空间下。这个知识点看着简单,但在实际多机器人系统里非常关键。

发布者不一定是“一个人”,也常常出现多个节点同时发布同一个话题的情况。这时话题不会报错,但订阅方收到的数据是多个发布者随机交错发布的,如果没有严格的时序约束,会出现数据混乱。解决思路有两种:要么从架构上确保同一话题同时只有一个活跃发布者(比如用latch属性或ros::transport的机制),要么在订阅逻辑里根据时间戳做过滤。

5.3 写完发布者之后,下一步该学什么

如果这一节的代码已经熟练掌握,建议按这个顺序继续往下走:先学订阅者的编写,体会“发布—订阅”两个角色是如何互动的;再学服务(Service)和动作(Action),理解不同通信机制各自的适用场景;然后开始接触launch文件的写法,学习如何用一条命令同时启动多个节点和参数配置;最后可以挑战自己动手做一个完整的小系统,比如一个“键盘遥控机器人”的模拟程序,发布者接收键盘输入、发布速度话题、订阅者接收话题并打印或者驱动仿真底盘。

这个过程中,最重要的不是背API,而是积累“数据如何在系统里流动”的直觉。每写完一个程序,用rqt_graph看一眼图里的拓扑,用rqt_console看一下日志,用rostopic观察一下数据的实时性——一套系统在你的脑子里从“代码片段”变成“数据流图”,之后遇到任何通信问题,都不会瞎猜了。

我自己在带新人的时候,经常说一句话:ROS的入门门槛其实很低,但上限很高。低就低在发布者、订阅者这种基础组件,学起来就是几行代码的事;高就高在把这些组件组合成可靠、高效、可维护的完整系统,需要长期的项目积累。这篇发布者编程实现,是这段路程的起点,也是后面所有复杂系统都绕不开的地基。走稳这一步,就会觉得ROS没有传说中那么难。

相关新闻

GRACE水储量重建:尺度因子方法的物理原理与工程实现

GRACE水储量重建:尺度因子方法的物理原理与工程实现

简介&#xff1a;本资源是一套面向地球物理、水文遥感及气候研究方向的科研人员与研究生的GRACE水储量反演实践数据集&#xff0c;聚焦于利用尺度因子方法校正并恢复高精度陆地水储量变化。资源提供完整的尺度因子计算与应用流程支撑文件&#xff0c;含3个MATLAB脚本&#xff0…

2026/10/20 18:45:49 阅读更多 →
赛马局团建:用竞合机制让团队从路人变战友

赛马局团建:用竞合机制让团队从路人变战友

说实话&#xff0c;当部门负责人跟我说“下个月团建你负责”的时候&#xff0c;我第一反应是想推掉。不是懒&#xff0c;而是见过太多次团建变成“换个地方加班”或者“大型尴尬现场”&#xff1a;吃饭时各玩各的手机&#xff0c;熟人在桌子一头扎堆&#xff0c;剩下的人缩在角…

2026/10/20 18:44:48 阅读更多 →
用Electron打造桌面富应用:文件分发与批量操作实战指南

用Electron打造桌面富应用:文件分发与批量操作实战指南

先交代一下背景&#xff1a;我手上这个活儿&#xff0c;是把一个内部用的“批量分发文件”需求做成了正经的 PC 桌面富应用&#xff0c;名字就叫“速分客户端”。起因很简单&#xff0c;团队里每天都有几十个文件要同步给不同机器、不同目录&#xff0c;还要按规则改文件名、按…

2026/10/20 18:44:48 阅读更多 →

最新新闻

企业信息收集一步到位:ENScan_GO 备案、APP、公众号聚合实战指南

企业信息收集一步到位:ENScan_GO 备案、APP、公众号聚合实战指南

企业信息收集一步到位&#xff1a;ENScan_GO 备案、APP、公众号聚合实战指南 【免费下载链接】ENScan_GO 一款基于各大企业信息API的工具&#xff0c;解决在遇到的各种针对国内企业信息收集难题。一键收集控股公司ICP备案、APP、小程序、微信公众号等信息聚合导出。支持MCP接入…

2026/10/20 19:21:40 阅读更多 →
风扇选型软件:从P-Q曲线到工作点计算与批量筛选

风扇选型软件:从P-Q曲线到工作点计算与批量筛选

简介&#xff1a;Optimiser风扇选型软件是Multi-Wing官方推出的一款轴流风扇选型工具&#xff0c;面向暖通空调、工业通风、冷却散热等领域的工程师与设备选型人员。使用者只需输入应用所需的风量、压力与能耗等参数&#xff0c;软件即可自动匹配莫迪温风扇型号&#xff0c;帮助…

2026/10/20 19:21:40 阅读更多 →
AI辅助项目管理实操:用CodeBuddy打造可对话的“活档案”

AI辅助项目管理实操:用CodeBuddy打造可对话的“活档案”

说实话&#xff0c;以前我对“用AI做项目管理”这事挺抵触的。项目管理讲究的是人对人的协作、决策和沟通&#xff0c;AI能插得上什么手&#xff1f;直到我连续带了三周迭代&#xff0c;发现自己一半精力被会议、同步、验收这些琐事磨掉了&#xff0c;才下定决心让CodeBuddy进项…

2026/10/20 19:21:40 阅读更多 →
免费开源 3D 打印切片软件 Bambu Studio:3 步出件,自动支撑、多色打印一次配齐

免费开源 3D 打印切片软件 Bambu Studio:3 步出件,自动支撑、多色打印一次配齐

免费开源 3D 打印切片软件 Bambu Studio&#xff1a;3 步出件&#xff0c;自动支撑、多色打印一次配齐 【免费下载链接】BambuStudio PC Software for BambuLab and other 3D printers 项目地址: https://gitcode.com/GitHub_Trending/ba/BambuStudio Bambu Studio 是一…

2026/10/20 19:21:40 阅读更多 →
SodaDownloader:汽水音乐链接解密提取FLAC/M4A的完整教程

SodaDownloader:汽水音乐链接解密提取FLAC/M4A的完整教程

简介&#xff1a;SodaDownloader是一款面向汽水音乐平台用户的便捷下载工具&#xff0c;只需复制分享链接即可解析歌曲信息&#xff0c;并支持FLAC无损音频和M4A高质量格式的解密与下载&#xff0c;让用户不进入平台也能获取高品质音乐文件。该源码工程压缩包共26个文件、仅72K…

2026/10/20 19:21:40 阅读更多 →
pandas动态时间窗口实现多周期销量统计

pandas动态时间窗口实现多周期销量统计

1. 项目概述&#xff1a;为什么“近X天销量统计”是业务分析的起点而非终点在某电商公司做数据支持的那两年&#xff0c;我每天早上八点准时打开BI看板&#xff0c;第一眼不是看总GMV&#xff0c;而是盯着“近7天销量趋势”那个小卡片——它像血压计一样&#xff0c;能快速判断…

2026/10/20 19:20:37 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →