Vehicle Configuration Directory Selection Sub-Application Architecture
Overview
The Vehicle Configuration Directory Selection sub-application allows users to create a new vehicle
configuration project, import one from a configured flight controller or .bin log, or open an existing
project. It manages directory selection and downloads parameter documentation for the project firmware.
The architecture follows a clean layered design with dependency injection, where the frontend components
depend on the VehicleProjectManager factory/container class, which provides a unified interface to all
backend services. This ensures loose coupling and better testability.
Requirements
Functional Requirements
- Directory Management
- Must allow creation of new vehicle configuration directories
- Must allow opening of existing vehicle configuration directories
- Must provide re-open functionality for recently used directories
- Must validate directory structure and required files
- Must handle directory permissions and access rights
- Template System
- Must provide a comprehensive template overview interface
- Must support multiple vehicle types (ArduCopter, ArduPlane, Rover, Heli, etc.)
- Must allow template selection based on vehicle characteristics
- Must copy template files to new vehicle directories
- Must preserve template structure and file organization
- Vehicle Template Selection
- Must display available templates with descriptions
- Must show template compatibility information
- Must provide visual representation of template contents
- Must allow filtering and searching of templates
- Must support template comparison features
- Parameter Documentation Management
- Must download parameter documentation metadata for FC firmware version
- Must store documentation files in the appropriate project directory
- Must handle offline operation when documentation is already available
- Must validate documentation file integrity
- Must support multiple documentation formats
- Project Configuration
- Must initialize project configuration files
- Must set up directory structure for parameter files
- Must create necessary subdirectories and organize files
- Must handle configuration file validation
- Must support project metadata management
- Recent Vehicle Directories History
- Must maintain a list of the 5 most recently opened vehicle directories
- Must display recent directories in reverse chronological order (most recent first)
- Must persist the history list across application sessions in settings.json
- Must update history when a vehicle directory is successfully opened
- Must preserve history entries for directories that become temporarily unavailable
- Must be permissive when storing paths (directories may become valid later)
- Must validate paths strictly when opening/using them (show error if invalid or missing)
- Must display history in a read-only combobox widget with full absolute paths
- Must allow selection from history via dropdown selection only (no text editing)
- Must show error message if selected directory no longer exists
- Must maintain history order when the same directory is opened again (promote to top)
- Must limit history to maximum of 5 entries (oldest removed when limit exceeded)
- Must normalize path separators according to the operating system (backslashes on Windows, forward slashes on Unix)
- Must provide graceful fallback if history is empty or corrupted
Non-Functional Requirements
- Usability
- Directory selection should be intuitive and user-friendly
- Template overview should provide clear visual guidance
- File operations should provide clear progress feedback
- Error messages should be actionable and informative
- Performance
- Directory operations should complete quickly
- Template copying should handle large file sets efficiently
- Documentation download should not block the user interface
- Memory usage should be optimized for large template collections
- Reliability
- Must handle incomplete or corrupted templates gracefully
- Must verify successful completion of all file operations
- Must provide rollback capability for failed operations
- Must maintain project integrity during all operations
- Compatibility
- Must support different operating system path conventions
- Must handle various file system limitations
- Must work with different permission systems
- Must support unicode file names and paths
Architecture
Architectural Pattern
The directory selection sub-application follows a Factory/Container Pattern with Dependency Injection:
- Frontend Layer: GUI components (
VehicleProjectOpenerWindow, VehicleProjectCreatorWindow, DirectorySelectionWidgets)
- Facade Layer:
VehicleProjectManager - provides unified interface to all backend services
- Backend Layer: Specialized services (
LocalFilesystem, project creators, openers, etc.)
This architecture ensures:
- Separation of Concerns: Each layer has distinct responsibilities
- Dependency Inversion: Frontend depends on abstractions, not concrete implementations
- Testability: Easy to mock dependencies for unit testing
- Maintainability: Changes to backend services don’t affect frontend code
GUI Frontend Components
Project Opener Window

