C++机器人算法库CppRobotics:从环境搭建到核心算法实现详解

📅 2026/7/16 23:21:34
C++机器人算法库CppRobotics:从环境搭建到核心算法实现详解
1. 项目概述为什么我们需要一个C的机器人算法库如果你正在机器人、自动驾驶或者无人机领域摸爬滚打或者是一个对高性能计算和算法实现有追求的C开发者那么“CppRobotics”这个名字你很可能已经听过或者至少应该了解一下。这是一个在GitHub上获得了超过2k星标的开源项目它的核心目标非常明确用现代C高质量地复现机器人学中那些经典且关键的算法。为什么这件事值得专门去做在机器人开发的前期无论是学术研究还是工程原型验证Python因其简洁的语法和丰富的生态如NumPy, SciPy, Matplotlib成为了绝对的主流。像“PythonRobotics”这样的项目让算法的理解、验证和可视化变得异常轻松。但是当算法需要从仿真走向真实机器人从原型走向产品级应用时性能、实时性和资源消耗就成了无法回避的硬指标。这时Python的解释执行和GIL全局解释器锁往往就成了瓶颈。C凭借其零成本抽象、对硬件的直接控制能力以及卓越的运行时性能自然成为了将算法落地的首选语言。然而从Python的“算法理解”到C的“工程实现”中间隔着一道不小的鸿沟。这不仅仅是语法翻译更涉及到内存管理、实时性保证、数值稳定性、接口设计等一系列工程挑战。CppRobotics项目本质上就是在填平这道鸿沟。它提供了一个经过良好组织、模块清晰、依赖明确的C代码库涵盖了从定位Localization、建图Mapping、SLAM同步定位与建图到路径规划Path Planning、轨迹生成Trajectory Generation再到运动控制Motion Control的完整算法链条。对于学习者它是一个绝佳的、可编译、可运行、可调试的“算法教科书”对于开发者它是一个可靠的、可以集成到自身项目中的“算法组件库”。我花了相当一段时间去研究、编译并实际运行了这个库里的多个算法。这个过程里有初次编译成功的兴奋也有被依赖库折磨的烦恼更有在调整参数、观察算法行为时获得的深刻理解。接下来我将以一个一线开发者的视角带你深入这个项目不仅告诉你它是什么更会分享如何从零开始把它用起来剖析其中关键算法的实现逻辑并记录下那些官方文档里不会写的“踩坑”经验和性能调优心得。2. 环境搭建与项目编译从克隆到运行第一个Demo拿到一个开源项目第一步永远是让它能在你自己的机器上跑起来。CppRobotics的编译依赖于CMake和几个关键的第三方库这一步走顺了后面的一切才有基础。2.1 核心依赖解析与安装项目在README里列出了几个依赖CMake, OpenCV, Eigen, CppAD/IPOPT用于MPC以及可选的ROS。我们来逐一拆解搞清楚每个依赖的作用以及最稳妥的安装方法。CMake ( 3.10)这是项目的构建系统。没有它你无法生成Makefile或Visual Studio的工程文件。在Ubuntu上直接用sudo apt-get install cmake安装。在Windows上建议从官网下载安装包并记得将cmake.exe的路径添加到系统环境变量PATH中。安装后在终端输入cmake --version验证。Eigen3这是一个纯头文件的C模板库用于线性代数、矩阵和向量运算。机器人算法中充斥着状态向量、协方差矩阵、雅可比矩阵的计算Eigen是事实上的标准。它的“纯头文件”特性意味着你通常不需要编译它只需要确保编译器能找到它的头文件路径。在Ubuntu上sudo apt-get install libeigen3-dev即可。安装后头文件通常位于/usr/include/eigen3。在Windows上你可以从官网下载压缩包解压后记住路径在后续CMake配置中指定Eigen3_DIR。OpenCV ( 3.3)主要用于算法的可视化。项目中的很多Demo都会弹出一个窗口实时显示机器人的运动轨迹、地图和障碍物。虽然算法核心逻辑不依赖OpenCV但没有它你就失去了一个直观的调试和验证工具。在Ubuntu 20.04/22.04上安装OpenCV 4.x通常更简单sudo apt-get install libopencv-dev但需要注意OpenCV 4.x的某些头文件和命名空间与3.x有差异可能导致编译错误。一个更稳妥的方法是按照项目要求从源码编译OpenCV 3.4.x。在Windows上可以使用官方预编译库或者使用vcpkg、MSYS2等包管理器安装。实操心得OpenCV版本陷阱我最初在Ubuntu 22.04上直接安装了系统仓库里的OpenCV 4.5结果编译时遇到了CV_WINDOW_NORMAL等宏定义未找到的错误。这是因为OpenCV 4中一些常量的命名发生了变化。最省事的解决方案就是按照项目要求手动编译安装指定版本的OpenCV。编译命令大致如下wget -O opencv.zip https://github.com/opencv/opencv/archive/3.4.15.zip unzip opencv.zip cd opencv-3.4.15 mkdir build cd build cmake -D CMAKE_BUILD_TYPERELEASE -D CMAKE_INSTALL_PREFIX/usr/local .. make -j$(nproc) sudo make install编译安装后记得运行sudo ldconfig更新动态链接库缓存。CppAD 与 IPOPT这两个是可选依赖仅在编译模型预测控制MPC相关算法时才需要。CppAD是一个用于自动微分计算梯度、雅可比矩阵、黑塞矩阵的C库而IPOPT是一个大规模非线性优化求解器。MPC需要在线求解一个带约束的优化问题这俩就是干这个的。如果你的研究或工作重点不在MPC可以先跳过这能避免很多复杂的依赖问题。如果需要在Ubuntu上可以通过sudo apt-get install cppad ipopt安装注意版本可能较旧或者从源码编译。ROS (可选)项目提到ROS主要用于3D可视化。对于绝大多数2D算法DemoROS不是必须的。除非你打算将算法与ROS生态系统如Gazebo仿真、Rviz可视化深度集成否则可以暂时不安装。2.2 编译流程详解与常见问题排查假设你的依赖都已经就绪接下来就是标准的CMake“三板斧”git clone https://github.com/onlytailei/CppRobotics.git cd CppRobotics mkdir build cd build cmake .. make -j$(nproc) # 在Windows的MSYS2或VS Developer Command Prompt中使用 cmake --build . --config Release如果一切顺利你会在build/bin/目录下看到生成的所有可执行文件例如extended_kalman_filter,a_star,dwa等等。然而现实往往不会这么顺利。下面是我遇到过的几个典型问题及其解决方案问题1CMake找不到Eigen3。CMake Error at CMakeLists.txt:10 (find_package): By not providing FindEigen3.cmake in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by Eigen3, but CMake did not find one.排查与解决这通常是因为Eigen3安装在了非标准路径或者CMake的模块路径不对。首先确认Eigen3已安装apt list --installed | grep eigen。如果已安装可以尝试在CMake命令中显式指定路径cmake -D Eigen3_DIR/usr/include/eigen3/cmake .. # 或者你的Eigen3安装路径如果还不行一个“暴力”但有效的方法是直接修改项目根目录的CMakeLists.txt将find_package(Eigen3 REQUIRED)暂时替换为include_directories(/usr/include/eigen3) # 你的Eigen头文件路径但这会破坏项目的跨平台性仅作临时测试用。问题2链接阶段报错提示未定义的OpenCV引用。undefined reference to cv::imshow(std::__cxx11::basic_stringchar...排查与解决这是典型的链接库缺失或版本不匹配。首先检查CMake输出的信息确认它找到的OpenCV版本是否正确应该是3.x。如果找到的是4.x你需要手动指定OpenCV 3.x的安装路径cmake -D OpenCV_DIR/path/to/your/opencv3/build ..如果路径正确但仍有问题可能是pkg-config配置有冲突。可以尝试在编译前设置环境变量PKG_CONFIG_PATH指向你安装的OpenCV 3的pkgconfig目录。问题3MPC相关代码编译失败。如果你启用了MPC编译默认是注释掉的而CppAD或IPOPT安装有问题编译会失败。错误信息可能非常冗长涉及大量的模板元编程错误。排查与解决首先确保你确实需要MPC功能。如果不需要直接保持CMakeLists.txt中相关部分的注释状态即可。如果需要请严格按照CppAD和IPOPT官方文档进行安装并确保CMake能正确找到它们。在Linux下使用apt安装的版本通常兼容性较好。在Windows下这可能是一个挑战建议使用vcpkg进行管理。注意事项构建目录的清理如果你修改了CMakeLists.txt或者切换了依赖库的版本最干净的做法是删除整个build目录然后从头执行cmake ..和make。直接在原build目录下重新运行cmake有时不能完全更新缓存会导致一些诡异的问题。3. 核心算法模块深度解析成功编译后我们就可以深入代码看看这些经典的机器人算法是如何用C实现的。CppRobotics的代码结构非常清晰主要算法模块都位于src目录下并有对应的头文件在include/cpprobotics中。3.1 定位Localization当机器人不知道自己在哪里定位是机器人知晓自身在环境中位置的过程。CppRobotics实现了三种经典的定位算法对应着不同的传感器模型和环境假设。3.1.1 扩展卡尔曼滤波EKF定位EKF是处理非线性系统状态估计的利器。在这个Demo中机器人有一个粗略的运动模型里程计并且能间歇性地获得带有噪声的绝对位置观测例如GPS信号。EKF的核心就是融合这两个不确定的信息源得到一个更优的位置估计。代码核心解读在src/localization/extended_kalman_filter.cpp中关键步骤在run函数里预测Prediction基于上一时刻的最优估计和当前的控制输入速度、角速度通过运动模型预测当前时刻的状态和协方差。这里使用了里程计模型并计算了该模型下的雅可比矩阵状态转移矩阵F。// 伪代码示意 x_pred motion_model(x_est, u); // u为控制量 F_j jacobian_of_motion_model(x_est, u); // 计算雅可比矩阵F P_pred F_j * P_est * F_j.transpose() Q; // Q为过程噪声协方差更新Update当获得观测值如GPS坐标时计算观测残差实际观测值与预测观测值之差。同样需要计算观测模型的雅可比矩阵H。然后计算卡尔曼增益K这个增益决定了我们是更相信预测还是更相信观测。z_pred observation_model(x_pred); // 预测的观测值 H_j jacobian_of_observation_model(x_pred); y z_true - z_pred; // 观测残差 S H_j * P_pred * H_j.transpose() R; // R为观测噪声协方差 K P_pred * H_j.transpose() * S.inverse(); // 卡尔曼增益 x_est x_pred K * y; // 状态更新 P_est (I - K * H_j) * P_pred; // 协方差更新可视化代码使用OpenCV实时绘制三条轨迹绿色真实轨迹、黑色纯里程计推算轨迹、蓝色EKF估计轨迹。你可以清晰地看到蓝色的EKF轨迹如何有效地修正黑色里程计的累积漂移紧紧跟随绿色真实轨迹。实操心得噪声协方差矩阵Q和R的调节EKF的性能极大程度上依赖于过程噪声Q和观测噪声R的设置。它们代表了你对“运动模型不准”和“传感器不准”的信心程度。Q调大表示你认为运动模型非常不可靠EKF会更信任观测收敛快但可能对观测噪声更敏感。R调大表示你认为传感器噪声很大EKF会更信任自身的预测估计结果更平滑但可能响应变慢。 在实际项目中Q和R需要通过传感器标定或经验来调整。一个技巧是可以先将它们设置为对角矩阵对角线上的值根据传感器精度如GPS的米级误差和运动模型误差来初步设定然后通过实际运行微调。3.1.2 粒子滤波Particle Filter定位粒子滤波是一种非参数化的贝叶斯滤波方法特别适合处理非高斯、多峰的后验概率分布。在机器人定位中它常用于已知地图环境下的全局定位“绑架机器人”问题。算法流程拆解初始化在整张地图上随机撒播大量粒子每个粒子代表一个可能的位置假设。预测根据控制输入运动模型移动所有粒子。这一步会引入随机噪声模拟运动的不确定性。更新重要性采样获取传感器观测例如激光雷达扫描到周围障碍物的距离。计算每个粒子的权重权重值正比于“在该粒子所处位置获得当前观测值的概率”。换句话说和当前观测匹配度越高的粒子权重越大。重采样根据权重重新抽取粒子。高权重的粒子更有可能被多次抽取低权重的粒子被淘汰。这相当于将计算资源集中在概率更高的区域。状态估计通常将所有粒子的位置进行加权平均得到最终的位姿估计。CppRobotics的实现中粒子滤波用于地标Landmark观测的定位。红色点代表地标蓝色轨迹是粒子滤波的估计结果。你可以观察到在开始时粒子云代表不确定性可能很分散随着机器人移动和观测粒子云会逐渐收敛到真实位置附近。注意事项粒子耗散与重采样策略粒子滤波有一个经典问题是“粒子耗散”即经过多次重采样后所有粒子可能都来源于少数几个祖先粒子导致多样性丧失无法应对后续的突变。代码中通常采用系统重采样或残差重采样等策略来缓解。在src/localization/particle_filter.cpp的resampling函数中就实现了系统重采样。理解不同重采样策略的优劣对于实现一个鲁棒的粒子滤波器至关重要。3.2 路径规划Path Planning为机器人找一条路路径规划的目标是在有障碍物的环境中找到一条从起点到终点的无碰撞路径。CppRobotics实现了从经典到前沿的多种规划算法。3.2.1 A算法*A* 可能是最广为人知的图搜索算法。它结合了Dijkstra算法保证找到最短路径和贪婪最佳优先搜索速度快的优点通过一个启发式函数h(n)来指导搜索方向。C实现的关键点在src/path_planning/a_star.cpp中核心数据结构是优先队列通常用std::priority_queue实现。队列中的节点按f(n) g(n) h(n)排序其中g(n)是从起点到当前节点n的实际代价h(n)是从节点n到终点的估计代价启发函数。// 节点结构体示例 struct Node { int x, y; // 网格坐标 double cost; // 这里的cost相当于f(n) // 重载运算符用于优先队列小顶堆 bool operator(const Node other) const { return cost other.cost; // 注意是大于号因为STL的优先队列默认是大顶堆 } };启发函数h(n)通常使用曼哈顿距离或欧几里得距离。在栅格地图中使用对角线允许的欧几里得距离能获得更优的路径。A的效率和质量高度依赖于h(n)的选择。如果h(n)永远不大于从n到终点的实际代价即可采纳的那么A保证找到最优路径。3.2.2 动态窗口法DWADWA是一种经典的局部规划器/避障算法适用于差分驱动或全向移动机器人。它不进行全局路径搜索而是在机器人当前的局部速度空间(v, ω)线速度和角速度中采样一系列速度对模拟这些速度下机器人短时间内的运动轨迹然后根据多个标准如目标方向、与障碍物的距离、速度大小对这些轨迹进行评分选择最优的速度指令执行。算法循环步骤速度空间离散化根据机器人的最大最小速度、加速度限制生成一系列可行的(v, ω)样本。轨迹模拟对每个速度样本利用机器人的运动学模型向前模拟未来一段时间例如3秒的轨迹。轨迹评价对每条模拟轨迹计算一个得分。评价函数通常包括朝向目标轨迹终点方向与目标点方向的偏差。速度倾向于选择更快的速度。障碍物距离轨迹上离最近障碍物的距离距离太近则给极低的分数或直接剔除。选择与执行选择得分最高的轨迹所对应的(v, ω)发送给机器人底层执行。在CppRobotics的DWA Demo中蓝色是目标点红色是机器人黑色是障碍物。你会看到机器人如何灵活地绕开障碍物平滑地接近目标。DWA的实时性很好但它是局部最优的容易陷入局部最小值比如复杂的U型障碍物。3.2.3 RRT快速探索随机树RRT是一种基于采样的规划算法特别适合高维空间如机械臂或复杂障碍物环境。它的思想很直观从起点开始随机在地图空间采样一个点然后在当前的树中找到离这个随机点最近的节点朝着随机点的方向生长一步步长固定如果这一步没有碰撞就将新点加入树中。重复这个过程直到新点接近目标点。实现细节与变种基础RRT生成的路径往往不是最优的而且曲折。因此有了很多改进如RRT*渐进最优、Informed RRT*在椭圆区域内采样加速收敛。CppRobotics实现的是基础RRT代码在src/path_planning/rrt.cpp。它的优点是概率完备只要时间足够总能找到路径且在高维空间比基于网格的A*高效得多。缺点是路径质量一般且由于随机性每次运行结果都可能不同。3.3 路径跟踪控制Path Tracking Control让机器人沿着路走规划出一条路径后如何控制机器人准确地跟踪这条路径这就是控制器的任务。CppRobotics实现了两种主流的控制器LQR和MPC。3.3.1 LQR线性二次调节器控制LQR是一种最优控制器它需要一个线性化的系统模型。在路径跟踪中我们通常使用车辆的运动学模型如自行车模型并在参考路径点附近进行线性化得到一个误差状态空间模型。LQR通过求解一个Riccati方程得到最优的状态反馈增益矩阵K使得控制量u -K * x能最小化一个二次型代价函数权衡跟踪误差和控制量大小。在src/path_tracking/lqr_speed_steering_control.cpp中系统状态x通常是横向误差、航向误差等控制量u是前轮转角和速度。代码的核心是构建系统矩阵A、控制矩阵B以及权重矩阵Q和R然后调用care或dare函数连续或离散代数Riccati方程求解器计算增益K。实操心得LQR权重矩阵Q和R的调节与EKF中的Q、R类似LQR的Q和R决定了控制器对状态误差和控制量大小的“惩罚”程度。增大Q意味着你希望状态误差如横向偏差快速收敛到零控制器会变得更“激进”可能产生较大的控制量。增大R意味着你希望控制动作如方向盘转角尽可能平滑、小控制器会变得更“保守”收敛速度可能变慢。 调试时通常先将R设为单位矩阵然后调整Q中对角线上对应你最关心的状态误差的权重。例如如果你更关心横向误差就加大Q中对应横向误差位置的权重。需要在实际仿真或实车中反复调试在跟踪精度和乘坐舒适性/执行器损耗之间取得平衡。3.3.2 模型预测控制MPCMPC是更高级、也更通用的控制方法。它不像LQR只计算当前时刻的最优控制而是预测未来一段时间预测时域的系统行为并求解一个有限时域的最优控制序列但只执行序列中的第一个控制量到下一时刻再重新进行预测和优化。这种方法能显式地处理系统的约束如转向角限制、加速度限制。CppRobotics的MPC实现依赖于CppAD和IPOPT来求解这个在线优化问题。在src/path_tracking/model_predictive_speed_steering_control.cpp中优化问题的构建是关键定义优化变量通常是预测时域内每一步的控制量速度、前轮转角。定义代价函数与LQR类似是预测时域内状态误差和控制量的加权平方和。定义约束包括系统动力学约束运动学模型、控制量上下限约束、初始状态约束等。求解调用IPOPT求解器得到最优控制序列。MPC的性能非常强大能处理非线性和约束但计算负担也重得多对求解器的实时性要求高。Demo中黄色的“x”就是MPC在每个控制周期内预测的参考轨迹你可以看到控制器是如何“前瞻”并提前做出调整的。注意事项MPC的实时性挑战MPC的在线优化计算耗时与预测时域长度、状态/控制变量维度呈指数关系。在嵌入式平台或对实时性要求极高的场景如高速自动驾驶必须仔细权衡预测时域长度和模型复杂度。常见的做法是使用线性时变模型、缩短预测时域或者采用显式MPC等加速技术。在CppRobotics的Demo中由于是离线仿真计算时间不是问题但在实际部署时必须重点评估。4. 项目工程化思考与扩展建议CppRobotics作为一个优秀的教学和研究代码库为我们提供了清晰的算法实现。但如果想将其用于更严肃的项目或产品中还需要从工程角度进行一些思考和改造。4.1 代码结构与接口设计目前的代码结构以算法Demo为主每个可执行文件包含了从参数初始化、算法循环到可视化的完整流程。在实际项目中我们需要将算法核心与数据IO如传感器输入、可视化、具体业务逻辑解耦。改造建议创建算法类库将每个算法如AStar,DWA,EKF封装成独立的C类。类应该提供清晰的接口例如class AStarPlanner { public: AStarPlanner(const GridMap map); bool plan(const Point2D start, const Point2D goal, std::vectorPoint2D path); void setHeuristic(HeuristicType type); // ... };抽象数据接口定义统一的地图接口MapBase、传感器数据接口SensorData等。这样算法可以独立于具体的传感器激光雷达、摄像头、GPS和地图表示栅格、拓扑、点云工作。分离可视化将OpenCV绘图代码抽离成独立的模块或回调函数。在生产环境中可视化可能被更专业的工具如ROS Rviz、Web前端替代。4.2 性能优化与数值稳定性C的优势在于性能但写出高性能的数值计算代码需要技巧。优化点Eigen的使用技巧Eigen的表达式模板Expression Templates在编译期优化运算但要避免在循环中创建临时小矩阵。对于固定大小的小矩阵如3x3, 4x4使用Eigen::Matrix的模板参数Eigen::Matrix来启用静态内存分配避免动态内存开销。内存预分配在粒子滤波、RRT等算法中需要频繁增删容器元素。提前reserve()足够的内存空间可以避免多次重新分配带来的性能损失。避免虚函数开销在性能关键的循环中避免通过虚函数接口调用。可以使用CRTP奇异递归模板模式等静态多态技术。数值稳定性在卡尔曼滤波中协方差矩阵P需要保持对称正定。在代码更新P时可以加入P (P P.transpose()) / 2.0;来强制对称。在计算矩阵逆时如卡尔曼增益中的S矩阵求逆对于小矩阵可以直接求逆对于大矩阵或病态矩阵应使用更稳定的QR分解或Cholesky分解求解线性系统。4.3 测试与仿真算法的正确性和鲁棒性必须通过充分的测试来保证。单元测试使用Google Test或Catch2等框架为每个算法模块的核心函数编写单元测试。例如测试A*在简单地图上是否能找到路径测试EKF在给定输入下输出是否符合预期。集成测试与仿真搭建一个轻量级的2D仿真环境模拟机器人的运动、传感器噪声和障碍物。用这个仿真环境对完整的“感知-规划-控制”流水线进行测试。CppRobotics自身的Demo就是一个很好的起点可以将其改造成一个可配置的仿真测试框架。参数自动化调优像DWA的评价函数权重、LQR的Q/R矩阵等参数手动调试费时费力。可以引入简单的自动化方法如网格搜索、随机搜索甚至贝叶斯优化在仿真环境中自动寻找一组在多种场景下表现良好的参数。4.4 与现代C特性及ROS2集成C17/20考虑使用现代C特性提升代码质量和安全性。例如用std::optional表示可能失败的计算结果用std::variant表示多种类型的传感器数据用std::filesystem处理路径用std::span传递数组视图避免拷贝。ROS2集成ROS2是机器人领域的事实标准中间件。可以将封装好的算法类包装成ROS2的节点Node。例如创建一个PlannerNode它订阅/goal_pose话题目标点订阅/map和/odom话题地图和里程计运行规划算法然后将路径发布到/global_plan话题。这样算法就能轻松融入ROS2生态与导航栈Nav2等组件协同工作。5. 从学习到实践我的个人路线图建议如果你被这个项目吸引想系统地学习并应用这些知识我建议遵循一个“理论-仿真-实践”的渐进路线第一阶段理解与运行通读代码选择一两个你最感兴趣的算法比如从A*和EKF开始仔细阅读src和include下的代码。对照《概率机器人》、《机器人学中的状态估计》等经典教材理解每一行代码对应的数学公式。成功编译并运行所有Demo按照第二部分的环境搭建指南克服依赖问题确保每个Demo都能跑起来。通过调整源码中的参数如噪声大小、权重观察算法行为的变化这是加深理解最有效的方式。第二阶段修改与实验“破坏性”实验尝试故意“破坏”算法。例如在EKF中把过程噪声Q设得极大或极小观察估计轨迹如何发散在A*中换用不同的启发函数比较路径质量和搜索速度在DWA中修改评价函数的权重看看机器人行为有何不同。实现小功能尝试给现有算法添加新功能。例如为RRT算法增加一个路径后处理函数对找到的路径进行平滑使用样条插值为粒子滤波增加一个自适应粒子数目的策略。第三阶段集成与创新构建迷你项目不依赖OpenCV的图形界面用纯文本或简单日志输出将2-3个算法串联起来。例如用A*做全局规划用DWA做局部规划和避障用EKF进行融合定位模拟一个完整的自主移动机器人导航流程。移植到仿真器尝试将算法移植到更专业的机器人仿真平台如Gazebo配合ROS/ROS2或Webots。在仿真中你可以获得更真实的物理引擎、传感器模型测试算法在更复杂环境下的表现。贡献与分享如果你修复了bug优化了性能或者实现了新的算法可以考虑向CppRobotics原项目提交Pull Request。也可以将你的学习笔记、实验过程整理成博客或视频分享出来教是最好的学。机器人学是一个理论与实践紧密结合的领域。CppRobotics提供了一个绝佳的桥梁将书本上的公式变成了屏幕上可交互、可修改的代码。通过亲手运行、修改和调试这些代码你对算法的理解会远远超过仅仅阅读论文或教材。这个过程可能会遇到不少编译错误和逻辑bug但每一次解决问题的经历都是你向成为一名合格的机器人工程师迈出的坚实一步。