如何在ROS2 Eloquent中有效应用断言?
在ROS2 Eloquent中实现有效断言的方案
修复原生assert()的调试信息缺失问题
原生assert()看不到具体位置,大概率是编译时没开调试符号或者被定义了NDEBUG宏禁用了断言信息。解决步骤:
- 在项目的
CMakeLists.txt中明确设置Debug构建类型:set(CMAKE_BUILD_TYPE Debug) - 如果用colcon编译,直接通过命令行强制Debug构建:
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debug
这样编译后,assert()触发时会直接在终端输出断言表达式、所在文件和行号,gdb调试时也能直接定位到对应代码行。
自定义ROS风格的断言宏
ROS2 Eloquent确实没有内置的rcpputils::assert_true()(该接口从Foxy版本才引入),可以自己实现类似ROS1ROS_ASSERT()的宏,结合ROS日志输出更友好的信息:
#include <cassert> #include "rclcpp/rclcpp.hpp" // 基础断言宏 #define ROS2_ASSERT(expr) \ do { \ if (!(expr)) { \ RCLCPP_FATAL(rclcpp::get_logger("assert"), "断言失败: 表达式[%s], 文件[%s], 行号[%d]", #expr, __FILE__, __LINE__); \ assert(expr); \ } \ } while(0) // 带自定义消息的断言宏(可选) #define ROS2_ASSERT_MSG(expr, ...) \ do { \ if (!(expr)) { \ RCLCPP_FATAL(rclcpp::get_logger("assert"), "断言失败: 表达式[%s], 文件[%s], 行号[%d] - " __VA_ARGS__, #expr, __FILE__, __LINE__); \ assert(expr); \ } \ } while(0)
使用时直接调用ROS2_ASSERT(your_condition)或者ROS2_ASSERT_MSG(your_condition, "自定义消息: %d", value),触发时会先通过ROS日志系统输出详细信息,再调用原生assert()终止进程,方便从终端或ROS日志工具中排查问题。
用GDB快速定位断言位置
如果坚持用原生assert(),可以直接用GDB启动节点,不用事后attach:
gdb --args ./install/your_package/lib/your_package/your_node
当进程触发SIGABRT时,输入bt命令就能打印完整调用栈,直接找到断言失败的代码位置。
内容的提问来源于stack exchange,提问作者Joachim Zhang
相关产品推荐
相关产品推荐

