Skip to content

Commit cb243f3

Browse files
committed
feat(phases): show configuration progress bar
divided in different phases optional phases are marked fully resizable with the window Optional, only active if phases data exists in the .json file
1 parent 5dc303b commit cb243f3

7 files changed

+535
-4
lines changed

ardupilot_methodic_configurator/backend_filesystem_configuration_steps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class ConfigurationSteps:
4141
def __init__(self, _vehicle_dir: str, vehicle_type: str) -> None:
4242
self.configuration_steps_filename = "configuration_steps_" + vehicle_type + ".json"
4343
self.configuration_steps: dict[str, dict] = {}
44+
self.configuration_phases: dict[str, dict] = {}
4445
self.forced_parameters: dict[str, dict] = {}
4546
self.derived_parameters: dict[str, dict] = {}
4647
self.log_loaded_file = False
@@ -96,6 +97,11 @@ def re_init(self, vehicle_dir: str, vehicle_type: str) -> None: # pylint: disab
9697
self.__validate_parameters_in_configuration_steps(filename, file_info, "derived")
9798
else:
9899
logging_warning(_("No configuration steps documentation and no forced and derived parameters will be available."))
100+
101+
if file_found and "phases" in json_content:
102+
self.configuration_phases = json_content["phases"]
103+
else:
104+
logging_warning(_("No configuration phases documentation will be available."))
99105
self.log_loaded_file = True
100106

101107
def __validate_parameters_in_configuration_steps(self, filename: str, file_info: dict, parameter_type: str) -> None:

ardupilot_methodic_configurator/configuration_steps_ArduCopter.json

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,5 +826,65 @@
826826
"auto_changed_by": "",
827827
"old_filenames": ["45_everyday_use.param", "47_everyday_use.param", "50_everyday_use.param"]
828828
}
829+
},
830+
"phases": {
831+
"IMU temperature calibration": {
832+
"description": "Calibrate the IMU sensors for at different temperatures",
833+
"optional": true,
834+
"start": 2
835+
},
836+
"Assemble all components except the propellers": {
837+
"description": "Assemble all components except the propellers"
838+
},
839+
"Basic mandatory configuration": {
840+
"description": "Set up the basic parameters for the vehicle",
841+
"start": 4
842+
},
843+
"Assemble the propellers and perform the first flight": {
844+
"description": "Assemble the propellers and perform the first flight"
845+
},
846+
"Minimalistic mandatory tuning": {
847+
"description": "Minimalistic mandatory tuning using test flight data",
848+
"start": 19
849+
},
850+
"Standard tuning": {
851+
"description": "Improve tuning with more test flight data",
852+
"optional": true,
853+
"start": 24
854+
},
855+
"Improve altitude control": {
856+
"description": "Improve altitude under windy conditions",
857+
"optional": true,
858+
"start": 40
859+
},
860+
"Analytical PID optimization": {
861+
"description": "System identification and analytical PID optimization",
862+
"optional": true,
863+
"start": 42
864+
},
865+
"Position controller tuning": {
866+
"description": "Position controller tuning",
867+
"optional": true,
868+
"start": 47
869+
},
870+
"Guided operation": {
871+
"description": "Guided operation",
872+
"optional": true,
873+
"start": 48
874+
},
875+
"Precision landing": {
876+
"description": "Precision landing",
877+
"optional": true,
878+
"start": 49
879+
},
880+
"Optical flow calibration": {
881+
"description": "Optical flow sensor calibration",
882+
"optional": true,
883+
"start": 50
884+
},
885+
"Everyday use": {
886+
"description": "Everyday use",
887+
"start": 53
888+
}
829889
}
830890
}

ardupilot_methodic_configurator/configuration_steps_schema.json

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"type": "object",
3-
"required": ["steps"],
3+
"required": ["steps", "phases"],
44
"properties": {
55
"steps": {
66
"type": "object",
@@ -149,6 +149,31 @@
149149
}
150150
}
151151
}
152+
},
153+
"phases": {
154+
"type": "object",
155+
"patternProperties": {
156+
"^.*$": {
157+
"type": "object",
158+
"required": ["description"],
159+
"properties": {
160+
"description": {
161+
"type": "string",
162+
"description": "Description of the phase"
163+
},
164+
"optional": {
165+
"type": "boolean",
166+
"description": "Whether this phase is optional"
167+
},
168+
"start": {
169+
"type": "integer",
170+
"minimum": 1,
171+
"description": "Starting step number of this phase"
172+
}
173+
}
174+
}
175+
},
176+
"description": "Phases of the configuration process"
152177
}
153178
},
154179
"additionalProperties": false

ardupilot_methodic_configurator/frontend_tkinter_parameter_editor.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from ardupilot_methodic_configurator.frontend_tkinter_directory_selection import VehicleDirectorySelectionWidgets
4545
from ardupilot_methodic_configurator.frontend_tkinter_parameter_editor_documentation_frame import DocumentationFrame
4646
from ardupilot_methodic_configurator.frontend_tkinter_parameter_editor_table import ParameterEditorTable
47+
from ardupilot_methodic_configurator.frontend_tkinter_stage_progress import StageProgressBar
4748
from ardupilot_methodic_configurator.tempcal_imu import IMUfit
4849

4950

@@ -153,7 +154,7 @@ def __init__(self, current_file: str, flight_controller: FlightController, local
153154
self.root.title(
154155
_("Amilcar Lucas's - ArduPilot methodic configurator ") + __version__ + _(" - Parameter file editor and uploader")
155156
)
156-
self.root.geometry("990x550") # Set the window width
157+
self.root.geometry("990x610") # Set the window width
157158

158159
# Bind the close_connection_and_quit function to the window close event
159160
self.root.protocol("WM_DELETE_WINDOW", self.close_connection_and_quit)
@@ -169,8 +170,19 @@ def __init__(self, current_file: str, flight_controller: FlightController, local
169170

170171
self.__create_conf_widgets(__version__)
171172

173+
if self.local_filesystem.configuration_phases:
174+
# Get the first two characters of the last configuration step filename
175+
last_step_filename = next(reversed(self.local_filesystem.file_parameters.keys()))
176+
last_step_nr = int(last_step_filename[:2]) + 1 if len(last_step_filename) >= 2 else 1
177+
178+
self.stage_progress_bar = StageProgressBar(
179+
self.main_frame, self.local_filesystem.configuration_phases, last_step_nr
180+
)
181+
self.stage_progress_bar.pack(side=tk.TOP, fill="x", expand=False, pady=(2, 2), padx=(4, 4))
182+
172183
# Create a DocumentationFrame object for the Documentation Content
173184
self.documentation_frame = DocumentationFrame(self.main_frame, self.local_filesystem, self.current_file)
185+
self.documentation_frame.documentation_frame.pack(side=tk.TOP, fill="x", expand=False, pady=(2, 2), padx=(4, 4))
174186

175187
self.__create_parameter_area_widgets()
176188

@@ -333,7 +345,9 @@ def __create_parameter_area_widgets(self) -> None:
333345
"Upload selected parameters to the flight controller and advance to the next "
334346
"intermediate parameter file\nIf changes have been made to the current file it will ask if you want "
335347
"to save them\nIt will reset the FC if necessary, re-download all parameters and validate their value"
336-
),
348+
)
349+
if self.flight_controller.master
350+
else _("No flight controller connected, without it this is not available"),
337351
)
338352

339353
# Create skip button
@@ -494,6 +508,7 @@ def on_param_file_combobox_change(self, _event: Union[None, tk.Event], forced: b
494508
return
495509
self.parameter_editor_table.generate_edit_widgets_focus_out()
496510
selected_file = self.file_selection_combobox.get()
511+
self._update_progress_bar_from_file(selected_file)
497512
if self.current_file != selected_file or forced:
498513
self.write_changes_to_intermediate_parameter_file()
499514
self.__do_tempcal_imu(selected_file)
@@ -509,6 +524,15 @@ def on_param_file_combobox_change(self, _event: Union[None, tk.Event], forced: b
509524
self.documentation_frame.update_why_why_now_tooltip(selected_file)
510525
self.repopulate_parameter_table(selected_file)
511526

527+
def _update_progress_bar_from_file(self, selected_file: str) -> None:
528+
if self.local_filesystem.configuration_phases:
529+
try:
530+
step_nr = int(selected_file[:2])
531+
self.stage_progress_bar.update_progress(step_nr)
532+
except ValueError as _e:
533+
msg = _("Failed to update progress bar, {selected_file} does not start with two digits like it should: {_e}")
534+
logging_error(msg.format(**locals()))
535+
512536
def download_flight_controller_parameters(self, redownload: bool = False) -> None:
513537
operation_string = _("Re-downloading FC parameters") if redownload else _("Downloading FC parameters")
514538
self.param_download_progress_window = ProgressWindow(

ardupilot_methodic_configurator/frontend_tkinter_parameter_editor_documentation_frame.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ def __init__(self, root: tk.Widget, local_filesystem: LocalFilesystem, current_f
4242

4343
def __create_documentation_frame(self) -> None:
4444
self.documentation_frame = ttk.LabelFrame(self.root, text=_("Documentation"))
45-
self.documentation_frame.pack(side=tk.TOP, fill="x", expand=False, pady=(4, 4), padx=(4, 4))
4645

4746
# Create a grid structure within the documentation_frame
4847
documentation_grid = ttk.Frame(self.documentation_frame)

0 commit comments

Comments
 (0)