Skip to content

Release 2.7.0#1279

Closed
bjsowa wants to merge 45 commits into
ros2from
release/2.7.0
Closed

Release 2.7.0#1279
bjsowa wants to merge 45 commits into
ros2from
release/2.7.0

Conversation

@bjsowa

@bjsowa bjsowa commented May 27, 2026

Copy link
Copy Markdown
Member

No description provided.

bjsowa and others added 30 commits September 9, 2025 01:09
* chore: Remove kilted and rolling ci workflows

* Remove stale workflow and dependabot config
* Add helper Protocol classes for ROS interface type checking

* Add type annotations to ros_loader

* Add type annotations to message_conversion

* Add type annotations to rosapi

* Add type annotations to protocol

* Add type annotations and simplify logging in defragmentation

* Remove ReceivedFragments singleton class, use class variable instead

* Add type annotations to fragmentation capability

* Add type variables for ROS interface types

* Use Clock instead of ROSClock in message_conversion

* Add type annotations to rosbridge_library internal modules

* Add type annotations to capabilities

* Fix mypy issues in protocol

* Add type annotation to util functions

* Improve future type annotation

* Small improvements in rosapi type annotations

* Pass result typevar to Future generic

* Fix spelling mistake

* Add type annotation to capability tests

* Fix args type for actions and services

* Add type annotation for capability message fields

* Reformat

* Disable some modules from annotation checks

* Allow empty callback in Subscription helper class

* Ignore encode_json assignment error

* Ignore no-redef mypy errors

* Add type annotation and resolve mypy errors in rosbridge_library

* Add type annotations to topic/service/action glob lists

* Add type annotation to rosbridge_server src

* Add type annotations to rosbridge_server tests

* Enable flake8-annotation linter checks

* Remove unused import

* Add type annotations for param variables

* Use __future__.annotations in every source file

* Set minimal python version to 3.10

* Fix assert in message_conversion

* Remove error messages from asserts in message_conversion

The asserts are self-explanatory

* Fix a typo

* Fix shebangs and make all of the tests runnable as scripts

It's either none of them or all of them

* Use __futute__.annotations in all tests

* Fix formatting

* Use list_types tuple

* Create ROSClock instead of Clock when clock not provided

* Fix BSON types

* Use Any type for inst argument in InvalidMessageException

* Raise TypeError instead of AssertionError on type mismatch

* Remove unsupported type arguments

* Backport rclpy action type checking classes

