Skip to content

Conversation

@srmainwaring
Copy link
Contributor

@srmainwaring srmainwaring commented Dec 8, 2025

🎉 New feature

DRAFT: (debug output to be removed etc. currently left to aid discussion of proposed approach) .

Allow systems to access the NetworkManagerSecondary namespace in distributed simulations so that model plugins associated with a performer can have the update limited to the secondary assigned to that performer.

There are also some bug fixes to ensure that performer parent model is available before the secondary stepping starts, and that models are only unloaded from secondaries that are not assigned.

Summary

The main issue is that presently a model system plugin will be updated on all running NetworkManager instances. This includes the primary, and all secondaries. There are examples where we would like a model system plugin to be only updated by the secondary responsible for updating the performer associated with the model owning the plugin. This is the case if the model is publishing data, or needs to remain in lock-step with some other service (such as a socket or other bridging application in the case of links to flight controller SITL backends such as those available for PX4 or ArduPilot).

This can be done by adding the secondary namespace to UpdateInfo object which is passed to all Systems when they are updated in the SimulationRunner. The system can elect to compare the namespace with the performer affinity, and decide whether or not to update. An example plugin (LevelDebug) is provided.

Test it

Terminal 1

gz sim -v4 -s -r --levels --network-role primary --network-secondaries 3 levels.sdf

Terminals 2,3,4

gz sim -v4 -s -r --levels --network-role secondary levels.sdf

Terminal 5

gz sim -v4 -g

Terminal 6

gz topic -t "/model/vehicle_red/cmd_vel" -m gz.msgs.Twist -p "linear: {x: 4.0}"

Example output for a couple of iterations:

Terminal 1: Primary

(2025-12-08 15:52:23.247) [info] [LevelDebug.cc:85] System is not a NetworkManagerSecondary
(2025-12-08 15:52:23.248) [debug] [NetworkManagerPrimary.cc:269] PopulateAffinities...
(2025-12-08 15:52:23.248) [debug] [NetworkManagerPrimary.cc:271] Performers:
(2025-12-08 15:52:23.248) [debug] [NetworkManagerPrimary.cc:283]   Performer: [2], Parent: [15]
(2025-12-08 15:52:23.248) [debug] [NetworkManagerPrimary.cc:288] Levels:
(2025-12-08 15:52:23.979) [debug] [NetworkManagerPrimary.cc:294]     Performer: [2]
(2025-12-08 15:52:23.979) [debug] [NetworkManagerPrimary.cc:291]   Level: [5]
(2025-12-08 15:52:23.979) [debug] [NetworkManagerPrimary.cc:294]     Performer: [2]
(2025-12-08 15:52:23.979) [debug] [NetworkManagerPrimary.cc:298] Secondary:
(2025-12-08 15:52:23.979) [debug] [NetworkManagerPrimary.cc:301]   Performer: [2], Secondary: [44e7c996]
(2025-12-08 15:52:23.981) [info] [LevelDebug.cc:85] System is not a NetworkManagerSecondary
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:269] PopulateAffinities...
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:271] Performers:
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:283]   Performer: [2], Parent: [15]
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:288] Levels:
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:291]   Level: [4]
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:294]     Performer: [2]
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:291]   Level: [5]
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:294]     Performer: [2]
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:298] Secondary:
(2025-12-08 15:52:23.982) [debug] [NetworkManagerPrimary.cc:301]   Performer: [2], Secondary: [44e7c996]

Terminal 2: Secondary 1

(2025-12-08 15:52:23.977) [info] [LevelDebug.cc:128] Model: [vehicle_red] is not updated by Secondary: [c3acbdae]
(2025-12-08 15:52:23.977) [debug] [NetworkManagerSecondary.cc:202] Secondary: performer: size: 0
(2025-12-08 15:52:23.979) [debug] [NetworkManagerSecondary.cc:115] NetworkManagerSecondary::OnStep [c3acbdae]
(2025-12-08 15:52:23.979) [debug] [SimulationRunner.cc:959] SimulationRunner: stepping secondary: c3acbdae
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:128] Model: [vehicle_red] is not updated by Secondary: [c3acbdae]
(2025-12-08 15:52:23.979) [debug] [NetworkManagerSecondary.cc:202] Secondary: performer: size: 0
(2025-12-08 15:52:23.982) [debug] [NetworkManagerSecondary.cc:115] NetworkManagerSecondary::OnStep [c3acbdae]
(2025-12-08 15:52:23.982) [debug] [SimulationRunner.cc:959] SimulationRunner: stepping secondary: c3acbdae

Terminal 3: Secondary 2

(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:136] Name: [perf_vehicle_red] 
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:141] Ref: [vehicle_red] 
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:146] Affinity: [44e7c996] 
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:151] All Models:
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:157] [9] stage
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:157] [15] vehicle_red
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:157] [53] tile_8
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:157] [75] tile_13
(2025-12-08 15:52:23.979) [debug] [NetworkManagerSecondary.cc:202] Secondary: performer: size: 1
(2025-12-08 15:52:23.979) [debug] [NetworkManagerSecondary.cc:223] Secondary: performer [2], parent: [15]
(2025-12-08 15:52:23.982) [debug] [NetworkManagerSecondary.cc:115] NetworkManagerSecondary::OnStep [44e7c996]
(2025-12-08 15:52:23.982) [debug] [SimulationRunner.cc:959] SimulationRunner: stepping secondary: 44e7c996
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:136] Name: [perf_vehicle_red] 
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:141] Ref: [vehicle_red] 
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:146] Affinity: [44e7c996] 
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:151] All Models:
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:157] [9] stage
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:157] [15] vehicle_red
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:157] [53] tile_8
(2025-12-08 15:52:23.982) [info] [LevelDebug.cc:157] [75] tile_13
(2025-12-08 15:52:23.982) [debug] [NetworkManagerSecondary.cc:202] Secondary: performer: size: 1
(2025-12-08 15:52:23.982) [debug] [NetworkManagerSecondary.cc:223] Secondary: performer [2], parent: [15]

Terminal 4: Secondary 3

(2025-12-08 15:52:23.977) [info] [LevelDebug.cc:128] Model: [vehicle_red] is not updated by Secondary: [b5ec493c]
(2025-12-08 15:52:23.977) [debug] [NetworkManagerSecondary.cc:202] Secondary: performer: size: 0
(2025-12-08 15:52:23.979) [debug] [NetworkManagerSecondary.cc:115] NetworkManagerSecondary::OnStep [b5ec493c]
(2025-12-08 15:52:23.979) [debug] [SimulationRunner.cc:959] SimulationRunner: stepping secondary: b5ec493c
(2025-12-08 15:52:23.979) [info] [LevelDebug.cc:128] Model: [vehicle_red] is not updated by Secondary: [b5ec493c]
(2025-12-08 15:52:23.979) [debug] [NetworkManagerSecondary.cc:202] Secondary: performer: size: 0
(2025-12-08 15:52:23.982) [debug] [NetworkManagerSecondary.cc:115] NetworkManagerSecondary::OnStep [b5ec493c]
(2025-12-08 15:52:23.982) [debug] [SimulationRunner.cc:959] SimulationRunner: stepping secondary: b5ec493c

Here we can see that only secondary 2 (44e7c996) has detailed output from LevelDebug, as this is the secondary associated with vehicle_red. In the GUI the rover will advance through the levels, and they will load and unload as expected.

Additional notes

  • The timeout increases are so that the primary or secondary may be stepped through in a debugger. It could be useful to have these exposed as parameters or settings.
  • Most of the debug messages can be removed.
  • The level example has been simplified to a single vehicle to ease debugging. The full example should also work.
  • NetworkManager: fix entity creation in network secondary #3160 does not address some bugs in the network secondary. This PR moves the entity creation to the SimulationRunner::Run method so the parent models are available before OnStep is called. The original logic to remove models from performers that are unassigned will remove parent models from secondaries that receive more than one performer affinity for the same performer which may result in a secondary with affinity not having the performer's model in the ECM.

Outstanding Tasks

Affinity assignment

  • There is an issue with multiple performers - needs fixing

  • The problem is related the performer affinity assignment. These are set in the NetworkManagerPrimary, and interpreted in the NetworkManagerSecondary.

  • The performer affinity is passed from the primary to the secondary in the SimulationStep message.

  • In the current implementation the entries in the list of performer affinities passed to the secondary are not unique, there may be repeated entries for a given entity to secondary assignment and an entity may be assigned to more than one secondary.

  • The primary assumes that the last assigned secondary for an entity is used (this is the behaviour coded in NetworkManagerPrimary::SetAffinity).

  • Suggest that the NetworkManagerPrimary ensures that the list of performer affinities contains a single entry for each performer entity. This will simplify the affinity assignment logic in the secondary.

Checklist

  • Signed all commits for DCO
  • Added tests
  • Added example and/or tutorial
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers
  • Was GenAI used to generate this PR? If so, make sure to add "Generated-by" to your commits. (See this policy for more info.)

Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining Signed-off-by and Generated-by messages.

@srmainwaring srmainwaring requested a review from arjo129 as a code owner December 8, 2025 16:23
@srmainwaring srmainwaring marked this pull request as draft December 8, 2025 16:23
@github-actions github-actions bot added the 🪵 jetty Gazebo Jetty label Dec 8, 2025
@srmainwaring srmainwaring force-pushed the prs/10/distributed-levels branch from b5d0571 to faa5a7c Compare December 8, 2025 18:22
- Move CreateEntities to Run, must be available before Step.
- Add debug output.

Signed-off-by: Rhys Mainwaring <[email protected]>
@srmainwaring srmainwaring force-pushed the prs/10/distributed-levels branch 2 times, most recently from dfc726c to 17a2693 Compare December 8, 2025 18:38
- Add error message if secondary fails to remove parent entity.
- Only remove models if performer is assigned to another secondary.
- Set the secondary namespace on the update info.
- Add debug output.

Signed-off-by: Rhys Mainwaring <[email protected]>
- Use update info and performer affinity to control update.
- Display model properties.

Signed-off-by: Rhys Mainwaring <[email protected]>
- Simplify levels example.
- Add LevelDebug system to red vehicle.
- Restore levels for red vehicle.

Signed-off-by: Rhys Mainwaring <[email protected]>
@srmainwaring srmainwaring force-pushed the prs/10/distributed-levels branch from 17a2693 to 37148a0 Compare December 8, 2025 18:51
- Only check a model is a performer once in configure.

Signed-off-by: Rhys Mainwaring <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🪵 jetty Gazebo Jetty

Projects

Status: Inbox

Development

Successfully merging this pull request may close these issues.

1 participant