- File:
frontend_tkinter_project_opener.py
- Purpose: Main interface for opening existing projects and launching new project creation
- Responsibilities:
- Present three main options: Create New, Open Existing, Re-open Last Used
- Handle user interactions and directory selection through callback patterns
- Launch VehicleProjectCreatorWindow for new project creation
- Delegate business logic to VehicleProjectManager
- Manage UI state and user feedback for project opening operations
- Dependencies: Depends only on VehicleProjectManager interface
Project Creator Window

- File:
frontend_tkinter_project_creator.py
- Purpose: Dedicated interface for creating new vehicle projects from templates or a configured flight controller
- Responsibilities:
- Present template selection and project configuration options for template-based creation
- Present destination controls for configured-flight-controller creation
- Handle new project settings and customization dynamically based on flight controller connection state
- Coordinate template selection through TemplateOverviewWindow
- Delegate project creation to VehicleProjectManager
- Provide feedback on creation progress and results
- Dependencies: Depends only on VehicleProjectManager interface
Template Overview Window
- File:
frontend_tkinter_template_overview.py
- Purpose: Visual interface for template browsing and selection
- Responsibilities:
- Display available vehicle templates
- Show template details and compatibility information
- Handle template selection and preview
- Provide template comparison features
- Dependencies: Accesses templates through VehicleProjectManager interface
- File:
frontend_tkinter_directory_selection.py
- Purpose: Reusable directory and path selection widgets
- Responsibilities:
- Provide common directory selection functionality through DirectorySelectionWidgets
- Handle path entry and validation through PathEntryWidget
- Support callback-based directory selection for flexible integration
- Manage widget state and user interactions
- Dependencies: No direct VehicleProjectManager dependency; uses callback patterns
Business logic components
VehicleProjectManager (Facade/Factory)
- File:
data_model_vehicle_project.py
- Purpose: Unified interface and factory for all vehicle project operations
- Responsibilities:
- Coordinate between frontend and backend services
- Provide high-level operations for project creation and opening
- Manage project lifecycle and state transitions
- Abstract backend complexity from frontend components
- Implement factory pattern for creating project-related objects
Backend Components (accessed via VehicleProjectManager)
Project Creation Services
- File:
data_model_vehicle_project_creator.py
- Purpose: Handle creation of new vehicle projects from templates and imported FC data
- Responsibilities:
- Template copying and customization
- Project directory initialization
- Optional substitution of FC parameter values and import of values not represented by the template
- Configuration file setup
- Project metadata creation
- Access: Through VehicleProjectManager factory methods
When FC values are supplied, template parameter files are transformed during copying; the manager then persists
firmware metadata and writes any remaining values to a numbered import file before opening the project.
Project Opening Services
- File:
data_model_vehicle_project_opener.py
- Purpose: Handle opening and validation of existing vehicle projects
- Responsibilities:
- Project directory validation
- Configuration file loading
- Project state reconstruction
- Error handling for corrupted projects
- Access: Through VehicleProjectManager factory methods
Configuration Steps Backend
- File:
backend_filesystem_configuration_steps.py
- Purpose: Manage configuration step definitions and documentation
- Responsibilities:
- Load configuration step metadata
- Validate configuration file structure
- Handle configuration step documentation
- Manage step sequencing and dependencies
Vehicle Components Backend
- File:
backend_filesystem_vehicle_components.py
- Purpose: Handle vehicle component definitions and templates
- Responsibilities:
- Load and validate vehicle component schemas
- Manage component template libraries
- Handle component compatibility checking
- Support component customization
Data Flow
The data flow follows the layered architecture pattern with clear separation of concerns:
- Application Initialization
- Legacy settings migration:
ProgramSettings.migrate_settings_to_latest_version() runs once on startup
- VehicleProjectManager is instantiated with required backend services
- VehicleProjectOpenerWindow receives VehicleProjectManager instance via dependency injection
- Recent directories history loaded via
ProgramSettings.get_recent_vehicle_dirs()
- Templates are loaded through VehicleProjectManager
- UI components are initialized with project manager reference
- Project Selection Flow
- User interacts with VehicleProjectOpenerWindow main interface
- New-project choices include template, configured-flight-controller, and
.bin log creation
- VehicleProjectOpenerWindow launches VehicleProjectCreatorWindow for template or configured-FC creation
- For existing projects: callback functions handle directory selection through VehicleDirectorySelectionWidgets
- New Project Creation Flow
- VehicleProjectCreatorWindow instantiated with project_manager reference
- Template creation presents a selectable template and optional settings
- Configured-FC creation resolves the matching empty firmware template automatically and uses live FC values
- VehicleProjectManager delegates copying to VehicleProjectCreator, persists project metadata, imports any
remaining FC values, opens the project, and updates recent-directory history
- Success and failure feedback is provided through the manager interface
- .bin Log Import Flow
- User clicks Create a vehicle project from a .bin log file in VehicleProjectOpenerWindow (option-1 panel, via
BinLogSelectionWidgets)
- Frontend opens a file-picker; user selects a
.bin ArduPilot log file
- Frontend delegates to
project_manager.create_new_vehicle_from_bin_log(bin_file)
VehicleProjectManager asks VehicleProjectCreator to extract firmware/default/current parameters,
resolve the matching empty template, and copy it without live-FC injection
- The shared import finalization persists firmware metadata, replaces
00_default.param with extracted
defaults, and exports remaining values to a numbered import file
- The project is opened and manager history/state are updated only after file preparation succeeds
- Success/failure feedback provided through manager interface; on failure the new directory
is not registered in session history and manager in-memory state is not updated,
though filesystem changes to the new project directory are not rolled back
- Existing Project Opening Flow
- User interacts with VehicleProjectOpenerWindow
- Frontend presents project opening and re-opening options
- User selects existing directory through DirectorySelectionWidgets with callbacks
- Callback functions call
project_manager.open_vehicle_directory() or project_manager.open_last_vehicle_directory()
- VehicleProjectManager validates directory through opener services
- Project state is reconstructed and validated
- Error handling managed through consistent interface
- Recent Directories History Flow
- On application startup,
ProgramSettings.get_recent_vehicle_dirs() loads history from settings.json; the history is passed through the manager
- History is passed to VehicleProjectOpenerWindow to populate the combobox widget
- User selects a directory from the combobox dropdown
- Frontend calls
project_manager.open_vehicle_directory(selected_dir)
- The
VehicleProjectManager (business logic) stores the path in the recent‑vehicle history
using LocalFilesystem/ProgramSettings abstractions; the frontend never touches
the persistence layer directly
- History is updated: selected directory moved/added to position [0], oldest removed if > 5 entries
- Updated history is persisted to settings.json
- History order maintained: most recent [0] to oldest [4]
Data Models and Storage
Recent Vehicle Directories History Storage
The recent vehicle directories are stored in the settings.json file in the user configuration directory:
Settings File Location:
- Windows:
%APPDATA%\.ardupilot_methodic_configurator\settings.json
- Linux/macOS:
~/.config/.ardupilot_methodic_configurator/settings.json
Data Structure in settings.json:
{
"Format version": 2,
"recent_vehicle_history": [
"C:\\Users\\username\\vehicles\\Quadcopter_Project_2026",
"C:\\Users\\username\\vehicles\\Hexacopter_Project",
"/mnt/projects/ArduPlane_Project",
"C:\\Users\\username\\Documents\\Old_Copter",
"/home/user/ardupilot/Test_Vehicle"
],
"directory_selection": {
"template_dir": "...",
"new_base_dir": "..."
},
"display_usage_popup": { ... },
"connection_history": [ ... ]
}
Data Schema:
- Field Name:
recent_vehicle_history
- Type: Array of strings
- Maximum Length: 5 entries
- Entry Format: Full absolute path with OS-appropriate separators
- Ordering: Index [0] = most recent, Index [4] = oldest
- Path Normalization: Backslashes on Windows, forward slashes on Unix-like systems
- Persistence: Updated on every successful directory open operation
- Migration Strategy:
- Legacy
vehicle_dir from directory_selection is migrated on first startup
- Permissive validation: paths failing strict validation are still migrated with warnings
- Template directories are excluded (detected via
_is_template_directory() check)
- Legacy setting is removed after migration to prevent repeated migration attempts
- Migration occurs once and only once per installation
- Migration: If key doesn’t exist, it’s initialized as empty array
[]
Backward Compatibility:
- On first use after upgrade, legacy
vehicle_dir in directory_selection is migrated to recent_vehicle_history
- Migration is permissive: invalid paths are migrated with warnings (may become valid later)
- Template directory paths are excluded from migration (not user selections)
- Legacy
vehicle_dir setting is always removed after migration attempt (prevents repeated migrations)
- Once migrated,
vehicle_dir is no longer used or written
- The
get_recently_used_dirs() method (invoked via the manager) returns recent_vehicle_history[0] as the last opened directory, or defaults if empty
Integration Points
The directory selection sub-application integrates with other components through the VehicleProjectManager interface:
- Main Application (
__main__.py): Creates VehicleProjectManager and launches VehicleProjectOpenerWindow
- Flight Controller Communication: VehicleProjectManager receives firmware information
- Component Editor: Receives project instance from VehicleProjectManager
- Parameter Editor: Gets configuration and documentation through VehicleProjectManager
- Template System: Accessed through VehicleProjectManager template methods
- File Operations: All file system access goes through VehicleProjectManager facade
Dependency Management
The architecture implements Dependency Inversion Principle:
Frontend (GUI) → VehicleProjectManager (Interface) → Backend Services
Dependencies Flow:
- Frontend depends on VehicleProjectManager interface (abstraction)
- VehicleProjectManager depends on backend service interfaces
- Backend services implement concrete functionality
- No direct dependencies between frontend and backend services
Benefits:
- Easy unit testing with mock VehicleProjectManager
- Backend services can be replaced without frontend changes
- Clear separation of concerns across layers
- Reduced coupling between components
Template Management
Template Structure
Templates are organized hierarchically by vehicle type:
vehicle_templates/
├── ArduCopter/
│ ├── X-Quadcopter/
│ ├── Y6-Hexacopter/
│ └── Traditional-Helicopter/
├── ArduPlane/
│ ├── Fixed-Wing/
│ └── VTOL/
└── Rover/
├── 4WD/
└── Boat/
Template Content
Each template contains:
- Parameter files (*.param) for configuration steps
- Vehicle component configuration (vehicle_components.json)
- Configuration step definitions
- Documentation and readme files
- Default parameter values
Error Handling Strategy
- Directory Access Errors: Provide clear guidance for permission issues
- Template Corruption: Validate templates and provide recovery options
- Network Errors: Handle documentation download failures gracefully
- File System Errors: Provide detailed error information and recovery steps
Testing Strategy
The layered architecture enables comprehensive testing at each level:
Unit Testing
- VehicleProjectManager: Test facade methods with mocked backend services
- Frontend Components: Test with mocked VehicleProjectManager interface
- Backend Services: Test in isolation with mocked dependencies
- Integration Points: Test VehicleProjectManager coordination logic
Test Fixtures and Mocking
mock_project_manager: Mock VehicleProjectManager for frontend tests
mock_local_filesystem: Mock backend services for manager tests
- Dependency injection enables easy test isolation
- Clear interfaces make mocking straightforward
Test Coverage Areas
- Directory validation through VehicleProjectManager interface
- Template operations via manager facade methods
- Error handling across architecture layers
- UI interactions with mocked manager dependencies
- File system operations through abstracted interfaces
Architecture Testing Benefits
- Isolation: Each layer tested independently
- Maintainability: Tests don’t break when backend implementation changes
- Clarity: Test focus matches architectural responsibilities
- Reliability: Mock interfaces provide consistent test behavior
Note: Acceptance tests for the Recent Vehicle Directories History feature are implemented in tests/acceptance_recent_vehicle_directories_history.py.
File Structure
# Frontend Layer (GUI)
frontend_tkinter_project_opener.py # Main vehicle project selection interface
frontend_tkinter_project_creator.py # Dedicated new project creation interface
frontend_tkinter_directory_selection.py # Reusable directory selection widgets with callback support
frontend_tkinter_template_overview.py # Template browsing and selection interface
# Facade/Factory Layer (Business Logic Coordination)
data_model_vehicle_project.py # VehicleProjectManager facade/factory
# Backend Services Layer (Specialized Operations)
data_model_vehicle_project_creator.py # New project creation services
data_model_vehicle_project_opener.py # Existing project opening services
backend_filesystem.py # File system operations
backend_filesystem_configuration_steps.py # Configuration step management
backend_filesystem_vehicle_components.py # Vehicle component handling
# Test Layer
tests/test_frontend_tkinter_project_opener.py # Project opener tests with mocked dependencies
tests/test_frontend_tkinter_project_creator.py # Project creator tests with mocked dependencies
tests/test_frontend_tkinter_directory_selection.py # Directory widgets tests
tests/test_frontend_tkinter_template_overview.py # Template overview tests
tests/acceptance_recent_vehicle_directories_history.py # Acceptance tests for recent directories history feature
Dependencies
External Dependencies
- Python Standard Library:
os and pathlib for path operations
shutil for directory copying
json for configuration file handling
tkinter for GUI components
- Third-party Libraries:
jsonschema for configuration validation
PIL (Pillow) for image handling in templates
Internal Architecture Dependencies
- Frontend Layer Dependencies:
data_model_vehicle_project.VehicleProjectManager (facade interface)
frontend_tkinter_base_window for GUI base classes
frontend_tkinter_directory_selection for reusable widgets
frontend_tkinter_template_overview for template selection
frontend_tkinter_scroll_frame for scrollable interfaces
- VehicleProjectManager Dependencies:
backend_filesystem.LocalFilesystem for file operations
data_model_vehicle_project_creator for project creation
data_model_vehicle_project_opener for project opening
- Data model classes for configuration management
- Backend Services Dependencies:
- Standard library modules for specific operations
- Configuration and schema validation libraries
- File system and network access modules
Dependency Injection Pattern
The architecture implements dependency injection where:
- Frontend receives VehicleProjectManager instance via constructor
- VehicleProjectManager receives backend services via constructor
- No direct frontend-to-backend dependencies
- Easy to substitute mock objects for testing
- Clear separation of concerns across layers
Architectural Benefits
Design Patterns Implemented
- Facade Pattern: VehicleProjectManager provides simplified interface to complex backend subsystems
- Factory Pattern: VehicleProjectManager creates and manages project-related objects
- Dependency Injection: Components receive dependencies via constructor parameters
- Layer Architecture: Clear separation between frontend, facade, and backend layers
Code Quality Improvements
- Loose Coupling: Frontend components don’t depend on specific backend implementations
- High Cohesion: Each component has a single, well-defined responsibility
- Testability: Easy to unit test with mocked dependencies
- Maintainability: Changes to one layer don’t cascade to other layers
- Extensibility: New backend services can be added without frontend changes
Development Benefits
- Parallel Development: Frontend and backend teams can work independently
- Easier Debugging: Clear component boundaries make issue isolation simpler
- Better Testing: Each layer can be tested in isolation with appropriate mocks
- Code Reuse: VehicleProjectManager can be used by multiple frontend components
- Consistent Interface: All vehicle project operations go through unified interface