Skip to content

Declare the hardware_interface dependency explicitly - #39

Merged
nbbrooks merged 1 commit into
mainfrom
nbbrooks/declare-hardware-interface-dep
Aug 3, 2026
Merged

Declare the hardware_interface dependency explicitly#39
nbbrooks merged 1 commit into
mainfrom
nbbrooks/declare-hardware-interface-dep

Conversation

@nbbrooks

@nbbrooks nbbrooks commented Aug 3, 2026

Copy link
Copy Markdown
Member

Fixes #36.

Why

Both controllers use hardware_interface directly:

include usage
picknik_reset_fault_controller src/…:26 #include "hardware_interface/loaned_command_interface.hpp" using hardware_interface::LoanedCommandInterface;
picknik_twist_controller src/…:31 same header same

Neither declared hardware_interface in package.xml, and neither find_packaged it. They relied on it arriving transitively:

picknik_*_controller -> controller_interface -> hardware_interface

As @Plumezz noted in #36, this is not a build break today. It's a metadata problem: a dependency we use directly is invisible to rosdep and to anyone reading the manifest, and it would break silently if controller_interface ever stopped re-exporting it.

Two additions to the original report: the gap is on main as well as humble, and it affects both packages, not just picknik_reset_fault_controller.

How

For each package:

  • <depend>hardware_interface</depend> in package.xml
  • find_package(hardware_interface REQUIRED)
  • hardware_interface added to THIS_PACKAGE_INCLUDE_DEPENDS, so it's re-exported to consumers alongside the other direct deps
  • ${hardware_interface_TARGETS} in target_link_libraries, matching the ${..._TARGETS} style already used for controller_interface

On the last point — I checked that hardware_interface_TARGETS resolves to hardware_interface::hardware_interface only. mock_components is in a separate export set (export_mock_components) and is not pulled in, so this doesn't widen the link beyond what's intended.

8 lines added, nothing removed.

Verification

Built both packages from a clean workspace in a ros:lyrical-ros-base container: rosdep install resolves the newly-declared dependency, and colcon build succeeds for both.

Separate finding: 12 ignored set_value() return values

Not fixed here, since it needs a behaviour decision rather than a metadata one — but the build surfaces it, so worth recording.

LoanedCommandInterface::set_value() is [[nodiscard]] on lyrical and returns false if it cannot acquire the lock within max_tries (default 10). Both controllers discard it at every call site — 12 -Wunused-result warnings, 6 per package:

  • picknik_reset_fault_controller.cpp: 87, 88, 113, 114, 122, 123
  • picknik_twist_controller.cpp: 148–153
warning: ignoring return value of 'bool hardware_interface::LoanedCommandInterface::set_value(
  const T&, unsigned int) [with T = double]', declared with attribute 'nodiscard' [-Wunused-result]

So both controllers can currently drop a command write silently. Note the read path was already modernised — get_optional() with value_or(...) — so this is the write half of the same API migration left unfinished. Worth its own issue; happy to file it and take it if you want.

Sequencing

Branched off main, so until #38 merges this PR only exercises the currently-active workflows. Once #38 is in I'll rebase so it gets the full matrix, including the blocking lyrical-main job.

The same fix is wanted on the humble branch, which has the identical gap in both packages. Say the word and I'll open that as a companion PR.

Both controllers include <hardware_interface/loaned_command_interface.hpp> and
name hardware_interface::LoanedCommandInterface directly, but neither declared
hardware_interface in package.xml or found it in CMake. They relied on
controller_interface to pull it in transitively:

  picknik_*_controller -> controller_interface -> hardware_interface

That works today and is not a build break, but it means a dependency we use
directly is invisible to rosdep and to anyone reading the manifest, and it would
break silently if controller_interface ever stopped re-exporting it.

Adds, for both packages:
  - <depend>hardware_interface</depend> in package.xml
  - find_package(hardware_interface REQUIRED)
  - hardware_interface in THIS_PACKAGE_INCLUDE_DEPENDS, so it is re-exported to
    consumers alongside the other direct deps
  - ${hardware_interface_TARGETS} in target_link_libraries, matching the
    ${..._TARGETS} style already used for controller_interface. That variable
    resolves to hardware_interface::hardware_interface only -- mock_components
    lives in a separate export set and is not pulled in.

Reported by @Plumezz in #36 against the humble branch; the same gap is present
on main and on humble, and both packages are affected, not just
picknik_reset_fault_controller.

Verified by building both packages from a clean workspace in a
ros:lyrical-ros-base container: rosdep resolves the new dependency and colcon
build succeeds.

Fixes #36

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nbbrooks
nbbrooks merged commit c605b68 into main Aug 3, 2026
7 of 8 checks passed
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.

picknik_reset_fault_controller appears to use hardware_interface directly without declaring it in package.xml

1 participant