* Fix/ignore other mypy errors
* Fix mypy errors (backport #1084)

* Fix lint errors
* Run pre-commit autoupdate

* Fix new ruff errors
* Update changelogs

* 2.4.0
…backport #1107) (#1109)

* feat: Replace cbor with cbor2 library, remove inline implementation

* Add simple test for encoding ROS message to CBOR
…vices_glob` parameter (backport #1115) (#1116)

* Support empty lists for globs

* Parse empty globs to None instead of empty list

* Default to empty globs instead of [*]

* fix: prevent appending to services_glob if it is None
* Update changelogs

* 2.4.1
Co-authored-by: Mike Lanighan <45465435+mlanighan@users.noreply.github.com>
* Update changelogs

* 2.4.2
Co-authored-by: Matthijs van der Burgh <MatthijsBurgh@outlook.com>
* Add error logging when service is unadvertised during in-flight request

* Fix service destruction method in AdvertisedServiceHandler

* Fix unadvertise service test

* Try to fix failing topic subscription assertions by adding a timeout

* Remove redundant sleeps

* Remove extra call to destroy service after graceful shutdown

* Re-raise original exception in handle_request
* add server timeout exception

* forward rejected goal handles

The goal_response_cb should not throw an exception, so the exception is passed in the result and then raised in  send_goal

* return an empty result when result was None due to cancellation/abortion

* fix lint error

---------

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
…#1162)

* Fix numpy.ndarray not handled in CBOR serialization

* Add test for numpy.ndarray handling in CBOR conversion

Co-authored-by: atofetti-botbot <atofetti@botbot.bot>
Co-authored-by: FieldSwan <michael.swan@fieldai.com>
…) (#1179)

* fix: Deadlock in concurrent module import in ros_loader (backport #1173)

* Fix deadlock issue on init

* Add initialization race condition and deadlock tests.

* Fix Future type hint

---------

Co-authored-by: FieldSwan <michael.swan@fieldai.com>
* Integration test instrumentation fix

* Revert unnecessary startup fix and remove corresponding always passing test

(cherry picked from commit 85ff1cd)

# Conflicts:
#	rosbridge_server/CMakeLists.txt
#	rosbridge_server/test/websocket/startup_race.test.py

* Fix conflicts

---------

Co-authored-by: FieldSwan <michael.swan@fieldai.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
* fix: Prevent client destruction race condition (#1183)

* Client creation/destruction race condition stress test

* Fix race condition with client destruction

* Use ros isolated pytest (#4)

---------

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit 5b20a2e)

# Conflicts:
#	rosbridge_server/CMakeLists.txt

* Fix conflicts

---------

Co-authored-by: FieldSwan <michael.swan@fieldai.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
… advertised (backport #1203) (#1205)

* feat: Create topic registrations in publish when topic not previously advertised (#1203)

* fix: Ensure reactor stops after websocket test execution

* fix: Ensure exceptions in websocket tests are reported correctly

* feat: Add test for advertise and publish publisher creation

* fix: Prevent duplicate publisher registration for existing topics

* Store topic registration in protocol class

* feat: Create topic registrations in publish when topic not previously advertised

* Remove redundant comment

* refactor: Simplify PublisherManager publish

* fix: Change log level from warn to info for unregistered topic publishing

* Update rosbridge_library/src/rosbridge_library/internal/publishers.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: Rename variable from aid to adv_id for clarity in advertisement handling

* fix: Improve error message formatting for unregistered topic exception

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
(cherry picked from commit 54598c2)

# Conflicts:
#	rosbridge_server/CMakeLists.txt

* Fix conflicts

---------

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
* Fix subscription creation and destruction race conditions

* Send fewer messages to closed websocket.

* Update rosbridge_library/src/rosbridge_library/internal/subscribers.py



---------


(cherry picked from commit 7a02d34)

Co-authored-by: FieldSwan <michael.swan@fieldai.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat: Cache rosapi get/set parameter clients (#1201)

* feat: Implement client caching for parameter services with cleanup mechanism

* Fix spelling

* Ignore mypy error

* fix: Enhance type hinting for parameter service clients

* Increase the cleanup timer period

* Use node.destroy_client

* Use counter instead of bool flag

* Fix mypy error

* Reformat

* Add docstring for _CachedClient

* fix: Improve client retrieval logic in _get_client function

(cherry picked from commit a62b886)

# Conflicts:
#	rosapi/src/rosapi/params.py

* Fix conflicts

---------

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit 03858b2)

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
bjsowa and others added 15 commits April 2, 2026 07:37
* docs: Clarify special handling of time fields

* Add tests for header and time fields population

* fix: Auto-populate header.stamp when header omitted

* fix: Validate header type in populate_instance function

(cherry picked from commit 42ce055)

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
…erations (backport #1150) (#1226)

* feat: Add QoS Profile support for advertise, publish and subscribe operations (#1150)

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit 8461d3d)

# Conflicts:
#	rosbridge_library/src/rosbridge_library/internal/publishers.py
#	rosbridge_library/src/rosbridge_library/internal/subscribers.py

* Fix conflicts

---------

Co-authored-by: Roald Schaum <178021507+Roald-Schaum@users.noreply.github.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit 3a62e07)

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
…ges (#1239) (#1241)

(cherry picked from commit 0e34327)

Co-authored-by: Harshdeep Singh <147519691+harsh-pal-robotics@users.noreply.github.com>
(cherry picked from commit 2f05ca5)

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit da7b3d6)

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
#1261) (#1262)

* fix: mypy errors and flaky subscriber/publisher tests (#1258)

* chore: fix pre-existing Rolling/Lyrical CI failures

Two independent root causes block any PR that touches a Rolling/Lyrical job:

mypy (Ubuntu 25.10 'resolute' ships a stricter mypy that flags 5 latent
issues older versions silently accepted):
- subscribe.py: extend the type-ignore on the simplejson fallback to also
  cover no-redef. The chained 'import as encode_json' pattern legitimately
  rebinds the name; newer mypy now requires the suppression to say so.
- websocket_handler.py: narrow Node | None at _log_exception's use site
  with the same assert pattern already in open()/on_close(); annotate the
  bare protocol_parameters ClassVar as dict[str, Any]; coerce the optional
  request.remote_ip to a str at the ClientManager.{add,remove}_client
  boundary (Tornado types it as Any | None).

Flaky topic-existence tests: the previous helpers polled the rmw graph
cache via get_(publisher|subscriber)_names_and_types_by_node, which
requires a DDS-discovery round-trip even for self-queries. On 'resolute'
that round-trip routinely overran the 1s polling deadline, so different
tests flaked across different runs.

Switch to a deterministic implementation:
- is_topic_published / is_topic_subscribed in util/ros.py now read
  node.publishers / node.subscriptions (the local entity list). These are
  populated synchronously inside create_publisher / create_subscription
  and cleared inside destroy_publisher / destroy_subscription, so the
  result is correct as soon as the calling thread has the entity handle.
- Drop the assert_topic_(not_)subscribed polling helpers from the
  subscriber tests; call is_topic_subscribed directly.
- subscribers.py routes destroy_subscription through executor.create_task
  (#1194), so after manager.unsubscribe / MultiSubscriber.unregister the
  test thread still has to synchronize with the executor before asserting
  the entity is gone. Add wait_for_executor_idle, which enqueues a no-op
  task and waits for it; SingleThreadedExecutor processes tasks FIFO, so
  any destroy task enqueued earlier has completed when it returns.
- Drop the time.sleep(0.1) before is_topic_published in
  test_publisher_manager.test_register_infer_topictype — create_publisher
  is now reflected immediately.

Existing time.sleep(manager.unregister_timeout + 1.0) waits stay: those
are waiting for threading.Timer to fire and run destroy_publisher, not
for graph propagation.

* test: daemonize worker threads in capability tests

test_capabilities was hitting CTest's 60-second timeout on Rolling and Lyrical
even though pytest itself completes in ~14s and reports 46/46 passing. The
remaining ~46s is wasted in Python interpreter shutdown waiting on non-daemon
worker threads.

Each of the action / service capability tests dispatches the rosbridge worker
via Thread(target=self.send_goal.send_action_goal, ...).start() (analogous to
the production protocol.register_operation path). The worker calls
SendGoal.send_goal / call_service.call_service, which busy-wait on a result
that is only delivered when the executor spins the registered callback. When
tearDown calls executor.shutdown() before the worker's result callback has
fired, the busy-wait runs forever. Because the dispatch threads are
non-daemon, the Python interpreter blocks at shutdown trying to join them.

Mark these worker threads daemon=True so process exit is not gated on them.
The threads still complete normally on the happy path; daemon only changes
behaviour at interpreter shutdown, mirroring the pattern already used in
test_stress_service_clients.py.

(cherry picked from commit efc9f37)

# Conflicts:
#	rosbridge_library/test/capabilities/test_action_capabilities.py

* Fix conflicts

---------



(cherry picked from commit 65034c7)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Joshua Whitley <josh@electrifiedautonomy.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
* feat: Improve action unadvertising (backport #1248) (#1252)

* feat: Improve action unadvertising (#1248)

* Improve logging on send_action_goal fail

* Reject new goals after action was unadversited

* Abort action goals on shutdown

* Schedule destruction of action server after last goal finishes

* Expand unadvertise action test

(cherry picked from commit cfd0646)

# Conflicts:
#	rosbridge_library/src/rosbridge_library/capabilities/advertise_action.py

* Fix conflicts

* fix: set threads as daemon in action goal tests

* fix: add type ignore for coroutine in execute_callback

* fix: mypy error

---------

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit cb538db)

# Conflicts:
#	rosbridge_library/src/rosbridge_library/capabilities/advertise_action.py

* Fix conflicts

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
…s (backport #1260) (#1267)

* feat: Provide separate arguments for publish and subscribe topic globs (#1260)

* Add separate publish/subscribe topics glob

* Restore deleted lines

* Provide a different example for topics_pub_glob

* Formatting

* Append topics_glob  to topics_pub_glob and topics_sub_glob

* Fix empty glob matching

* Align rosapi and rosbridge_server glob parsing logic

* Update rosapi readme and refactor glob merging in rosbridge_websocket

* Update proxy

* Address Copilot comments

(cherry picked from commit 44365ff)

# Conflicts:
#	rosbridge_server/scripts/rosbridge_websocket.py

* Fix conflicts

---------



(cherry picked from commit a64a945)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: p7yong <pei7yong@gmail.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
#1255) (#1270)

* fix: Prevent client destruction race in services.call_service (backport #1255) (#1269)

* fix: prevent rclpy entity-lifecycle race in service and action capabilities (#1255)

Both `services.call_service` and `advertise_action`'s `AdvertisedActionHandler`
create rclpy entities (`rclpy.Client` and `rclpy.action.ActionServer`,
respectively) on the rosbridge node directly from a worker thread.  The same
node is concurrently spun by the rclpy executor, so the executor's wait-set
rebuild can race with the worker thread's entity registration / destruction
and either crash inside `_rclpy` (action servers SIGSEGV in
`rclpy/action/server.py:__init__`) or leave the executor holding a handle
whose underlying PyCapsule has been freed (services surface this later as
`TypeError: Object of type 'NoneType' is not an instance of 'capsule'`).

This is the service- and action-capability analogue of the IncomingQueue
race fixed in #1183: route the lifecycle calls through the executor via
`executor.create_task(...)` so they serialize with the executor's own work
instead of competing with it.

- Extract the executor-routing pattern into
  `rosbridge_library.internal.executor_helpers`, exposing `run_on_executor`
  (synchronous; returns the value, used when the caller needs the entity
  back) and `schedule_on_executor` (fire-and-forget, used for destructors).
  Both fall back to inline invocation when the node has no attached
  executor, preserving unit-test behaviour.
- Apply `run_on_executor` to client creation in `services.call_service` and
  ActionServer creation in `AdvertisedActionHandler.__init__`. The three
  `destroy_client` sites in `services.call_service` now use
  `schedule_on_executor`. ActionServer destruction was already routed
  through the executor in #1248.
- `ActionTester` in `test_actions.py` constructs its own ActionServer from
  the test thread while the fixture's executor is already spinning. Route
  that creation through `run_on_executor` for the same reason; without it
  the rclpy SIGSEGV reproduces on a workspace with up-to-date rclpy.

`test_stress_service_clients.py` exercises the service race window
(parallel callers, barrier-synchronized starts, rapid sequential cycles,
and interleaved waves of concurrent callers) and asserts the executor
remains healthy and responsive afterwards.

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit 06bf324)

# Conflicts:
#	rosbridge_library/src/rosbridge_library/capabilities/advertise_action.py
#	rosbridge_library/test/internal/actions/test_actions.py

* Fix conflicts

---------

Co-authored-by: Joshua Whitley <josh@electrifiedautonomy.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
(cherry picked from commit 7631e3f)

# Conflicts:
#	rosbridge_library/src/rosbridge_library/capabilities/advertise_action.py
#	rosbridge_library/test/internal/actions/test_actions.py

* Fix conflicts

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
* fix: Use Clock instead of deprecated ROSClock (#1273)

(cherry picked from commit 3703507)

# Conflicts:
#	rosbridge_library/src/rosbridge_library/internal/message_conversion.py

* Fix conflicts

---------

Co-authored-by: Błażej Sowa <bsowa123@gmail.com>
@bjsowa bjsowa added the jazzy label May 27, 2026
@bjsowa bjsowa closed this May 27, 2026
@bjsowa bjsowa deleted the release/2.7.0 branch May 28, 2026 07:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant