task_generator_gui¶
RViz2 plugins for the Arena-Rosnav task generator. Ships:
TaskGeneratorPanel(rviz_common::Panel): episode management, task-mode selection, world/robot configuration, live episode history playlist.SpawnPedestrianTool(rviz_common::Tool): toolbar tool that click+drags a pose and callsruntime/spawn_dynamicto spawn a dynamic obstacle (pedestrian).
The auditory panel and the spawn microphone and spawn sound tools live in the
arena_auditory_viz package of the auditory feature, see the
arena_auditory README. The
acoustics:=arena backend declares them in the viz manifest's plugins, and
rviz_config.py adds every declared panel and tool to the generated config.
Service contract¶
All service paths are relative to the task_generator node namespace (default /task_generator_node, configurable via the RViz panel Target config key).
| Path | Type | Usage |
|---|---|---|
lifecycle/reset_episode |
task_generator_msgs::srv::ResetEpisode |
Next button (after queue flush) |
lifecycle/pause |
std_srvs::srv::Empty |
Pause button |
lifecycle/unpause |
std_srvs::srv::Empty |
Unpause button |
lifecycle/wait_for_world |
std_srvs::srv::Empty |
Called after world param change |
query/worlds |
task_generator_msgs::srv::QueryWorlds |
Populate world combobox |
query/robots |
task_generator_msgs::srv::QueryRobots |
Populate robot combobox |
query/environments |
task_generator_msgs::srv::QueryEnvironments |
Populate environment list |
query/parametrizeds |
task_generator_msgs::srv::QueryParametrizeds |
Populate parametrized list |
query/static_obstacles |
task_generator_msgs::srv::QueryStaticObstacles |
Populate static model list |
query/dynamic_obstacles |
task_generator_msgs::srv::QueryDynamicObstacles |
Populate dynamic model list |
query/scenarios |
task_generator_msgs::srv::QueryScenarios |
Populate scenario list for current world |
query/task_modes |
task_generator_msgs::srv::QueryTaskModes |
Populate mode comboboxes (obstacles, robots, modules) |
config/queue_episode |
task_generator_msgs::srv::QueueEpisode |
Queue / Next buttons (modes, world, robots, per-mode params staged for next reset) |
runtime/spawn_dynamic |
task_generator_msgs::srv::SpawnDynamic |
Spawn pedestrian tool (click+drag pose) |
runtime/spawn_robot |
task_generator_msgs::srv::SpawnRobot |
Spawn Robot button (mid-episode spawn) |
Latched topics consumed¶
| Topic | Type | Usage |
|---|---|---|
state/episode |
task_generator_msgs::msg::EpisodeRecord |
Current episode. Subscribers dedup by episode_id (same id may be republished as outcome resolves) and feed the panel's local history_buffer_ (ring of 50, oldest-first) plus the current/bold row. |
state/queue |
task_generator_msgs::msg::EpisodeRecord |
Queued (next) episode. On arrival the panel populates widgets via populateFromQueue (signal-blocked) and clears dirty flags. Drives the "Next:" preview row when it differs from current. |
state/paused |
std_msgs::msg::Bool |
Drives the pause button label authoritatively. The pause button is fire-and-forget; UI reflects the published state, not the service-call return. |
state/resetting |
std_msgs::msg::Bool |
True while _run_reset_cycle holds the reset lock. The world generator panel disables "+Deploy" while it is set. |
/parameter_events |
rcl_interfaces::msg::ParameterEvent |
Filters on node == task_generator_node; if any changed/new/deleted parameter starts with task.<active_mode>., rebuilds the matching family's param tree on the Qt thread. |
SpawnPedestrianTool¶
Subclass of rviz_default_plugins::tools::PoseTool. Click+drag in the 3D view to set position and yaw; the tool then calls <Target>/runtime/spawn_dynamic with use_pose=true, the clicked PoseStamped (in the rviz Fixed Frame), and the Model string. Both Target and Model are exposed as Tool Properties; Model defaults to arenian. Shortcut key: p.
Discard / Queue / Next buttons¶
The button row is Pause | Discard | Queue | Next. Discard and Queue are enabled only when widget values differ from the latched state/queue snapshot (any of the per-family dirty flags set).
- Discard: re-populates widgets from
last_queued_episode_viapopulateFromQueue(signal-blocked) and clears dirty. No service call. - Queue: builds a
QueueEpisode::Requestfrom current widget state and sendsconfig/queue_episode. Does not trigger a reset. The latchedstate/queuetopic round-trip then refreshes widgets and clears dirty. - Next: if dirty, calls Queue first; once the response arrives, calls
lifecycle/reset_episode(worldleft empty so the server resolves from queued overrides). If aRunEpisodegoal is in flight, the server resolves it withResult.SKIPPED(reason="reset").
Pause / Unpause button¶
A single Pause/Unpause button. The label is driven by the latched state/paused topic, not by the service-call return. Clicking is fire-and-forget: calls lifecycle/pause or lifecycle/unpause based on the current state, and the label flips when the server publishes the new value. This keeps the UI in sync even if pause/unpause is triggered externally.
Playlist (episode history)¶
The panel maintains a local history_buffer_ (std::deque<EpisodeRecord>, max 50) deduped by episode_id. On every state/episode arrival the record is upserted into the buffer and the table is rebuilt:
- Each finalized record is shown oldest-first:
episode_id,world,seed,outcome_state(QUEUED/RUNNING/SUCCESS/FAILED/SKIPPED/FATAL),outcome_info. Theoutcome_infocell is live: tasks may republish it mid-episode (e.g."timeout after 120s","50% complete") viaTask.set_info(text)and the panel will refresh on the next latched message. - The current episode (
last_current_episode_) appears as the last (bottom) row in bold. - A "Next:" preview row is appended (italic) when
last_queued_episode_differs meaningfully from current (world, modes, robots, or any param).
History is held only in the panel.
World combobox staging¶
The world combobox stages a world value into the queued slot via QueueEpisode. World is bound to the episode and changes at the next reset boundary; nothing happens to the live world until Queue or Next fires.
Task-mode tabs¶
Two tabs (Obstacles, Robots) hold the only TM controls:
- Obstacles tab has a task-mode combobox (
Environment/Parametrized/Random/Scenario/Prompt) and per-mode parameter widgets. Combobox change markstm_obstacles_dirty_, rebuilds the param tree, and updates Discard/Queue enabled state. No service call until Queue / Next fires. - Robots tab has a task-mode combobox (
Explore/Guided/Random/Scenario). Combobox change markstm_robots_dirty_, rebuilds the param tree, and updates Discard/Queue enabled state. No service call until Queue / Next fires.
Server validates the string values against the Python enum on the eventual QueueEpisode call. On rejection, a WARN is logged with the server's error_msg.
Per-mode parameter staging¶
All edits are batched locally (no live push). On Queue / Next, buildQueueEpisodeRequest packages current widget state into a single config/queue_episode request: tm_robots, tm_obstacles (lowercased), world, robots = [selected_robot_model], plus per-mode obstacles_params and robots_params (each a rcl_interfaces/Parameter with a leaf-keyed name relative to the mode, e.g. scenario.file, static.n). QueueEpisode is per-field merge with action = MERGE: empty scalar fields preserve previously-queued overrides; robots unions with prior queued set (dedup, insertion order). The server stages everything and applies at the next lifecycle/reset_episode boundary.
Mode combobox population¶
The GUI uses query/task_modes to populate the Obstacles and Robots comboboxes at startup. The comboboxes stay in sync automatically when new task modes are registered on the server side. Since walk_schemas declares all task.<mode>.* params at node startup, the param tree can be rebuilt against any mode without first switching the active mode.
Cold start¶
load() returns immediately after building the empty UI shell. Every discovery call is async:
query/robots,query/worlds,query/task_modesare gated through awhenReadypolling helper that waits for service readiness off the rviz executor, then firesasync_send_requestwith a response callback. Each callback marshals back to the Qt thread viaQMetaObject::invokeMethod(..., Qt::QueuedConnection)and usesQSignalBlockerwhile populating combos to suppress spuriouscurrentTextChangedsignals.- The first
state/queuearrival drivespopulateFromQueue, which seeds the task-mode combos, world combobox, and robot combobox (signal-blocked), then triggers the initialrebuildParamTreefor both families and writes any param values from the queued record into the widgets viasetWidgetValueFromParam.loading_from_queue_is set during population so widget signals don't bump dirty flags. rebuildParamTreecarries a per-family generation counter through a sharedRebuildStatestruct; stale callbacks (older generation) drop their results. The chain islist_parameters→ paralleldescribe_parameters+get_parameters→ Qt-thread widget construction → catalog fan-out. Catalog combos render immediately, seeded with the current value(s) plus any ids memoized from earlier fetches, and are refilled in place (signal-blocked, selection preserved) as each catalog arrives.