Skip to content

Refactor/events/v1#33

Open
KalanaRatnayake wants to merge 42 commits intodevelopfrom
refactor/events/v1
Open

Refactor/events/v1#33
KalanaRatnayake wants to merge 42 commits intodevelopfrom
refactor/events/v1

Conversation

@KalanaRatnayake
Copy link
Collaborator

@KalanaRatnayake KalanaRatnayake commented Feb 18, 2026

Pull Request Template

Description

  • Tested and fixed issues with the new event system
  • Introduced instancing to the capabilities
  • Introduced EventParameters to reduce the usage of tinyXML2 as a whole (runners are now completely free.

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as intended)
  • This change requires a documentation update

How Has This Been Tested?

Tested using examples from fabric

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes do not break the build
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

mik-p and others added 30 commits September 23, 2025 15:13
…gration, remove uuid dependency replace with rclcpp, simpler logging interface, update trigger service function
…in cmake to support uuid gen in higher libraries
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the Capabilities2 event system (v1) by introducing a dedicated capabilities2_events package, migrating runner triggering from XML strings to typed parameters, and updating server/runner APIs to support bonding + instancing.

Changes:

  • Add capabilities2_events (event emitter/node model, UUID generator, published event implementation) and wire it into capabilities2_server.
  • Update runner plugin API to be bond/instance-aware and migrate triggering to typed EventParameters/CapabilityParameter.
  • Update messages/services for triggering + connecting capabilities (TriggerCapability changes, new ConnectCapability) and bump package versions to 0.2.0.

Reviewed changes

