从”照着配置跑通 move_base demo”升级为”理解建图/定位/规划/代价地图每层的数学原理,知道参数为什么这么设、导航失败往哪查”。激光雷达数据模型、gmapping 与 cartographer 的取舍、AMCL 粒子滤波、代价地图三层结构与衰减公式、A*/DWA/TEB 的算法本质、move_base 状态机与恢复行为——最后给出可量化的调参顺序与评估指标。
一、激光雷达数据:LaserScan 的几何与噪声模型LaserScan 的结构12345678# 典型 2D 雷达(如 rplidar A1):360°、每圈 720 点angle_min: -3.14159 # 起始角(rad)angle_max: 3.14159 # 结束角angle_increment: 0.00873 # 0.5°/点 = 2π/720range_min: 0.12range_max: 12.0ranges: [ ... 720 个浮点数 ... ] # 单位米,无效点 = inf / NaNintensit...
入门教程讲”怎么拖控件”,本文讲”Qt 凭什么能这么写”。以机器人调参上位机(类似 rm_pid_tuner 的 PID 调参面板:滑条改参数、实时曲线、一键下发)为贯穿案例,把 MOC 元对象系统 → 信号与槽 → 对象树 → 跨线程刷新 这条链路讲透。理解了这四层,Qt 从”会用的库”变成”能设计架构的框架”。
一、Qt 在工程里的定位机器人/嵌入式项目的上位机几乎都是 Qt:跨平台(Windows 调参电脑 + Linux 工控机同一套代码)、信号槽天然适合”界面事件 → 控制指令”的解耦、QPainter 能画实时曲线。一个典型调参面板的架构:
12345QDoubleSpinBox(参数输入) ──valueChanged──► 参数模型(校验/限幅) ──► 指令打包 ──► 串口/CAN/ROSQSlider(手感调节) ──valueChanged──► ▲实时曲线(QPainter/QChart) ◄──数据回调线程── 采集线程(读反馈) │ ▲ ...
上一篇讲元对象系统与信号槽,这一篇解决”界面怎么做才不翻车”:布局与控件的正确用法、QSS 样式、事件系统、QPainter 实时绘图、线程与界面。延续调参上位机的场景——做完这一篇,你应该能独立写出一个带实时曲线、可换肤、不卡死的上位机界面。
一、控件的本质:数据到界面的映射层控件不是”画出来的按钮”,而是数据模型的投影:QSpinBox 显示并编辑一个数值,QCheckBox 映射一个 bool,QComboBox 映射一个枚举。理解这一点,选控件的依据就变成了”我的数据是什么类型”:
数据类型
控件
关键信号(选对信号!)
连续数值
QDoubleSpinBox / QSlider
valueChanged(double)
整数枚举
QComboBox
currentIndexChanged(int)(activated 只在用户操作时触发)
开关量
QCheckBox / QRadioButton
toggled(bool)(clicked 在编程 setChecked 时不触发)
短文本
QLineEdit
textEdi...
入门文的通病是”能点亮 LED 就毕业”。本文换一条路线:以 RoboMaster 电控的真实任务链为主线——CubeMX 生成工程 → 时钟树 → GPIO → 串口帧协议 → 编码器 → CAN 总线驱动 M3508/C620 → 云台双环 PID,把每一层”为什么”讲透,并附上实际调车时踩过的坑。看完你应该能独立完成”STM32 通过 CAN 控制一个无刷电机并做闭环”这件事。
一、任务链:入门到实战之间缺什么一个最小可用的电控系统长这样:
12345678遥控器 → 接收机 → 串口/USB → STM32 (解析协议) │ ┌─────────────────────────┼──────────────────┐ ▼ ▼ ▼ 编码器(AB相) PWM/舵机 CAN 总线 → C620 电调 → M3508 电机 ...
本文把运动学/动力学从”背公式”升级为”能推导、能写代码”。核心思路:DH 参数为什么是 4 个 → 正解就是矩阵连乘 → 逆解的本质是解方程(解析 or 数值)→ 雅可比连接速度层与力层 → 拉格朗日从能量导出 M/C/G → 麦轮底盘从辊子几何推导速度分解矩阵。全程结合 RoboMaster 云台/麦轮底盘和减速器课程设计的实战。
DH 参数:为什么恰好是 4 个参数两个相邻连杆坐标系之间的变换有 6 个自由度(3 旋转 + 3 平移),但 DH 约定把关节轴线本身作为约束,把问题降维:
连杆 i 的坐标系 {i} 固连在关节 i+1 上,Z 轴沿关节轴线
相邻坐标系 {i-1} → {i} 的变换被拆成 4 次基本变换:绕 Z 转 θ、沿 Z 移 d、沿 X 移 a、绕 X 转 α
$$A_i = \operatorname{Rot}(z, \theta_i) \cdot \operatorname{Trans}(z, d_i) \cdot \operatorname{Trans}(x, a_i) \cdot \op...
本文结合 rm_pid_tuner(ROS Noetic 自动调参系统)的实际开发经验,讲清楚 ROS2 到底改了什么、为什么要改,以及把 ROS1 工程迁到 ROS2 时每一步会踩什么坑。不满足于”会建包、会发布订阅”,而是让你理解 DDS 通信模型 → QoS 契约 → 执行模型 → 迁移实战 的完整链路。
为什么要有 ROS2:ROS1 的架构性缺陷ROS1 的核心是 roscore(master):所有节点启动时向 master 注册,通信双方通过 master 交换地址信息后建立点对点连接。这个架构有三个致命问题:
单点故障:master 挂了整个系统瘫痪。机器人比赛/产线上不可能接受”调度器进程崩溃 = 全车失联”
无实时性保证:roscpp 的发布订阅基于 TCP/UDP socket,传输层不可控,回调触发时机不确定
无安全/多机支持:ROS1 的跨机通信需要所有机器共享同一 ROS_MASTER_URI,没有加密、没有权限隔离,多机器人场景下 QoS 完全无法区分
ROS2 的答案是:把通信层整个换成 DDS(Da...
本文不满足于”SLAM 分前端后端回环五步”的科普框架,而是讲清楚每个模块在数学上到底在解什么:SLAM 是最大后验估计 → 前端是帧间几何 → 后端是稀疏最小二乘 → 回环是全局一致性 → KD 树是搜索加速。结合 RoboMaster 视觉(HSV 灯条识别、深度相机选型)和 FAST-LIO2 的实际工程经验。
SLAM 的数学本质:一个状态估计问题SLAM 所有模块都可以统一到同一个框架——带噪声的状态估计。定义两个方程:
运动方程(状态怎么变):$x_k = f(x_{k-1}, u_k) + w_k$观测方程(传感器看到什么):$z_{k,j} = h(x_k, l_j) + v_{k,j}$
$x_k$:k 时刻位姿;$u_k$:控制输入(IMU/轮速);$l_j$:第 j 个路标(地图点)
$w_k, v_{k,j}$:过程噪声与观测噪声,假设零均值高斯 $N(0, \Sigma)$
要求的是:给定所有观测 Z 和输入 U,估计位姿 X 和路标 L。这是典型的贝叶斯推断——最大后验估计(MAP):
$$X^*, L^* ...
本文基于 rm_pid_tuner 项目的实际开发经验。与大多数讲 PID 的文章不同,这里不满足于”知道三个环节的作用”,而是从数学模型 → 离散化 → 工程实现 → 性能评估 → 自动调参完整链路展开,让你看完能自己写一个带自动调参功能的 PID 控制器。
从传递函数说起:PID 到底在补偿什么几乎所有”PID 入门”文章都会从三个环节的作用讲起,但很少有人问:为什么这三个环节是完备的?
考虑一个典型的直流电机速度环。忽略电感(电气时间常数远小于机械时间常数),电机模型为:
$$E = IR + K_e\omega$$
$$T = K_t I$$
合并得:
$$T = \frac{K_t(E - K_e\omega)}{R} = \frac{K_t}{R}E - \frac{K_t K_e}{R}\omega$$
注意这里的结构:**输入 E(电压)与输出 ω(转速)之间存在一个负反馈项 $\frac{K_t K_e}{R}\omega$**——电机本身就是一个天然的被控对象加内环反馈。加上负载惯量 J 和粘性阻尼 B:
$$J\f...
上一篇(PID 工程实践)解决”控制器怎么写”,这一篇解决”控制器怎么跑在真实硬件上”。ros_control 的文档很多,但大部分停留在”照着模板抄 RobotHW”。这里从控制循环的实时性讲起,一路讲到 CAN 总线电机对接的实战细节。
一、先理解控制循环:50Hz 背后的实时性陷阱ros_control 的核心是一个固定频率的控制循环,典型实现:
12345678910ros::Rate rate(50); // 50Hzwhile (ros::ok()) { ros::Time now = ros::Time::now(); ros::Duration dt = now - prev; robot_hw.read(); // 1. 读硬件状态 cm.update(now, dt); // 2. 更新所有控制器(PID计算) robot_hw.write(); // 3. 写控制指令 prev = now; rate.sleep();}
这个循环看起来简单,但...
调 PID 时最常听到的一句话:”Kp 别加太大,会振荡。”但很少有人解释为什么。这篇用 4 张图,把”传递函数 → 极点 → 振荡”这条链完整走一遍。看完你就能回答:Kp 增大时,系统的极点到底发生了什么。
一、从微分方程到传递函数:一句话概括控制系统的核心问题:输入 u(t) 经过系统,输出 y(t)。 系统内部的行为用微分方程描述,比如电机速度环(忽略电感):
$$J\frac{d\omega}{dt} + B\omega = T(t)$$
对两边做拉普拉斯变换(把”微分”变成”乘以 s”),得到传递函数:
$$G(s) = \frac{\Omega(s)}{T(s)} = \frac{1/J}{s + B/J} = \frac{K}{\tau s + 1}$$
传递函数的关键:分母多项式的根,就是系统的极点。
极点位置 = 系统”本性”的数学表达
它不随输入变化,只由系统自身参数(J、B、R、Kt)决定
输入决定系统”被激发成什么样”,极点决定系统”自己会怎么动”
二、一阶系统:极点越靠左,响应...