Skip to main content

C++ Workspaces

ros2inspector has first-class support for C++ packages using Tree-sitter for accurate AST-level parsing.

What it detects

For C++ nodes, ros2inspector finds:

  • Classes inheriting from rclcpp::Node
  • Classes inheriting from rclcpp_lifecycle::LifecycleNode
  • All create_publisher<T>(), create_subscription<T>(), create_service<T>(), create_client<T>() calls
  • Template type arguments resolved to message type strings
  • Action servers and clients

Typical C++ node

#include "rclcpp/rclcpp.hpp"
#include "geometry_msgs/msg/twist.hpp"
#include "nav_msgs/msg/odometry.hpp"

class MyController : public rclcpp::Node
{
public:
MyController() : Node("my_controller")
{
cmd_pub_ = this->create_publisher<geometry_msgs::msg::Twist>("/cmd_vel", 10);
odom_sub_ = this->create_subscription<nav_msgs::msg::Odometry>(
"/odom", 10,
std::bind(&MyController::odomCallback, this, std::placeholders::_1)
);
}

private:
void odomCallback(const nav_msgs::msg::Odometry::SharedPtr msg) {}

rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr cmd_pub_;
rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_;
};

ros2inspector extracts:

Node: MyController
language: cpp
publishers: ["/cmd_vel"]
publisher_types: ["geometry_msgs/Twist"]
subscriptions: ["/odom"]
subscription_types: ["nav_msgs/Odometry"]

Lifecycle nodes

#include "rclcpp_lifecycle/lifecycle_node.hpp"

class MySensor : public rclcpp_lifecycle::LifecycleNode
{
public:
MySensor() : LifecycleNode("my_sensor")
{
scan_pub_ = this->create_publisher<sensor_msgs::msg::LaserScan>("/scan", 10);
}
// ...
};

This is detected the same way as a regular rclcpp::Node.

Mixed Python + C++ workspaces

ros2inspector handles both in the same workspace scan:

ros2inspector nodes
┌──────────────────┬──────────────┬──────────┬───────────────────────┐
│ Node │ Package │ Language │ Publishers │
├──────────────────┼──────────────┼──────────┼───────────────────────┤
│ MyController │ my_pkg │ cpp │ /cmd_vel │
│ MySensor │ sensor_pkg │ cpp │ /scan │
│ DataProcessor │ proc_pkg │ python │ /processed_data │
└──────────────────┴──────────────┴──────────┴───────────────────────┘

Filter to C++ only:

ros2inspector packages --filter cpp

Known limitations

Template metaprogramming

Topic names computed via template metaprogramming are not resolved:

// Not detected
template<typename T>
class GenericNode : public rclcpp::Node {
auto pub_ = create_publisher<T>(TopicName<T>::value, 10);
};

Macro-generated nodes

Nodes registered via PLUGINLIB_EXPORT_CLASS or custom macros may not be detected if the class definition is hidden inside the macro.

Dynamic topic names from parameters

// Not captured — flagged as has_dynamic_names: true
auto topic = this->get_parameter("topic").as_string();
pub_ = create_publisher<std_msgs::msg::String>(topic, 10);

Header files

ros2inspector parses .cpp, .hpp, and .h files. If your node class is defined in a header file, it will be detected correctly.

Performance

C++ parsing with Tree-sitter is fast (~50ms per file), and results are cached. A 20-package C++ workspace typically analyzes in under 2 seconds after the first run.