Copilot reviewed 67 out of 67 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
changelog.md Adds 0.2.0 release notes.
capabilities2_utils/package.xml Removes deprecated capabilities2_utils package metadata.
capabilities2_utils/include/capabilities2_utils/event_types.hpp Removes legacy event type definitions.
capabilities2_utils/include/capabilities2_utils/connection.hpp Removes legacy connection model (tinyxml2-based).
capabilities2_utils/include/capabilities2_utils/bond_client.hpp Removes legacy bond client wrapper.
capabilities2_utils/CMakeLists.txt Removes deprecated package build config.
capabilities2_server/test/test.cpp Fixes semantic interface API typo in test.
capabilities2_server/readme.md Updates server API docs (bond requirements, ConnectCapability, topics/messages).
capabilities2_server/package.xml Bumps version and updates dependencies to include capabilities2_events.
capabilities2_server/launch/capabilities2_server.launch.py Formatting/refactor of config path building.
capabilities2_server/launch/capabilities2_server.composed.launch.py Formatting/refactor of config path building.
capabilities2_server/include/capabilities2_server/runner_cache.hpp Adapts runner cache to new runner API + event connections.
capabilities2_server/include/capabilities2_server/models/running.hpp Refactors running model to inherit capability identity.
capabilities2_server/include/capabilities2_server/models/readme.md Notes new v3 model proposals (running/connections).
capabilities2_server/include/capabilities2_server/models/provider.hpp Updates provider model inheritance (and minor header changes).
capabilities2_server/include/capabilities2_server/capabilities_server.hpp Integrates new event publisher + ConnectCapability service; updates validation/logging.
capabilities2_server/include/capabilities2_server/capabilities_api.hpp Refactors API for new events + bond-scoped triggering + connections; swaps UUID generation.
capabilities2_server/include/capabilities2_server/bond_cache.hpp Extends bond cache with bond existence checks and doc improvements.
capabilities2_server/CMakeLists.txt Bumps CMake min version and swaps deps to capabilities2_events (drops uuid/backward_ros wiring).
capabilities2_runner/src/system/system_runners.cpp Registers new system runner plugins.
capabilities2_runner/src/standard_runners.cpp Removes prior combined runner registration TU.
capabilities2_runner/src/launch_runner.cpp Adds dedicated LaunchRunner plugin registration TU.
capabilities2_runner/src/dummy_runner.cpp Adds DummyRunner updated to new runner/event API.
capabilities2_runner/readme.md Updates runner docs structure + adds system runner section; retains API snippets.
capabilities2_runner/providers/InputMultiplexRunner.yaml Adds provider spec for InputMultiplexRunner.
capabilities2_runner/providers/GetCapabilitySpecsRunner.yaml Adds provider spec for GetCapabilitySpecsRunner.
capabilities2_runner/plugins.xml Registers new runner plugins in pluginlib manifest.
capabilities2_runner/package.xml Bumps version and exports capability interface/provider YAMLs; adds events dependency.
capabilities2_runner/interfaces/InputMultiplexRunner.yaml Adds interface spec for InputMultiplexRunner.
capabilities2_runner/interfaces/GetCapabilitySpecsRunner.yaml Adds interface spec for GetCapabilitySpecsRunner.
capabilities2_runner/include/capabilities2_runner/topic_runner.hpp Migrates TopicRunner to ThreadTriggerRunner + event emission.
capabilities2_runner/include/capabilities2_runner/threadtrigger_runner.hpp Introduces threaded trigger execution base for runners.
capabilities2_runner/include/capabilities2_runner/system/input_multiplex_runner.hpp Adds system runner for multiplexing trigger inputs.
capabilities2_runner/include/capabilities2_runner/system/get_capability_specs_runner.hpp Adds ServiceRunner-based system runner to query server specs.
capabilities2_runner/include/capabilities2_runner/service_runner.hpp Migrates ServiceRunner to new trigger/thread/event API.
capabilities2_runner/include/capabilities2_runner/runner_base.hpp Refactors RunnerBase to inherit EventNode and use typed EventParameters + bond/instance scoping.
capabilities2_runner/include/capabilities2_runner/notrigger_runner.hpp Adds NoTriggerRunner base for runners that must not be triggered.
capabilities2_runner/include/capabilities2_runner/launch_runner.hpp Reworks LaunchRunner to a no-trigger runner (currently unimplemented).
capabilities2_runner/include/capabilities2_runner/encap_runner.hpp Updates EnCapRunner stop signature + event emission.
capabilities2_runner/include/capabilities2_runner/action_runner.hpp Migrates ActionRunner to ThreadTriggerRunner + EventParameters.
capabilities2_runner/docs/parameter_format.md Adds (placeholder) parameter format documentation.
capabilities2_runner/CMakeLists.txt Updates build inputs + dependencies; installs interface/provider specs.
capabilities2_msgs/srv/TriggerCapability.srv Makes trigger requests bond-scoped and typed (Capability message).
capabilities2_msgs/srv/ConnectCapability.srv Adds service to connect capabilities via connections.
capabilities2_msgs/srv/ConfigureCapability.srv Removes legacy configure service.
capabilities2_msgs/readme.md Updates message/service list and “New in …” notes.
capabilities2_msgs/msg/CapabilityParameter.msg Adds typed parameter message for trigger/event parameters.
capabilities2_msgs/msg/CapabilityEventCode.msg Adds dedicated event code message.
capabilities2_msgs/msg/CapabilityEvent.msg Refactors event payload to use connection + event code + trigger id.
capabilities2_msgs/msg/CapabilityConnection.msg Adds connection type (event code) to the connection message.
capabilities2_msgs/msg/Capability.msg Adds instance_id and typed parameters array.
capabilities2_msgs/CMakeLists.txt Registers new msgs/srvs and updates ordering.
capabilities2_events/src/uuid_generator.cpp Implements UUID string generator.
capabilities2_events/readme.md Adds documentation for the new event subsystem.
capabilities2_events/package.xml Adds new package manifest for event subsystem.
capabilities2_events/include/capabilities2_events/uuid_generator.hpp Declares UUID generator API.
capabilities2_events/include/capabilities2_events/published_event.hpp Implements publisher-backed event emitter.
capabilities2_events/include/capabilities2_events/event_parameters.hpp Implements typed parameter container with conversions.
capabilities2_events/include/capabilities2_events/event_node.hpp Implements connection storage + event emission routing.
capabilities2_events/include/capabilities2_events/event_base.hpp Defines event emitter interface and callback typing.
capabilities2_events/CMakeLists.txt Adds build config for new events library and uuid linkage.
capabilities2_events/.clang-format Adds formatting config for the new package.
capabilities2/package.xml Bumps metapackage version and adds events package dependency.
TODO.md Updates TODO/refactor notes (thread safety, trigger prototype, versions).
.devcontainer/devcontainer.json Updates devcontainer workspace mount and run args.
.devcontainer/Dockerfile Sets workspace workdir and clones external test suite repo.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +170 to +171
[this, &instance_id, &completed, &cv,
&bond_id, &instance_id](const typename rclcpp_action::ClientGoalHandle<ActionT>::WrappedResult& wrapped_result) {
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result_callback lambda capture list captures instance_id twice (&instance_id appears two times). This is a compile error in C++ and will prevent the runner library from building. Remove the duplicate capture and ensure only the needed variables are captured.

Suggested change
[this, &instance_id, &completed, &cv,
&bond_id, &instance_id](const typename rclcpp_action::ClientGoalHandle<ActionT>::WrappedResult& wrapped_result) {
[this, &instance_id, &completed, &cv, &bond_id](
const typename rclcpp_action::ClientGoalHandle<ActionT>::WrappedResult& wrapped_result) {

Copilot uses AI. Check for mistakes.
Comment on lines +124 to +128
if (exec_thread.joinable())
{
// TODO: FIX THIS FUTURE MICHAEL
exec_thread.join();
}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stop_execution() unconditionally calls join() on all threads (and the timeout parameter is effectively unused), so shutdown/destruction can block indefinitely if any execution() never returns. Consider cooperative cancellation (e.g., std::jthread + stop_token) and a bounded shutdown strategy, or remove the timeout argument and document the blocking behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +11
# TODO

Runners can use parameters. These parameters are passed to the runner in the `trigger` function. The parameter format for capabilities2 uses XML. A runner expects to receive a minimal XML structure which includes an ID attribute, for example:

```xml
<parameters id="1234">
```

The `id` is used to identify the runner instance and manage its execution.
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc still states trigger parameters use XML (with an id attribute), but the PR switches to typed parameters (CapabilityParameter[] / EventParameters) and uses bond_id + instance_id for scoping. Update the document so it matches the new parameter representation and how runners should read values.

Suggested change
# TODO
Runners can use parameters. These parameters are passed to the runner in the `trigger` function. The parameter format for capabilities2 uses XML. A runner expects to receive a minimal XML structure which includes an ID attribute, for example:
```xml
<parameters id="1234">
```
The `id` is used to identify the runner instance and manage its execution.
Runners can use parameters. These parameters are passed to the runner in the `trigger` function as **typed parameters**, not XML.
In capabilities2, trigger parameters are represented as a collection of typed values (for example, `CapabilityParameter[]` on capabilities and `EventParameters` on events). Each parameter has a name/key and a strongly typed value (string, number, boolean, etc.), so runners should read values directly from these structures rather than parsing XML.
Each trigger invocation is scoped by two identifiers:
- `bond_id`: Identifies the bond under which the runner is executing.
- `instance_id`: Identifies the specific runner instance within that bond.
Runners should use the combination of `bond_id` and `instance_id` to associate incoming parameters and state with the correct runner instance. When handling a trigger, read the parameter values from the provided typed parameter collection using the parameter names defined in the capability or event schema, and rely on `bond_id` + `instance_id` for scoping instead of an XML `id` attribute.

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +37
BOOL,
DOUBLE,
INT,
STRING,
UNCONVERTED,
VECTOR_BOOL,
VECTOR_DOUBLE,
VECTOR_INT,
VECTOR_STRING
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OptionType enum values don’t match the wire values in capabilities2_msgs/msg/CapabilityParameter.msg (that message defines VECTOR_BOOL = 4, but this enum inserts UNCONVERTED at 4). As a result, static_cast<OptionType>(msg.type) will misinterpret vector types (and likely break parameter decoding). Align the enum numeric values with the message constants (or introduce an explicit mapping function) and consider removing/renaming UNCONVERTED if it’s not part of the on-wire schema.

Suggested change
BOOL,
DOUBLE,
INT,
STRING,
UNCONVERTED,
VECTOR_BOOL,
VECTOR_DOUBLE,
VECTOR_INT,
VECTOR_STRING
// These values must match capabilities2_msgs/msg/CapabilityParameter.msg
BOOL = 0,
DOUBLE = 1,
INT = 2,
STRING = 3,
VECTOR_BOOL = 4,
VECTOR_DOUBLE = 5,
VECTOR_INT = 6,
VECTOR_STRING = 7,
// Internal use only; not part of the on-wire schema
UNCONVERTED = 100

Copilot uses AI. Check for mistakes.
Comment on lines +123 to 127
completed = true;
cv.notify_all();
});

// trigger the events related to on_started state
if (events[id].on_started.interface != "")
{
event_(EventType::STARTED, id, events[id].on_started.interface, events[id].on_started.provider);
triggerFunction_(events[id].on_started.interface, update_on_started(events[id].on_started.parameters));
}

// Conditional wait
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

completed is set and cv.notify_all() is called from the async response callback without holding the same mutex used by cv.wait(...). This introduces a data race on completed and undefined behavior. Protect completed with the mutex (lock in the callback before writing + notify), or use an atomic/shared state object for cross-thread signaling.

Copilot uses AI. Check for mistakes.
Comment on lines 80 to 83
### LaunchRunner

The `Launch Runner` inherits from the `capabilities2_runner::NoTriggerActionRunner` and is a special case. To instatiate this runner, provide a launch file path as the `runner` tag in the capability provider.
The `Launch Runner` inherits from the `capabilities2_runner::NoTriggerActionRunner` and is a special case. To instantiate this runner, provide a launch file path as the `runner` tag in the capability provider.

Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section still references the old runner API (stop() with no args, trigger() using tinyxml2) and says LaunchRunner inherits from NoTriggerActionRunner, but the code now uses stop(bond_id, instance_id) and EventParameters, and LaunchRunner inherits from NoTriggerRunner. Please update the README snippet/description so it matches the current RunnerBase API and class hierarchy.

Copilot uses AI. Check for mistakes.
// generate a reequest from launch_name and package_name
auto request_msg = std::make_shared<Launch::Request>();
// stop the launch process
throw runner_exception("launch runner not implemented yet");
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LaunchRunner::stop() currently throws "launch runner not implemented yet"; the subsequent emit_stopped(...) is unreachable. This makes cleanup/shutdown of launch-file capabilities impossible and may leave processes running. Implement stop/termination semantics (or disable this runner until implemented).

Suggested change
throw runner_exception("launch runner not implemented yet");
// NOTE: concrete implementations should ensure any launched processes are
// properly terminated before or when calling this base implementation.

Copilot uses AI. Check for mistakes.
Comment on lines 6 to 10
#include <capabilities2_server/models/remappable_base.hpp>
#include <capabilities2_server/models/defineable_base.hpp>
#include <capabilities2_server/models/predicateable_base.hpp>
#include <capabilities2_server/models/defineable_base.hpp>
#include <capabilities2_server/utils/sql_safe.hpp>
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate include: defineable_base.hpp is included twice. This is harmless but adds noise and can slow builds; remove the redundant include.

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +37
capabilities2_msgs::msg::CapabilityEventStamped event_msg;
event_msg.header.stamp = rclcpp::Clock().now();
event_msg.event.trigger_id = instance_id;
event_msg.event.code.code = event_code;
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rclcpp::Clock().now() defaults to system time; if the rest of the system expects ROS time (use_sim_time), event timestamps may be inconsistent. Consider injecting a node clock / time source (e.g., using node->get_clock()->now() or a Clock configured for ROS time) so published events follow the node’s time semantics.

Copilot uses AI. Check for mistakes.
Comment on lines 187 to 190
result_ = wrapped_result.result;
completed_ = true;
cv_.notify_all();
completed = true;
cv.notify_all();
};
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to ServiceRunner: completed is set and cv.notify_all() is called from the result callback without holding block_mutex, while cv.wait(lock, ...) reads completed under that lock. This is a data race/UB. Lock the same mutex in the callback before writing completed, or use an atomic/shared state designed for cross-thread signaling.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants