A new plugin for RC calibration - #1816
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces an RC calibration/monitoring plugin to ArduPilot Methodic Configurator, including a new RC data model, a tkinter frontend view, and supporting registration/schema wiring. It also factors out a shared calibration popup base class and refactors the existing compass calibration popup to use it.
Changes:
- Add RC calibration plugin wiring (plugin constant, plugin registration in
__main__.py, schema enum update, and data model factory hookup). - Introduce RC calibration UI (
frontend_tkinter_rc_calibration.py) and a quadcopter preview renderer stub (renderer_3d_quadcopter.py). - Add
CalibrationPopupBaseand refactor compass calibration popup to inherit from it.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
ardupilot_methodic_configurator/renderer_3d_quadcopter.py |
New renderer stub used by the RC calibration UI preview. |
ardupilot_methodic_configurator/plugin_constants.py |
Adds PLUGIN_RC_CALIBRATION. |
ardupilot_methodic_configurator/frontend_tkinter_rc_calibration.py |
New RC calibration plugin UI (embedded view + popup + dev window). |
ardupilot_methodic_configurator/frontend_tkinter_compass_calibration.py |
Refactors compass popup to use the new shared popup base. |
ardupilot_methodic_configurator/frontend_tkinter_calibration_popup_base.py |
New shared base class for calibration popups. |
ardupilot_methodic_configurator/data_model_rc_calibration.py |
New RC calibration data model using MAVLink RC telemetry and parameter writes. |
ardupilot_methodic_configurator/data_model_parameter_editor.py |
Wires RC calibration data model creation into plugin model factory. |
ardupilot_methodic_configurator/configuration_steps_schema.json |
Extends plugin name enum to include rc_calibration. |
ardupilot_methodic_configurator/__main__.py |
Registers the RC calibration plugin at startup. |
ARCHITECTURE_rc_calibration.md |
Adds architecture doc for the new plugin. |
| """ | ||
| 3D Quadcopter Renderer using PyOpenGL. | ||
|
|
||
| This module provides a class to render a simple 3D quadcopter model | ||
| based on roll, pitch, yaw, and throttle inputs. | ||
|
|
| Args: | ||
| roll: Roll angle in degrees. | ||
| pitch: Pitch angle in degrees. | ||
| yaw: Yaw angle in degrees. | ||
| throttle: Throttle value (0.0 to 1.0). | ||
|
|
| self.flight_mode: str = "No Data" | ||
| self.channels: list[dict] = [] |
| ttk.Label(mode_frame, text=_("Flight Mode:"), font=("TkDefaultFont", 11, "bold")).pack(side="left") | ||
| self.mode_label = ttk.Label(mode_frame, text="No Data", font=("TkDefaultFont", 11)) | ||
| self.mode_label.pack(side="left", padx=10) |
| # Update Flight Mode | ||
| self.flight_mode = telemetry.get("flight_mode", "No Data") | ||
| self.mode_label.configure(text=self.flight_mode) |
| if not self.is_connected(): | ||
| error_msg = _("Not connected to flight controller") | ||
| return False, error_msg |
| for ch_idx, min_val in self._channel_min.items(): | ||
| ch_num = ch_idx + 1 # convert to 1-based RC channel number | ||
| max_val = self._channel_max.get(ch_idx, _RC_CENTER_PWM * 2 - min_val) | ||
| trim_val = (min_val + max_val) // 2 | ||
| self.flight_controller.set_param(f"RC{ch_num}_MIN", float(min_val)) | ||
| self.flight_controller.set_param(f"RC{ch_num}_MAX", float(max_val)) | ||
| self.flight_controller.set_param(f"RC{ch_num}_TRIM", float(trim_val)) |
| try: | ||
| rc_msg = master.recv_match( # pyright: ignore[reportAttributeAccessIssue] | ||
| type="RC_CHANNELS", blocking=False | ||
| ) |
| class RCCalibrationDataModel: | ||
| """Data model for RC calibration, backed by MAVLink RC_CHANNELS telemetry.""" | ||
|
|
||
| def __init__(self, flight_controller: FlightController) -> None: | ||
| self.flight_controller = flight_controller | ||
| self._is_calibrating = False | ||
| self._channel_min: dict[int, int] = {} # 0-based channel index → observed minimum PWM | ||
| self._channel_max: dict[int, int] = {} # 0-based channel index → observed maximum PWM |
| > **Note:** The data model is currently a stub that returns dummy data. | ||
| > MAVLink integration (`RC_CHANNELS` / `HEARTBEAT` messages) is planned for a future commit. |
☂️ Code Coverage
Overall Coverage
New Files
Modified Files
|
Test Results 4 files ± 0 4 suites ±0 45m 29s ⏱️ - 4m 7s For more details on these failures, see this check. Results for commit 44aed60. ± Comparison against base commit a4ed796. ♻️ This comment has been updated with latest results. |
theraihanrakibb
left a comment
There was a problem hiding this comment.
Solid foundation for the RC calibration plugin — thanks for the thorough architecture doc and the clean Model-View split. A few things worth addressing:
1. Doc/code contradiction (please fix): ARCHITECTURE_rc_calibration.md states several times "The data model is currently a stub that returns dummy data," but data_model_rc_calibration.py's get_rc_telemetry() actually reads real MAVLink RC_CHANNELS/HEARTBEAT via recv_match. Update the doc to match the code (or vice-versa).
2. grab_set() makes the live monitor modal (UX bug): CalibrationPopupBase.__init__ calls grab_set(), which captures all keyboard/mouse focus. That's correct for the compass calibration popup, but RCCalibrationPopup is meant to be a floating live monitor the user watches while using the rest of AMC. With grab_set() they can't interact with the main window. Override/disable grab_set in the RC subclass (or make the base non-modal and let compass opt in).
3. finish_calibration() trim heuristic: when a channel recorded a min but no max, max is synthesized as 3000 - min (assumes center 1500). Reasonable fallback, but add a comment so it isn't mistaken for a measured value later.
4. WIP vs CI: the status table shows many untested/unimplemented items, and the repo checklist wants BDD pytest — none are added for the new plugin. Either add a smoke test or open this as a draft PR so main-branch gating isn't a surprise.
5. Verify wiring: register_rc_calibration_plugin() and create_plugin_data_model() are wired, but I didn't see RCCalibrationView instantiated in plugin_factory/editor — confirm the embedded view actually mounts.
Nice refactor extracting CalibrationPopupBase (the compass popup drops ~80 duplicated lines).
Software test suite for
|
|
@amilcarlucas, should we introduce the 3d model here? We can use the same model here to check the rc inputs in the 3d popup itself(as discussed), we can have the input bars on the sides along with the drone in the centre and then can be scrolled for additional options? Also is an invert control option good or should it be done on the TX only? |
volkkov
left a comment
There was a problem hiding this comment.
Good improvement overall. One edge case: empty string vs null aren't treated the same downstream — might need a normalization step.
Signed-off-by: Dr.-Ing. Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
Adds 25 hardware-free unit tests for data_model_rc_calibration.py using a mocked FlightController (MagicMock), following the BDD Given-When-Then style already used in test_data_model_accelerometer_calibration.py. Coverage of data_model_rc_calibration.py: 99% (all statements, 25/26 branches). Covered behaviours: - connection state (connected / disconnected) - start/cancel calibration and stale-state clearing - finish_calibration: RCn_MIN/MAX/TRIM writes, midpoint trim, symmetric max fallback, 0-based to 1-based channel mapping, state cleanup - RC_CHANNELS telemetry: axis mapping, invalid-PWM sentinel handling, chancount bound, swallowed recv_match exceptions, HEARTBEAT flight_mode - min/max tracking active only while calibrating No hardware required: all MAVLink I/O is mocked. Signed-off-by: Billard <82095453+iacker@users.noreply.github.com>
Removes the duplicated window-centering block (R0801) shared between CalibrationPopupBase and CompassCalibrationInstructionsPopup. Both now call a single module-level center_over_parent() helper. Behavior unchanged; fixes the pylint 3.14 duplicate-code failure.
de962ef to
2ae479a
Compare
for more information, see https://pre-commit.ci
Description
RC controller calibration plugin
WIP needs a lot more testing and development
implements #1754
Checklist
git commit --signoff)Testing
Describe how you tested these changes: