Skip to content

feat: add autoware_command_gate and its tests#1012

Open
sasakisasaki wants to merge 2 commits intoautowarefoundation:mainfrom
sasakisasaki:feat-add-initial-autoware-command-gate
Open

feat: add autoware_command_gate and its tests#1012
sasakisasaki wants to merge 2 commits intoautowarefoundation:mainfrom
sasakisasaki:feat-add-initial-autoware-command-gate

Conversation

@sasakisasaki
Copy link
Copy Markdown
Contributor

Description

Add the autoware_command_gate package to the autoware.core control stack. This package provides a minimal gateway that exposes operation-mode change services (API and system) and publishes matching operation-mode state and gear commands. STOP requests map to gear PARK, AUTONOMOUS requests map to gear DRIVE, and LOCAL/REMOTE requests emit gear NONE. The launch file starts the node as autoware_command_gate_exe.

Related links

This PR is the split PR that of:

How was this PR tested?

For tests, I used a branch based on this PR.

I tested using the planning simulation and scenario simulation workflow. Please see README, all the steps I tested are written there.

Quick Note:

  • Build and launch planning/scenario simulation from README.md.
  • Called the operation-mode change services and confirmed /api/operation_mode/state,
    /system/operation_mode/state, and /control/command/gear_cmd were published.

Notes for reviewers

  • The node publishes both /api/operation_mode/state and /system/operation_mode/state with reliable, transient-local QoS and emits a gear command on each service call.
  • API services cover STOP and AUTONOMOUS; the system service also supports LOCAL and REMOTE (gear NONE).
  • No parameters are introduced.

Interface changes

Topic changes

Additions and removals

Change type Topic Type Topic Name Message Type Description
Added Pub /api/operation_mode/state autoware_adapi_v1_msgs/msg/OperationModeState Published on each service call (reliable, transient-local QoS).
Added Pub /system/operation_mode/state autoware_adapi_v1_msgs/msg/OperationModeState Published on each service call (reliable, transient-local QoS).
Added Pub /control/command/gear_cmd autoware_vehicle_msgs/msg/GearCommand Gear command emitted on each service call.

Service changes

Additions and removals

Change type Service Name Service Type Description
Added /api/operation_mode/change_to_stop autoware_adapi_v1_msgs/srv/ChangeOperationMode Requests STOP mode and publishes outputs.
Added /api/operation_mode/change_to_autonomous autoware_adapi_v1_msgs/srv/ChangeOperationMode Requests AUTONOMOUS mode and publishes outputs.
Added /system/operation_mode/change_operation_mode autoware_system_msgs/srv/ChangeOperationMode Requests system STOP/AUTONOMOUS/LOCAL/REMOTE and publishes outputs.

ROS Parameter Changes

Additions and removals

Change type Parameter Name Type Default Value Description
None - - - -

Effects on system behavior

  • Enables command gating behavior by introducing the autoware_command_gate package and emitting consistent operation-mode state and gear outputs for API and system requests.

@sasakisasaki sasakisasaki requested review from a team, mitsudome-r, xmfcx and youtalk as code owners April 3, 2026 07:21
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

Thank you for contributing to the Autoware project!

🚧 If your pull request is in progress, switch it to draft mode.

Please ensure:

@sasakisasaki sasakisasaki self-assigned this Apr 3, 2026
@sasakisasaki sasakisasaki added run:build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci) component:control labels Apr 3, 2026

EXPECT_TRUE(outputs.status.success);
EXPECT_EQ(outputs.status.code, 0);
EXPECT_EQ(outputs.status.message, "Switched to STOP");
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Perhaps we can omit tests for message check as it is kind of cosmetic.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 3, 2026

Codecov Report

❌ Patch coverage is 90.10989% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.83%. Comparing base (37ae000) to head (7779e16).

Files with missing lines Patch % Lines
...utoware_command_gate/src/autoware_command_gate.cpp 82.35% 6 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1012      +/-   ##
==========================================
+ Coverage   56.70%   56.83%   +0.13%     
==========================================
  Files         375      378       +3     
  Lines       23276    23367      +91     
  Branches    10969    11005      +36     
==========================================
+ Hits        13198    13280      +82     
- Misses       7276     7282       +6     
- Partials     2802     2805       +3     
Flag Coverage Δ *Carryforward flag
daily-humble 56.02% <ø> (ø) Carriedforward from 37ae000
daily-jazzy 56.21% <ø> (ø) Carriedforward from 37ae000
differential-humble 88.17% <90.10%> (?)
differential-jazzy 86.66% <88.63%> (?)
total 49.99% <ø> (ø) Carriedforward from 37ae000
total-humble 56.03% <ø> (ø) Carriedforward from 37ae000
total-jazzy 56.22% <ø> (ø) Carriedforward from 37ae000

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

sasakisasaki and others added 2 commits April 10, 2026 12:52
@xmfcx xmfcx force-pushed the feat-add-initial-autoware-command-gate branch from c4d4b94 to 7779e16 Compare April 10, 2026 09:52
Comment on lines +34 to +68
namespace spec
{
struct ChangeToStop
{
using Service = autoware_adapi_v1_msgs::srv::ChangeOperationMode;
static constexpr char name[] = "/api/operation_mode/change_to_stop";
};

struct ChangeToAutonomous
{
using Service = autoware_adapi_v1_msgs::srv::ChangeOperationMode;
static constexpr char name[] = "/api/operation_mode/change_to_autonomous";
};

struct OperationModeState
{
using Message = autoware_adapi_v1_msgs::msg::OperationModeState;
static constexpr char name[] = "/api/operation_mode/state";
};

struct GearCommand
{
using Message = autoware_vehicle_msgs::msg::GearCommand;
static constexpr char name[] = "/control/command/gear_cmd";
};
} // namespace spec

namespace system
{
struct OperationModeState
{
using Message = autoware_adapi_v1_msgs::msg::OperationModeState;
static constexpr char name[] = "/system/operation_mode/state";
};
} // namespace system
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These specs are duplicated from here:

struct ChangeToStop
{
using Service = autoware_adapi_v1_msgs::srv::ChangeOperationMode;
static constexpr char name[] = "/api/operation_mode/change_to_stop";
};
struct ChangeToAutonomous
{
using Service = autoware_adapi_v1_msgs::srv::ChangeOperationMode;
static constexpr char name[] = "/api/operation_mode/change_to_autonomous";
};

struct OperationModeState
{
using Message = autoware_adapi_v1_msgs::msg::OperationModeState;
static constexpr char name[] = "/api/operation_mode/state";
static constexpr size_t depth = 1;
static constexpr auto reliability = RMW_QOS_POLICY_RELIABILITY_RELIABLE;
static constexpr auto durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;
};

struct OperationModeState
{
using Message = autoware_adapi_v1_msgs::msg::OperationModeState;
static constexpr char name[] = "/system/operation_mode/state";
static constexpr size_t depth = 1;
static constexpr auto reliability = RMW_QOS_POLICY_RELIABILITY_RELIABLE;
static constexpr auto durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;
};

Only the GearCommand is unique. Should they be reused instead?

Comment on lines +84 to +86
rclcpp::QoS state_qos(depth);
state_qos.reliable();
state_qos.transient_local();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

QoS is manually constructed as rclcpp::QoS(1).reliable().transient_local() instead of using the spec-defined QoS (e.g. get_qos<T>()). Functionally correct today but will drift if specs change.


target_include_directories(${PROJECT_NAME}_node
PUBLIC
include
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
include

There is no include folder.

Comment on lines +42 to +44
ament_add_gtest(test_ros_integration
test/integration/test_ros_integration.cpp
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
ament_add_gtest(test_ros_integration
test/integration/test_ros_integration.cpp
)
ament_add_ros_isolated_gtest(test_ros_integration
test/integration/test_ros_integration.cpp
)

I didn't test it but this might be a better way to do this as test numbers grow.

Comment on lines +18 to +19
<depend>autoware_vehicle_msgs</depend>
<depend>rclcpp</depend>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
<depend>autoware_vehicle_msgs</depend>
<depend>rclcpp</depend>
<depend>autoware_vehicle_msgs</depend>
<depend>builtin_interfaces</depend>
<depend>rclcpp</depend>

command_gate_mode_builder.hpp directly includes <builtin_interfaces/msg/time.hpp> but it's not a direct <depend>. Works transitively but violates package isolation.

foreach(target ${PROJECT_NAME}_node test_command_gate_mode_builder test_ros_integration)
if(TARGET ${target})
target_compile_options(${target} PRIVATE -O0 -g --coverage)
target_link_options(${target} PRIVATE --coverage)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Consider removing this entire ENABLE_COVERAGE block (lines 63-100).

No other package in autoware_core has custom coverage CMake targets. The workspace already handles coverage collection:

  1. Build-time: CI uses the coverage-gcc mixin which injects --coverage via CMAKE_CXX_FLAGS globally to all packages.
  2. Test-time: CI runs colcon lcov-result to capture gcov data workspace-wide.
  3. Upload: The resulting total_coverage.info is uploaded to Codecov.

This custom ENABLE_COVERAGE option is never set by CI (defaults to OFF), so the coverage_unit and coverage_integration targets are never created in CI. When the workspace-level --coverage flag is active, gcov data is already generated for this package's tests and collected by colcon lcov-result without any per-package opt-in.

The one argument for keeping it is local developer convenience (per-package HTML reports), but that's achievable with the standard workspace commands and is not a convention any other package follows. Keeping it risks future packages cargo-culting this pattern, fragmenting the build.

Copy link
Copy Markdown
Contributor

@xmfcx xmfcx left a comment

Choose a reason for hiding this comment

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

Thanks for the work on this, the package is well-structured and the test coverage is solid (both unit and integration tests for all four modes is great). The separation of the builder logic from the ROS node is clean, and the gating via launch_command_gate: false is the right call for avoiding conflicts with universe.

A few things to address before this can be merged:

  1. Use existing interface specs (autoware_command_gate.cpp:36-68): Four of the five locally-declared structs (ChangeToStop, ChangeToAutonomous, OperationModeState, system::OperationModeState) already exist in autoware_adapi_specs/operation_mode.hpp and autoware_component_interface_specs/system.hpp. Reusing them avoids drift if topic names or QoS change upstream. GearCommand is the only one that's genuinely new.

  2. QoS from specs (autoware_command_gate.cpp:84-86): Once the specs are used, the QoS (depth, reliability, durability) comes for free instead of being manually constructed.

  3. Remove phantom include dir (CMakeLists.txt:14): The include directory doesn't exist.

  4. Add builtin_interfaces to package.xml: Directly included but not declared as a dependency.

  5. Remove custom coverage block (CMakeLists.txt:63-100): No other package in autoware_core does this. The workspace-level coverage-gcc mixin and colcon lcov-result already handle everything. See inline comment for details.

  6. Consider ament_add_ros_isolated_gtest for the integration test to match the project convention.

The inline comments have more details on each point. Happy to discuss any of these if you have questions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:control run:build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants