Motor Test Sub-application Architecture
Status Legend
- β
Green Check: Fully implemented and tested with BDD pytest
- π‘ Yellow Check: Implemented but not yet tested with BDD pytest
- β Red Cross: Not implemented
Overview
The Motor Test sub-application provides a graphical interface for testing individual motors on ArduPilot vehicles, similar to Mission Plannerβs motor test functionality.
It allows users to test motor functionality, verify motor order and direction, and configure motor parameters before flight.
Requirements Analysis
Functional Requirements
- Frame Configuration Interface
- β
FRAME_TYPE dropdown populated from parameter documentation metadata
- β
Immediate parameter application to flight controller on selection
- β
Dynamic motor count calculation based on frame configuration
- β
Motor diagram display showing the currently selected frame configuration
- β
SVG motor diagrams loaded from local images directory (downloaded from ArduPilot documentation)
- The original diagrams are the
.svg
files in the https://ardupilot.org/copter/_images/
directory
- Motor Parameter Configuration
- β
βSet Motor Spin Armβ button with parameter dialog for MOT_SPIN_ARM
- β
βSet Motor Spin Minβ button with parameter dialog for MOT_SPIN_MIN
- β
Immediate parameter save and upload to flight controller
- β
Current value display and validation
- Motor Testing Interface
- β
Display N motor test buttons based on detected/configured frame
- β
Label buttons with letters (A, B, C, Dβ¦) following ArduPilot conventions
- β
Expected direction labels (CW/CCW) for each motor position
- β
Detected order dropdown comboboxes for user feedback
- β
Configurable test duration (default: 2 seconds)
- β
Real-time BATT1 voltage and current display with color-coded status
- Battery Status Display
- β
Current BATT1 voltage and current readings (only when BATT_MONITOR != 0)
- β
When BATT_MONITOR == 0: Display βN/Aβ
- β
Color-coded voltage display based on BATT_ARM_VOLT and MOT_BAT_VOLT_MAX thresholds:
- Green: Voltage within BATT_ARM_VOLT to MOT_BAT_VOLT_MAX range (safe for motor testing)
- Red: Voltage outside the safe range (unsafe for motor testing)
- β
Safety popup when motor testing attempted with voltage outside safe range
- β
Real-time updates during motor testing operations
- Safety Controls
- β
Prominent red βStop all motorsβ emergency button
- β
βTest in Sequenceβ button for automated testing
- β
Safety warnings and operational guidelines at top
- β
Parameter validation before motor testing
- β
Automatic motor timeout for safety
- Order Detection and Validation
- β
User-selectable βDetectedβ comboboxes for each motor
- π‘ Comparison between expected and detected motor order
- β
Visual feedback for correct/incorrect motor placement
- π‘ Guidance for correcting wiring issues
Non-Functional Requirements
- Safety
- Multiple safety warnings prominently displayed
- Clear indication of active motor testing
- Emergency stop functionality always accessible
- Safe parameter defaults and validation
- Usability
- Intuitive frame-based layout with logical workflow progression
- Clear visual feedback for active operations
- Immediate parameter application with confirmation
- Responsive UI with real-time feedback
- Keyboard shortcuts for critical functions
- Reliability
- Active flight controller connection required for all motor testing operations
- Robust error handling for communication failures
- Parameter validation and bounds checking
- Graceful degradation when features unavailable
- Comprehensive logging for debugging
- Performance
- Responsive UI updates during motor testing
- Efficient parameter reading/writing
- Minimal latency for emergency stop operations
- Low resource usage
System Design
Architecture Pattern
The motor test sub-application follows the Model-View separation pattern established in the project:
βββββββββββββββββββ ββββββββββββββββββββββββ
β GUI Layer β β Data Model Layer β
β β β β
β frontend_tkinterβββββΊβ data_model_motor β
β _motor_test.py β β _test.py β
β β β β
β - UI Layout β β - Business Logic β
β - Event Handlingβ β - Parameter Mgmt β
β - User Feedback β β - Frame Detection β
βββββββββββββββββββ ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββ
β Backend Layer β
β β
β βββββββββββββββββββββββββββββββββββββββ€
β β backend_flightcontroller.py β
β β - Motor test commands (individual, β
β β all, sequence, emergency stop) β
β β - Battery monitoring & safety β
β β β - Frame detection & motor count β
β β - MAVLink communication β
β β - Parameter read/write β
β βββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββββββββββββββββββββββββββ€
β β backend_filesystem.py β
β β - Safety validation logic β
β β - Frame configuration support β
β β - Parameter documentation metadata β
β βββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββββββββββββββββββββββββββ€
β β backend_filesystem_program_settings.py β
β β - Motor diagram SVG file access β
β β - Settings persistence (test duration)β
β β - Application configuration β
β βββββββββββββββββββββββββββββββββββββββ€
βββββββββββββββββββββββββββββββββββββββββ
Component Responsibilities
Data Model Layer (data_model_motor_test.py
)
Primary Responsibilities:
- Frame type detection and motor count calculation
- Motor label generation (numbers and letters)
- Parameter reading and writing (MOT_SPIN_ARM, MOT_SPIN_MIN)
- Battery status monitoring (BATT1 voltage and current when BATT_MONITOR != 0)
- Voltage threshold validation (BATT_ARM_VOLT and MOT_BAT_VOLT_MAX thresholds)
- Business logic validation
- Backend coordination and abstraction
Key Methods:
def __init__(self, flight_controller: FlightController, filesystem: LocalFilesystem, settings: ProgramSettings) -> None
def get_motor_count(self) -> int
def get_motor_labels(self) -> list[str]
def get_motor_numbers(self) -> list[int]
def get_motor_directions(self) -> list[str] # Returns CW/CCW direction labels for each motor
def get_battery_status(self) -> Optional[tuple[float, float]] # voltage, current or None if BATT_MONITOR == 0
def get_voltage_status(self) -> str # "safe", "critical" "unavailable" or "disabled"
def is_battery_monitoring_enabled(self) -> bool # True if BATT_MONITOR != 0
def is_motor_test_safe(self) -> tuple[bool, str] # (is_safe, reason)
def set_parameter(self, param_name: str, value: float) -> tuple[bool, str] # (success, error_message)
def get_parameter(self, param_name: str) -> Optional[float]
def test_motor(self, motor_number: int, throttle_percent: int, timeout_seconds: int) -> tuple[bool, str]
def test_all_motors(self, throttle_percent: int, timeout_seconds: int) -> tuple[bool, str]
def test_motors_in_sequence(self, throttle_percent: int, timeout_seconds: int) -> tuple[bool, str]
def stop_all_motors(self) -> tuple[bool, str]
def get_motor_diagram_path(self) -> tuple[str, str] # Returns (filepath, description)
def motor_diagram_exists(self) -> bool
def get_test_duration(self) -> float
def set_test_duration(self, duration: float) -> bool
def get_test_throttle_pct(self) -> int
def set_test_throttle_pct(self, throttle: int) -> bool
def update_frame_configuration(self, frame_class: int, frame_type: int) -> tuple[bool, str]
def get_frame_options(self) -> dict[str, dict[int, str]]
def refresh_connection_status(self) -> bool
def get_voltage_thresholds(self) -> tuple[float, float] # Returns (BATT_ARM_VOLT, MOT_BAT_VOLT_MAX)
Data Attributes:
flight_controller
: Backend flight controller interface
filesystem
: Backend filesystem interface
settings
: Backend program settings interface
frame_class
: Detected vehicle frame class
frame_type
: Detected vehicle frame type
motor_count
: Number of motors for current frame
Backend Layer Distribution
The motor test sub-application backend logic is distributed across three specialized backend modules:
backend_flightcontroller.py
- Flight Controller Communication
Responsibilities:
- Direct MAVLink communication with flight controller
- Motor testing command execution
- Real-time battery monitoring and telemetry
- Parameter read/write operations
- Flight controller status monitoring
Key Motor Test Methods:
def test_motor(self, motor_number: int, throttle_percent: int, timeout_seconds: int) -> tuple[bool, str]
def test_all_motors(self, throttle_percent: int, timeout_seconds: int) -> tuple[bool, str]
def test_motors_in_sequence(self, throttle_percent: int, timeout_seconds: int) -> tuple[bool, str]
def stop_all_motors(self) -> tuple[bool, str]
def get_battery_status(self) -> tuple[Union[tuple[float, float], None], str]
def get_voltage_thresholds(self) -> tuple[float, float]
def is_battery_monitoring_enabled(self) -> bool
def get_frame_info(self) -> tuple[int, int]
def get_motor_count_from_frame(self) -> int
backend_filesystem.py
- Safety & Parameter Support
Responsibilities:
- Motor testing safety validation logic
- Parameter default values and bounds checking
- Frame configuration from parameter metadata
- Parameter documentation access
backend_filesystem_program_settings.py
- Diagrams & Settings
Responsibilities:
- Motor diagram SVG file access and validation
- User settings persistence (test duration, preferences)
- Application configuration management
Key Motor Test Methods:
@staticmethod
def motor_diagram_filepath(frame_class: int, frame_type: int) -> str
@staticmethod
def motor_diagram_exists(frame_class: int, frame_type: int) -> bool
# Settings persistence methods (protected methods for test duration, etc.)
GUI Layer (frontend_tkinter_motor_test.py
)
Primary Responsibilities:
- User interface layout and visual design
- Event handling and user interactions
- Real-time feedback and status updates
- Safety confirmations and warnings
- Integration with application window management
Key UI Components:
- Information and safety warnings at the top
- Frame configuration section with FRAME_TYPE and FRAME_CLASS comboboxes
- Arm and min throttle configuration with parameter buttons
- Motor order/direction configuration with test buttons and direction detection
- Real-time battery status display with color-coded voltage indication
- Prominent red emergency stop button and test sequence controls
Layout Structure:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Information & Safety Warnings β
β β’ Remove propellers before testing β
β β’ Ensure vehicle is secured β
β β’ Emergency stop always available β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 1. Frame configuration β
β Frame Type: [FRAME_TYPE βΌ] Frame Class: [FRAME_CLASS βΌ] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 2. Arm and min throttle configuration β
β [Set Motor Spin Arm] [Set Motor Spin Min] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 3. Motor order/direction configuration β
β Duration: [____] seconds Battery: 12.4V/2.1A β
β β
β [Motor A] Motor 1 CW [Detected: βΌ] β
β [Motor B] Motor 2 CCW [Detected: βΌ] β
β [Motor C] Motor 3 CCW [Detected: βΌ] β
β [Motor D] Motor 4 CW [Detected: βΌ] β
β ... β
β β
β [π STOP ALL MOTORS] [Test in Sequence] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data Flow
User Workflow Sequence
- Safety Setup
- User reads safety warnings and ensures propellers are removed
- User secures vehicle to prevent movement during tests
- Frame Configuration
- User selects appropriate FRAME_TYPE from dropdown (populated from parameter documentation)
- Parameters are immediately applied to flight controller on selection
- Motor Parameter Configuration
- User clicks βSet Motor Spin Armβ to configure MOT_SPIN_ARM parameter
- User clicks βSet Motor Spin Minβ to configure MOT_SPIN_MIN parameter
- Each button opens parameter dialog and saves/uploads value immediately
- Motor Testing and Order Detection
- User monitors real-time battery voltage and current display (if BATT_MONITOR != 0)
- User sets throttle % (default: 1%)
- User sets test duration (default: 2 seconds)
- User tests individual motors using labeled buttons (Motor A, B, C, etc.)
- User observes actual motor spinning and records in βDetectedβ comboboxes
- System provides color-coded voltage feedback (green=safe, red=outside safe range)
- Safety popup appears when attempting motor test with voltage outside BATT_ARM_VOLT to MOT_BAT_VOLT_MAX range
- User can run βTest in Sequenceβ to automatically test all motors
- Emergency stop button available at all times during testing
- Order Validation
- System compares expected vs detected motor order
- User corrects any wiring issues based on feedback
- System provides guidance on proper motor/ESC connections
Motor Testing Workflow
- Initialization: GUI requests motor count and labels from data model
- Frame Detection: Data model reads FRAME_CLASS/FRAME_TYPE parameters
- Battery Monitoring: Data model reads BATT1 voltage/current and BATT_ARM_VOLT/MOT_BAT_VOLT_MAX thresholds (if BATT_MONITOR != 0)
- UI Setup: Dynamic button creation based on detected frame configuration
- Battery Validation: System checks voltage status before allowing motor tests
- User Action: User clicks motor test button
- Safety Validation: Data model validates parameters, battery status (if enabled), and safety conditions
- Execution: Motor command sent to flight controller via backend
- Feedback: UI updates to show active motor testing status and battery monitoring
- Completion: Automatic timeout or user stop action
Battery Safety Validation Workflow
- Motor Test Request: User clicks any motor test button
- Battery Monitor Check: Data model checks if BATT_MONITOR != 0
- Voltage Range Check: If battery monitoring enabled, validate voltage is within BATT_ARM_VOLT to MOT_BAT_VOLT_MAX range
- Safety Popup: If voltage outside safe range, display popup:
βBattery voltage outside safe range. Please connect battery and/or ensure battery is in charged state.β
- User Action: User can choose to:
- Cancel motor test and address battery issue
- Override and proceed (with additional warning)
- Test Execution: Motor test proceeds only if voltage is safe or user explicitly overrides
Parameter Configuration Workflow
- Frame Selection: User selects FRAME_TYPE from dropdowns
- Immediate Application: Parameters uploaded to flight controller immediately
- Parameter Button: User clicks βSet Motor Spin Arm/Minβ button
- Current Value: Data model reads current parameter value
- User Input: GUI presents input dialog with current value
- Validation: Data model validates new parameter value
- Update: Parameter uploaded to flight controller
- Confirmation: UI confirms successful parameter update
Testing Strategy
Current Test Coverage Status
Data Model Tests (tests/test_data_model_motor_test.py
) - β
IMPLEMENTED
Status: 54 comprehensive BDD pytest tests implemented covering all functionality
Test Coverage Areas:
- β
Frame detection logic with various FRAME_CLASS/FRAME_TYPE combinations
- β
Motor count calculation for all supported frame types
- β
Motor label generation (number/letter mapping)
- β
Parameter validation and bounds checking
- β
Error handling for communication failures
- β
Motor testing command generation
- β
Battery monitoring and safety validation
- β
Settings persistence and configuration management
- β
Exception handling and edge cases
GUI Tests (tests/test_frontend_tkinter_motor_test.py
) - β NOT IMPLEMENTED
Status: Frontend tests not yet implemented
Planned Test Coverage:
- β UI component creation and layout
- β Button generation based on motor count
- β Event handling for all interactive elements
- β Safety confirmation dialogs
- β Parameter input validation
- β Integration with data model layer
- β Keyboard shortcut functionality
- β SVG diagram rendering
Integration Testing
End-to-End Scenarios
- Complete motor testing workflow from GUI to flight controller
- Parameter configuration and validation
- Emergency stop functionality
- Multi-frame type support validation
Mock Testing Strategy
- Flight controller communication mocking
- Parameter read/write simulation
- Frame detection with various configurations
- Error condition simulation
- Safety mechanism testing
Test Fixtures and Patterns
Following project pytest guidelines with BDD structure:
@pytest.fixture
def mock_flight_controller() -> MagicMock:
"""Fixture providing mocked flight controller with realistic responses."""
@pytest.fixture
def motor_test_data_model(mock_flight_controller) -> MotorTestDataModel:
"""Fixture providing configured motor test data model."""
@pytest.fixture
def motor_test_window(motor_test_data_model) -> MotorTestWindow:
"""Fixture providing configured motor test GUI window."""
def test_user_can_test_individual_motor(self, motor_test_window) -> None:
"""
User can test individual motors safely.
GIVEN: A configured vehicle with detected frame type
WHEN: User clicks a motor test button
THEN: The corresponding motor should activate with feedback
"""
Implementation Guidelines
Code Style Requirements
- Type Hints: All functions must include complete type annotations
- Documentation: Comprehensive docstrings following project standards
- Error Handling: Graceful error handling with user feedback
- Logging: Appropriate logging for debugging and audit trail
- Internationalization: All user-facing strings wrapped with
_()
Safety Implementation
- Parameter Validation: All parameters validated before sending to FC
- Battery Monitoring: Real-time battery voltage monitoring with BATT_ARM_VOLT/MOT_BAT_VOLT_MAX threshold validation (when BATT_MONITOR != 0)
- Voltage Safety: Safety popup when attempting motor test with voltage outside safe range, prompting user to connect battery and/or ensure charged state
- Timeout Mechanisms: Automatic motor stop after configured timeout
- Emergency Stop: Always accessible stop functionality
- User Confirmation: Display a Safety confirmation popup the first time a Motor test button is pressed
- Visual Feedback: Clear indication of active motor testing (status column) and battery status (green/red voltage display)
- Lazy Loading: UI components created only when needed
- Efficient Updates: Minimal UI updates during motor testing
- Resource Management: Proper cleanup of timers and connections
- Responsive Design: Non-blocking operations for UI responsiveness
Integration Points
Main Application Integration
The motor test sub-application integrates with the main ArduPilot Methodic Configurator through:
- Menu Integration: Accessible from dedicated button
- Flight Controller Sharing: Uses existing FC connection
- Parameter Context: Reads current vehicle configuration (LocalFilesystem)
- Logging Integration: Uses application logging framework
- Settings Persistence: Saves user settings (test duration in ProgramSettings)
Backend Architecture Integration
The motor test sub-application leverages the existing backend infrastructure without requiring additional backend modules:
Flight Controller Backend Integration (backend_flightcontroller.py
)
- Existing Infrastructure: Utilizes the established MAVLink connection and parameter system
- Motor Commands: All motor testing functionality is already implemented with proper error handling
- Battery Monitoring: Real-time telemetry integration with safety threshold validation
- Frame Detection: Automatic vehicle configuration detection from flight controller parameters
Filesystem Backend Integration (backend_filesystem.py
)
- Safety Framework: Leverages existing parameter validation and safety check infrastructure
- Configuration Management: Uses established parameter default and metadata systems
- Documentation Access: Integrates with existing parameter documentation framework
Program Settings Integration (backend_filesystem_program_settings.py
)
- Motor Diagrams: Comprehensive SVG diagram support for all ArduPilot frame types
- Settings Persistence: Consistent user preference storage using established patterns
- Resource Management: Proper handling of application resources and file paths
This architecture demonstrates the projectβs modular design - new sub-applications can be implemented by primarily creating frontend
and data model layers while leveraging the robust, tested backend infrastructure that already exists.
ArduPilot Integration
Communication with ArduPilot flight controller via:
- MAVLink Protocol: Standard parameter and command protocols
- Parameter System: Read/write MOT_* parameters
- Motor Commands: Direct motor control via MAVLink
- Status Monitoring: Real-time status and safety monitoring
- Frame Detection: Automatic vehicle configuration detection
Future Enhancements
Planned Features
- Motor Health Monitoring: Current draw and performance metrics
- Calibration Assistance: Guided motor calibration procedures
- Visual Frame Display: Graphical representation of motor layout
Security Considerations
Safety Measures
- Parameter Bounds: Strict validation of all motor parameters
Risk Mitigation
- Hardware Safety: Clear warnings about propeller removal
- Software Safety: Multiple layers of safety checks
- Communication Safety: Robust error handling for comm failures
- User Safety: Clear operational guidelines and warnings
This architecture provides a comprehensive foundation for implementing a safe, reliable, and user-friendly motor test sub-application
that integrates seamlessly with the ArduPilot Methodic Configurator while maintaining the highest safety standards for motor testing operations.