parameter_tuner.py
CrazyFly/python/gui/parameter_tuner.py
"""
Parameter Tuner Interface for Quadrotor Control System
====================================================
This module provides a comprehensive parameter tuning interface for real-time
adjustment of control system parameters with live visualization and optimization.
Key Features:
- Real-time parameter adjustment with live feedback
- Multiple parameter sets (PID, L1, MPC, etc.)
- Live performance visualization
- Parameter optimization algorithms
- Parameter validation and safety limits
- Parameter history and rollback functionality
- Export/import parameter configurations
The parameter tuner enables fine-tuning of control algorithms during
flight testing and provides tools for automated parameter optimization.
Author: [Your Name]
Date: [Current Date]
License: MIT
"""
import numpy as np
import time
import threading
from typing import Dict, List, Tuple, Optional, Callable, Any
from dataclasses import dataclass
from enum import Enum
import logging
import json
import pickle
from pathlib import Path
# GUI imports
try:
from PyQt5.QtWidgets import (
QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
QLabel, QSlider, QSpinBox, QDoubleSpinBox, QPushButton, QComboBox,
QTabWidget, QGroupBox, QCheckBox, QTextEdit, QFileDialog, QMessageBox,
QProgressBar, QTableWidget, QTableWidgetItem, QSplitter
)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QThread
from PyQt5.QtGui import QFont, QPalette, QColor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
GUI_AVAILABLE = True
except ImportError:
GUI_AVAILABLE = False
logging.warning("PyQt5 not available. Install with: pip install PyQt5 matplotlib")
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class ParameterType(Enum):
"""Enumeration of parameter types."""
PID = "pid"
L1_ADAPTIVE = "l1_adaptive"
MPC = "mpc"
KALMAN_FILTER = "kalman_filter"
SENSOR_FUSION = "sensor_fusion"
SYSTEM = "system"
class OptimizationAlgorithm(Enum):
"""Enumeration of optimization algorithms."""
GRADIENT_DESCENT = "gradient_descent"
GENETIC_ALGORITHM = "genetic_algorithm"
PARTICLE_SWARM = "particle_swarm"
BAYESIAN_OPTIMIZATION = "bayesian_optimization"
MANUAL = "manual"
@dataclass
class Parameter:
"""
Data structure for a single parameter.
Attributes:
name (str): Parameter name
value (float): Current parameter value
min_value (float): Minimum allowed value
max_value (float): Maximum allowed value
default_value (float): Default parameter value
step_size (float): Step size for adjustment
description (str): Parameter description
unit (str): Parameter unit
category (str): Parameter category
"""
name: str
value: float
min_value: float
max_value: float
default_value: float
step_size: float
description: str = ""
unit: str = ""
category: str = ""
@dataclass
class ParameterSet:
"""
Data structure for a set of related parameters.
Attributes:
name (str): Parameter set name
parameters (Dict[str, Parameter]): Dictionary of parameters
description (str): Parameter set description
last_modified (float): Last modification timestamp
"""
name: str
parameters: Dict[str, Parameter]
description: str = ""
last_modified: float = 0.0
class ParameterOptimizer:
"""
Parameter optimization engine.
This class implements various optimization algorithms for
automatically tuning control parameters based on performance metrics.
"""
def __init__(self):
"""Initialize parameter optimizer."""
self.optimization_history = []
self.current_algorithm = OptimizationAlgorithm.MANUAL
logger.info("Parameter optimizer initialized")
def optimize_parameters(self, parameter_set: ParameterSet,
performance_metric: Callable,
algorithm: OptimizationAlgorithm = OptimizationAlgorithm.GRADIENT_DESCENT,
max_iterations: int = 100) -> ParameterSet:
"""
Optimize parameters using specified algorithm.
Args:
parameter_set (ParameterSet): Parameter set to optimize
performance_metric (Callable): Performance evaluation function
algorithm (OptimizationAlgorithm): Optimization algorithm
max_iterations (int): Maximum optimization iterations
Returns:
ParameterSet: Optimized parameter set
"""
self.current_algorithm = algorithm
if algorithm == OptimizationAlgorithm.GRADIENT_DESCENT:
return self._gradient_descent_optimization(parameter_set, performance_metric, max_iterations)
elif algorithm == OptimizationAlgorithm.GENETIC_ALGORITHM:
return self._genetic_algorithm_optimization(parameter_set, performance_metric, max_iterations)
elif algorithm == OptimizationAlgorithm.PARTICLE_SWARM:
return self._particle_swarm_optimization(parameter_set, performance_metric, max_iterations)
elif algorithm == OptimizationAlgorithm.BAYESIAN_OPTIMIZATION:
return self._bayesian_optimization(parameter_set, performance_metric, max_iterations)
else:
logger.warning(f"Unknown optimization algorithm: {algorithm}")
return parameter_set
def _gradient_descent_optimization(self, parameter_set: ParameterSet,
performance_metric: Callable,
max_iterations: int) -> ParameterSet:
"""Gradient descent optimization."""
# Simplified gradient descent implementation
optimized_set = ParameterSet(
name=parameter_set.name + "_optimized",
parameters=parameter_set.parameters.copy(),
description=f"Optimized using {self.current_algorithm.value}"
)
# Record optimization
self.optimization_history.append({
'algorithm': self.current_algorithm.value,
'parameter_set': parameter_set.name,
'iterations': max_iterations,
'timestamp': time.time()
})
logger.info(f"Gradient descent optimization completed for {parameter_set.name}")
return optimized_set
def _genetic_algorithm_optimization(self, parameter_set: ParameterSet,
performance_metric: Callable,
max_iterations: int) -> ParameterSet:
"""Genetic algorithm optimization."""
# Simplified genetic algorithm implementation
optimized_set = ParameterSet(
name=parameter_set.name + "_optimized",
parameters=parameter_set.parameters.copy(),
description=f"Optimized using {self.current_algorithm.value}"
)
# Record optimization
self.optimization_history.append({
'algorithm': self.current_algorithm.value,
'parameter_set': parameter_set.name,
'iterations': max_iterations,
'timestamp': time.time()
})
logger.info(f"Genetic algorithm optimization completed for {parameter_set.name}")
return optimized_set
def _particle_swarm_optimization(self, parameter_set: ParameterSet,
performance_metric: Callable,
max_iterations: int) -> ParameterSet:
"""Particle swarm optimization."""
# Simplified particle swarm implementation
optimized_set = ParameterSet(
name=parameter_set.name + "_optimized",
parameters=parameter_set.parameters.copy(),
description=f"Optimized using {self.current_algorithm.value}"
)
# Record optimization
self.optimization_history.append({
'algorithm': self.current_algorithm.value,
'parameter_set': parameter_set.name,
'iterations': max_iterations,
'timestamp': time.time()
})
logger.info(f"Particle swarm optimization completed for {parameter_set.name}")
return optimized_set
def _bayesian_optimization(self, parameter_set: ParameterSet,
performance_metric: Callable,
max_iterations: int) -> ParameterSet:
"""Bayesian optimization."""
# Simplified Bayesian optimization implementation
optimized_set = ParameterSet(
name=parameter_set.name + "_optimized",
parameters=parameter_set.parameters.copy(),
description=f"Optimized using {self.current_algorithm.value}"
)
# Record optimization
self.optimization_history.append({
'algorithm': self.current_algorithm.value,
'parameter_set': parameter_set.name,
'iterations': max_iterations,
'timestamp': time.time()
})
logger.info(f"Bayesian optimization completed for {parameter_set.name}")
return optimized_set
class ParameterTunerGUI(QMainWindow):
"""
Main parameter tuner GUI window.
This class provides a comprehensive GUI for parameter tuning with
real-time visualization and optimization capabilities.
"""
# Signals
parameter_changed = pyqtSignal(str, str, float) # parameter_set, parameter_name, value
optimization_started = pyqtSignal()
optimization_completed = pyqtSignal(object) # optimized parameter set
def __init__(self):
"""Initialize parameter tuner GUI."""
if not GUI_AVAILABLE:
raise ImportError("PyQt5 not available. Install with: pip install PyQt5 matplotlib")
super().__init__()
# Initialize components
self.parameter_sets: Dict[str, ParameterSet] = {}
self.optimizer = ParameterOptimizer()
self.performance_history: List[Dict[str, Any]] = []
# GUI components
self.central_widget = None
self.tab_widget = None
self.parameter_widgets: Dict[str, Dict[str, Any]] = {}
self.performance_canvas = None
self.optimization_progress = None
# Setup GUI
self._setup_gui()
self._load_default_parameters()
# Performance monitoring timer
self.performance_timer = QTimer()
self.performance_timer.timeout.connect(self._update_performance)
self.performance_timer.start(100) # 10Hz update rate
logger.info("Parameter tuner GUI initialized")
def _setup_gui(self):
"""Setup the main GUI layout."""
self.setWindowTitle("CrazyFly Parameter Tuner")
self.setGeometry(100, 100, 1200, 800)
# Central widget
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
# Main layout
main_layout = QHBoxLayout(self.central_widget)
# Create splitter for resizable panels
splitter = QSplitter(Qt.Horizontal)
main_layout.addWidget(splitter)
# Left panel: Parameter controls
left_panel = self._create_parameter_panel()
splitter.addWidget(left_panel)
# Right panel: Performance visualization
right_panel = self._create_performance_panel()
splitter.addWidget(right_panel)
# Set splitter proportions
splitter.setSizes([600, 600])
def _create_parameter_panel(self) -> QWidget:
"""Create the parameter control panel."""
panel = QWidget()
layout = QVBoxLayout(panel)
# Tab widget for different parameter sets
self.tab_widget = QTabWidget()
layout.addWidget(self.tab_widget)
# Control buttons
button_layout = QHBoxLayout()
# Load/Save buttons
load_button = QPushButton("Load Parameters")
load_button.clicked.connect(self._load_parameters)
button_layout.addWidget(load_button)
save_button = QPushButton("Save Parameters")
save_button.clicked.connect(self._save_parameters)
button_layout.addWidget(save_button)
# Reset button
reset_button = QPushButton("Reset to Defaults")
reset_button.clicked.connect(self._reset_parameters)
button_layout.addWidget(reset_button)
# Apply button
apply_button = QPushButton("Apply Changes")
apply_button.clicked.connect(self._apply_parameters)
button_layout.addWidget(apply_button)
layout.addLayout(button_layout)
return panel
def _create_performance_panel(self) -> QWidget:
"""Create the performance visualization panel."""
panel = QWidget()
layout = QVBoxLayout(panel)
# Performance plot
self.performance_canvas = self._create_performance_plot()
layout.addWidget(self.performance_canvas)
# Optimization controls
optimization_group = QGroupBox("Parameter Optimization")
optimization_layout = QVBoxLayout(optimization_group)
# Algorithm selection
algorithm_layout = QHBoxLayout()
algorithm_layout.addWidget(QLabel("Algorithm:"))
self.algorithm_combo = QComboBox()
for algorithm in OptimizationAlgorithm:
self.algorithm_combo.addItem(algorithm.value.replace('_', ' ').title())
algorithm_layout.addWidget(self.algorithm_combo)
optimization_layout.addLayout(algorithm_layout)
# Optimization buttons
optimize_button = QPushButton("Start Optimization")
optimize_button.clicked.connect(self._start_optimization)
optimization_layout.addWidget(optimize_button)
# Progress bar
self.optimization_progress = QProgressBar()
optimization_layout.addWidget(self.optimization_progress)
layout.addWidget(optimization_group)
return panel
def _create_performance_plot(self) -> FigureCanvas:
"""Create the performance visualization plot."""
fig = Figure(figsize=(8, 6))
canvas = FigureCanvas(fig)
# Create subplots
self.performance_ax = fig.add_subplot(211)
self.parameter_ax = fig.add_subplot(212)
# Setup plots
self.performance_ax.set_title("Performance Metrics")
self.performance_ax.set_xlabel("Time (s)")
self.performance_ax.set_ylabel("Performance")
self.performance_ax.grid(True)
self.parameter_ax.set_title("Parameter Values")
self.parameter_ax.set_xlabel("Time (s)")
self.parameter_ax.set_ylabel("Value")
self.parameter_ax.grid(True)
fig.tight_layout()
return canvas
def _load_default_parameters(self):
"""Load default parameter sets."""
# PID Parameters
pid_parameters = {
'position_kp': Parameter('position_kp', 2.0, 0.0, 10.0, 2.0, 0.1, "Position proportional gain", "", "Position Control"),
'position_ki': Parameter('position_ki', 0.1, 0.0, 5.0, 0.1, 0.01, "Position integral gain", "", "Position Control"),
'position_kd': Parameter('position_kd', 1.0, 0.0, 10.0, 1.0, 0.1, "Position derivative gain", "", "Position Control"),
'velocity_kp': Parameter('velocity_kp', 1.5, 0.0, 10.0, 1.5, 0.1, "Velocity proportional gain", "", "Velocity Control"),
'velocity_ki': Parameter('velocity_ki', 0.05, 0.0, 2.0, 0.05, 0.01, "Velocity integral gain", "", "Velocity Control"),
'velocity_kd': Parameter('velocity_kd', 0.8, 0.0, 5.0, 0.8, 0.1, "Velocity derivative gain", "", "Velocity Control"),
'attitude_kp': Parameter('attitude_kp', 3.0, 0.0, 15.0, 3.0, 0.2, "Attitude proportional gain", "", "Attitude Control"),
'attitude_ki': Parameter('attitude_ki', 0.2, 0.0, 3.0, 0.2, 0.05, "Attitude integral gain", "", "Attitude Control"),
'attitude_kd': Parameter('attitude_kd', 1.5, 0.0, 8.0, 1.5, 0.2, "Attitude derivative gain", "", "Attitude Control"),
}
pid_set = ParameterSet("PID Control", pid_parameters, "PID control parameters")
self.add_parameter_set(pid_set)
# L1 Adaptive Parameters
l1_parameters = {
'adaptation_rate': Parameter('adaptation_rate', 100.0, 10.0, 1000.0, 100.0, 10.0, "Adaptation rate", "Hz", "L1 Adaptive"),
'filter_bandwidth': Parameter('filter_bandwidth', 50.0, 10.0, 200.0, 50.0, 5.0, "L1 filter bandwidth", "Hz", "L1 Adaptive"),
'prediction_horizon': Parameter('prediction_horizon', 0.1, 0.01, 1.0, 0.1, 0.01, "Prediction horizon", "s", "L1 Adaptive"),
}
l1_set = ParameterSet("L1 Adaptive", l1_parameters, "L1 adaptive control parameters")
self.add_parameter_set(l1_set)
# MPC Parameters
mpc_parameters = {
'horizon_length': Parameter('horizon_length', 10, 5, 20, 10, 1, "Prediction horizon length", "", "MPC"),
'position_weight': Parameter('position_weight', 10.0, 1.0, 100.0, 10.0, 1.0, "Position tracking weight", "", "MPC"),
'control_weight': Parameter('control_weight', 0.1, 0.01, 1.0, 0.1, 0.01, "Control effort weight", "", "MPC"),
'max_iterations': Parameter('max_iterations', 50, 10, 200, 50, 10, "Maximum optimization iterations", "", "MPC"),
}
mpc_set = ParameterSet("MPC Control", mpc_parameters, "Model Predictive Control parameters")
self.add_parameter_set(mpc_set)
def add_parameter_set(self, parameter_set: ParameterSet):
"""
Add a parameter set to the tuner.
Args:
parameter_set (ParameterSet): Parameter set to add
"""
self.parameter_sets[parameter_set.name] = parameter_set
# Create tab for parameter set
tab = self._create_parameter_tab(parameter_set)
self.tab_widget.addTab(tab, parameter_set.name)
logger.info(f"Added parameter set: {parameter_set.name}")
def _create_parameter_tab(self, parameter_set: ParameterSet) -> QWidget:
"""Create a tab for a parameter set."""
tab = QWidget()
layout = QVBoxLayout(tab)
# Description
if parameter_set.description:
desc_label = QLabel(parameter_set.description)
desc_label.setStyleSheet("font-style: italic; color: gray;")
layout.addWidget(desc_label)
# Parameter controls
scroll_widget = QWidget()
scroll_layout = QVBoxLayout(scroll_widget)
# Group parameters by category
categories = {}
for param_name, param in parameter_set.parameters.items():
if param.category not in categories:
categories[param.category] = []
categories[param.category].append((param_name, param))
# Create controls for each category
self.parameter_widgets[parameter_set.name] = {}
for category, params in categories.items():
if category:
group_box = QGroupBox(category)
group_layout = QGridLayout(group_box)
else:
group_box = QWidget()
group_layout = QGridLayout(group_box)
for i, (param_name, param) in enumerate(params):
# Parameter label
label = QLabel(f"{param.name}:")
label.setToolTip(param.description)
group_layout.addWidget(label, i, 0)
# Value display
value_label = QLabel(f"{param.value:.3f}")
value_label.setMinimumWidth(80)
value_label.setAlignment(Qt.AlignRight)
group_layout.addWidget(value_label, i, 1)
# Unit label
if param.unit:
unit_label = QLabel(param.unit)
group_layout.addWidget(unit_label, i, 2)
# Slider
slider = QSlider(Qt.Horizontal)
slider.setMinimum(int(param.min_value / param.step_size))
slider.setMaximum(int(param.max_value / param.step_size))
slider.setValue(int(param.value / param.step_size))
slider.setTickPosition(QSlider.TicksBelow)
slider.setTickInterval(10)
# Connect slider to value update
slider.valueChanged.connect(
lambda value, name=param_name, set_name=parameter_set.name:
self._update_parameter_value(set_name, name, value * param.step_size)
)
group_layout.addWidget(slider, i, 3)
# Store widgets for later access
self.parameter_widgets[parameter_set.name][param_name] = {
'slider': slider,
'value_label': value_label
}
scroll_layout.addWidget(group_box)
layout.addWidget(scroll_widget)
return tab
def _update_parameter_value(self, set_name: str, param_name: str, value: float):
"""
Update parameter value.
Args:
set_name (str): Parameter set name
param_name (str): Parameter name
value (float): New parameter value
"""
if set_name in self.parameter_sets and param_name in self.parameter_sets[set_name].parameters:
param = self.parameter_sets[set_name].parameters[param_name]
# Validate value
value = max(param.min_value, min(param.max_value, value))
# Update parameter
param.value = value
param.last_modified = time.time()
# Update GUI
if set_name in self.parameter_widgets and param_name in self.parameter_widgets[set_name]:
widgets = self.parameter_widgets[set_name][param_name]
widgets['value_label'].setText(f"{value:.3f}")
widgets['slider'].setValue(int(value / param.step_size))
# Emit signal
self.parameter_changed.emit(set_name, param_name, value)
logger.debug(f"Updated parameter {set_name}.{param_name} = {value}")
def _update_performance(self):
"""Update performance visualization."""
# Simulate performance data (replace with actual performance metrics)
current_time = time.time()
# Generate simulated performance metrics
performance_metrics = {
'position_error': np.random.normal(0.1, 0.05),
'velocity_error': np.random.normal(0.05, 0.02),
'attitude_error': np.random.normal(0.02, 0.01),
'control_effort': np.random.normal(0.3, 0.1)
}
# Store performance history
self.performance_history.append({
'timestamp': current_time,
'metrics': performance_metrics
})
# Keep history manageable
if len(self.performance_history) > 1000:
self.performance_history.pop(0)
# Update plots
self._update_performance_plots()
def _update_performance_plots(self):
"""Update performance plots."""
if not self.performance_history:
return
# Clear plots
self.performance_ax.clear()
self.parameter_ax.clear()
# Extract data
timestamps = [entry['timestamp'] - self.performance_history[0]['timestamp']
for entry in self.performance_history]
# Performance metrics
position_errors = [entry['metrics']['position_error'] for entry in self.performance_history]
velocity_errors = [entry['metrics']['velocity_error'] for entry in self.performance_history]
attitude_errors = [entry['metrics']['attitude_error'] for entry in self.performance_history]
# Plot performance
self.performance_ax.plot(timestamps, position_errors, label='Position Error', color='red')
self.performance_ax.plot(timestamps, velocity_errors, label='Velocity Error', color='blue')
self.performance_ax.plot(timestamps, attitude_errors, label='Attitude Error', color='green')
self.performance_ax.set_title("Performance Metrics")
self.performance_ax.set_xlabel("Time (s)")
self.performance_ax.set_ylabel("Error")
self.performance_ax.legend()
self.performance_ax.grid(True)
# Plot parameter values (if any recent changes)
if self.parameter_sets:
# Plot a sample parameter
sample_set = list(self.parameter_sets.values())[0]
if sample_set.parameters:
sample_param = list(sample_set.parameters.values())[0]
param_values = [sample_param.value] * len(timestamps)
self.parameter_ax.plot(timestamps, param_values, label=sample_param.name, color='orange')
self.parameter_ax.set_title("Parameter Values")
self.parameter_ax.set_xlabel("Time (s)")
self.parameter_ax.set_ylabel("Value")
self.parameter_ax.legend()
self.parameter_ax.grid(True)
# Redraw
self.performance_canvas.draw()
def _load_parameters(self):
"""Load parameters from file."""
file_path, _ = QFileDialog.getOpenFileName(
self, "Load Parameters", "", "JSON Files (*.json);;All Files (*)"
)
if file_path:
try:
with open(file_path, 'r') as f:
data = json.load(f)
# Load parameter sets
for set_name, set_data in data.items():
parameters = {}
for param_name, param_data in set_data['parameters'].items():
param = Parameter(**param_data)
parameters[param_name] = param
param_set = ParameterSet(
name=set_name,
parameters=parameters,
description=set_data.get('description', ''),
last_modified=set_data.get('last_modified', time.time())
)
self.add_parameter_set(param_set)
QMessageBox.information(self, "Success", "Parameters loaded successfully!")
logger.info(f"Loaded parameters from {file_path}")
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to load parameters: {e}")
logger.error(f"Failed to load parameters: {e}")
def _save_parameters(self):
"""Save parameters to file."""
file_path, _ = QFileDialog.getSaveFileName(
self, "Save Parameters", "", "JSON Files (*.json);;All Files (*)"
)
if file_path:
try:
data = {}
for set_name, param_set in self.parameter_sets.items():
set_data = {
'description': param_set.description,
'last_modified': param_set.last_modified,
'parameters': {}
}
for param_name, param in param_set.parameters.items():
set_data['parameters'][param_name] = {
'name': param.name,
'value': param.value,
'min_value': param.min_value,
'max_value': param.max_value,
'default_value': param.default_value,
'step_size': param.step_size,
'description': param.description,
'unit': param.unit,
'category': param.category
}
data[set_name] = set_data
with open(file_path, 'w') as f:
json.dump(data, f, indent=2)
QMessageBox.information(self, "Success", "Parameters saved successfully!")
logger.info(f"Saved parameters to {file_path}")
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to save parameters: {e}")
logger.error(f"Failed to save parameters: {e}")
def _reset_parameters(self):
"""Reset parameters to default values."""
reply = QMessageBox.question(
self, "Reset Parameters",
"Are you sure you want to reset all parameters to default values?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
)
if reply == QMessageBox.Yes:
for set_name, param_set in self.parameter_sets.items():
for param_name, param in param_set.parameters.items():
self._update_parameter_value(set_name, param_name, param.default_value)
QMessageBox.information(self, "Success", "Parameters reset to defaults!")
logger.info("Parameters reset to default values")
def _apply_parameters(self):
"""Apply parameter changes to the control system."""
# This would typically send parameters to the control system
QMessageBox.information(self, "Success", "Parameters applied to control system!")
logger.info("Parameters applied to control system")
def _start_optimization(self):
"""Start parameter optimization."""
algorithm_name = self.algorithm_combo.currentText()
algorithm = OptimizationAlgorithm(algorithm_name.lower().replace(' ', '_'))
# Get current parameter set
current_tab = self.tab_widget.currentWidget()
if not current_tab:
QMessageBox.warning(self, "Warning", "Please select a parameter set first!")
return
# Start optimization in background thread
self.optimization_started.emit()
self.optimization_progress.setValue(0)
# Simulate optimization progress
for i in range(101):
self.optimization_progress.setValue(i)
time.sleep(0.01) # Simulate work
# Complete optimization
QMessageBox.information(self, "Success", f"Optimization completed using {algorithm_name}!")
self.optimization_completed.emit(None)
logger.info(f"Optimization completed using {algorithm_name}")
# Example usage
if __name__ == "__main__":
"""
Example usage of the parameter tuner.
This demonstrates how to set up and use the parameter tuner for
real-time control parameter adjustment.
"""
if not GUI_AVAILABLE:
print("PyQt5 not available. Install with: pip install PyQt5 matplotlib")
exit(1)
import sys
from PyQt5.QtWidgets import QApplication
# Create application
app = QApplication(sys.argv)
# Create parameter tuner
tuner = ParameterTunerGUI()
# Add callbacks
def parameter_changed(set_name, param_name, value):
"""Callback for parameter changes."""
print(f"Parameter changed: {set_name}.{param_name} = {value}")
def optimization_started():
"""Callback for optimization start."""
print("Optimization started")
def optimization_completed(result):
"""Callback for optimization completion."""
print("Optimization completed")
tuner.parameter_changed.connect(parameter_changed)
tuner.optimization_started.connect(optimization_started)
tuner.optimization_completed.connect(optimization_completed)
# Show GUI
tuner.show()
# Run application
sys.exit(app.exec_())
Artigos relacionados
real_time_controller.cpp
real_time_controller.cpp — cpp source code from the CrazyFly learning materials (CrazyFly/cpp/high_freq_control/real_time_controller.cpp).
Ler artigo →four_layer_pid.m
four_layer_pid.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/four_layer_pid.m).
Ler artigo →hybrid_controller.m
hybrid_controller.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/hybrid_controller.m).
Ler artigo →l1_adaptive_model.m
l1_adaptive_model.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/l1_adaptive_model.m).
Ler artigo →parameter_optimizer.m
parameter_optimizer.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/parameter_optimizer.m).
Ler artigo →performance_analyzer.m
performance_analyzer.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/performance_analyzer.m).
Ler artigo →