Skip to content

Allow choosing the SITL frame in the frontend#3950

Open
Williangalvani wants to merge 2 commits into
bluerobotics:masterfrom
Williangalvani:pick_sitl_frame
Open

Allow choosing the SITL frame in the frontend#3950
Williangalvani wants to merge 2 commits into
bluerobotics:masterfrom
Williangalvani:pick_sitl_frame

Conversation

@Williangalvani

@Williangalvani Williangalvani commented Jun 12, 2026

Copy link
Copy Markdown
Member
Screenshot 2026-06-12 at 16 25 35

Summary by Sourcery

Add frontend and API support for configuring and reading the current SITL frame type for the autopilot simulator.

New Features:

  • Expose the current SITL frame via a new backend GET endpoint returning the SITLFrame value.
  • Introduce a SITL configuration panel in the frontend autopilot view to select and change the SITL frame when using a SITL board.
  • Store the selected SITL frame in the frontend Vuex store and keep it in sync with the backend via a polling task.

Enhancements:

  • Mirror the backend SITLFrame enum in the frontend types to provide typed options for SITL frame selection.

The POST endpoint already existed; add the matching GET so the
frontend can read the currently configured SITL frame.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Williangalvani Williangalvani marked this pull request as ready for review June 15, 2026 15:57

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In SitlConfiguration.vue, consider calling fetchSitlFrame() once on mounted() in addition to wiring it into OneMoreTime, so the initial selected frame reflects the backend state immediately rather than only after the first scheduled fetch.
  • The SITLFrame enum values are shown directly as user-facing labels (e.g. +, x, lowercased names); adding a mapping to more descriptive and consistently formatted labels in sitl_frame_options would improve clarity in the dropdown.
  • The new /sitl_frame GET endpoint is typed to always return a SITLFrame, but the code returns autopilot.current_sitl_frame; ensure this is never None or explicitly handle the None case to avoid response model mismatches.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `SitlConfiguration.vue`, consider calling `fetchSitlFrame()` once on `mounted()` in addition to wiring it into `OneMoreTime`, so the initial selected frame reflects the backend state immediately rather than only after the first scheduled fetch.
- The `SITLFrame` enum values are shown directly as user-facing labels (e.g. `+`, `x`, lowercased names); adding a mapping to more descriptive and consistently formatted labels in `sitl_frame_options` would improve clarity in the dropdown.
- The new `/sitl_frame` GET endpoint is typed to always return a `SITLFrame`, but the code returns `autopilot.current_sitl_frame`; ensure this is never `None` or explicitly handle the `None` case to avoid response model mismatches.

## Individual Comments

### Comment 1
<location path="core/frontend/src/components/autopilot/SitlConfiguration.vue" line_range="58-60" />
<code_context>
+    }
+  },
+  computed: {
+    sitl_frame_options(): {value: SITLFrame, text: string}[] {
+      return Object.values(SITLFrame)
+        .filter((frame) => frame !== SITLFrame.UNDEFINED)
+        .map((frame) => ({ value: frame, text: frame }))
+    },
</code_context>
<issue_to_address>
**issue (bug_risk):** Handling of SITLFrame.UNDEFINED can desync the selected value and the available items.

Because `SITLFrame.UNDEFINED` is filtered out here, `autopilot.sitl_frame` may still be `UNDEFINED` while the corresponding `<v-select>` has no matching `item`, causing an empty or inconsistent selection. Either normalize `UNDEFINED` to `null` in the store/setter, or include `UNDEFINED` in the options (e.g. as a disabled/placeholder entry).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread core/frontend/src/components/autopilot/SitlConfiguration.vue
@github-actions

Copy link
Copy Markdown

Automated PR Review

0. Summary

  • Verdict: MINOR SUGGESTIONS ✏️

Adds a "SITL configuration" expansion panel to the Autopilot view that lets the user pick the SITL frame from a v-select. The frontend exposes a new fetchSitlFrame updater, a sitl_frame field + mutation on the autopilot store, a mirrored TS SITLFrame enum, and a new SitlConfiguration.vue component shown when the current board is SITL. The backend adds a matching GET /sitl_frame route that returns autopilot.current_sitl_frame. Setting a new frame POSTs to the existing endpoint and then calls restart() so SITL re-launches with the new frame.

1. Correctness & Implementation Bugs

  • 1.1 [minor] core/frontend/src/components/autopilot/SitlConfiguration.vue:51-62changeSitlFrame sets this.setting = false on both the success path and the early-return error path. A try { ... } finally { this.setting = false } around the POST would prevent the flag from being left as true if a future edit adds an early return or throws between the two assignments. Small robustness win.
  • 1.2 [minor] core/frontend/src/components/autopilot/SitlConfiguration.vue:38-46 — the optimistic autopilot.setSitlFrame(frame) runs after the POST succeeds but before restart() is awaited. If restart() fails, the local store reflects the new frame while SITL is still running the old one. The 5 s fetchSitlFrame poll will reconcile this within a tick, but consider letting the next fetch be the source of truth instead of writing the store optimistically here.

5. UI / UX

  • 5.1 [minor] core/frontend/src/components/autopilot/SitlConfiguration.vue:7-13 — the v-select uses :value + @change instead of v-model. That is fine when the value lives in a Vuex store, but the rest of this PR's snackbar uses v-model, so the mixed style is mildly inconsistent. Acceptable as-is; mentioned only for consistency with the surrounding components.
  • 5.2 [nit] core/frontend/src/components/autopilot/SitlConfiguration.vue:14-26 — the user-facing label "SITL frame" and the success message "SITL frame set, autopilot restarted" are fine, but consider sorting/grouping sitl_frame_options (e.g. copter / plane / rover / boat / sim backends) since the raw enum order is hard to scan with ~50 entries.

6. Code Quality & Style

  • 6.1 [minor] core/frontend/src/types/autopilot.ts:30-86 — the TS SITLFrame enum is a hand-maintained mirror of the Python SITLFrame in core/services/ardupilot_manager/typedefs.py. The header comment acknowledges this, which is good, but consider adding a brief test or runtime sanity check that fetches the backend value and warns if it is not a member of the TS enum — silent drift between the two lists is the realistic failure mode here.
  • 6.2 [nit] core/services/ardupilot_manager/api/v1/routers/index.py:139-143 — the new get_sitl_frame does not guard on autopilot.current_board, which is fine because current_sitl_frame always returns a value loaded from config, but it is inconsistent with the surrounding get_firmware_info / get_vehicle_type style that returns 503 when no board is running. Either is defensible; flagging only because the file is otherwise uniform.

8. Documentation

  • 8.1 [nit] core/frontend/src/components/autopilot/SitlConfiguration.vue:67-69 — the inline comment // restart() pushes its own error notification on failure. is good context. The sibling // The new frame is only picked up at SITL launch, so restart so it takes effect. is also valuable — keep both. No action; mentioned as positive examples for the rest of the review tone.

Generated by PR Review Bot. This is advisory, a human reviewer must still approve.

Add a dedicated expansion panel (visible only when SITL is the running
board) with a frame-type dropdown. Selecting a frame POSTs to
/sitl_frame and automatically restarts the autopilot so the new frame
takes effect (matching set_board behavior), with a loading spinner and
success snackbar for feedback.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +117 to +130
export async function fetchSitlFrame(): Promise<void> {
try {
const response: AxiosResponse = await back_axios({
method: 'get',
url: `${autopilot.API_URL}/sitl_frame`,
timeout: 10000,
})
autopilot.setSitlFrame(response.data as SITLFrame)
} catch (error) {
autopilot.setSitlFrame(null)
notifier.pushBackError('AUTOPILOT_SITL_FRAME_FETCH_FAIL', error)
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Any reason why not using the return back_axios({/*...*/}).then(/*...*/).catch(/*...*/) pattern used in the similar functions below?

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.

2 participants