Add parameter selection
This commit is contained in:
@ -143,6 +143,10 @@ fn draw_setting(
|
||||
font: &Font,
|
||||
) {
|
||||
let text_scale = Scale::uniform(screen.yres() as f32 / 4.0 - 8.0);
|
||||
let value_scale = Scale {
|
||||
x: screen.xres() as f32 / 10.0,
|
||||
y: screen.yres() as f32 / 4.0 - 8.0,
|
||||
};
|
||||
let x = screen.xres() as i32 / 8 + screen.xres() as i32 * i32::from(index) / 4;
|
||||
draw_centered_text(
|
||||
screen,
|
||||
@ -156,9 +160,9 @@ fn draw_setting(
|
||||
screen,
|
||||
x,
|
||||
screen.yres() as i32 * 5 / 8 + 4,
|
||||
text_scale,
|
||||
value_scale,
|
||||
font,
|
||||
format!("{value}").as_str(),
|
||||
format!("{value:.2}").as_str(),
|
||||
);
|
||||
let top_triangle = [
|
||||
Point::new(x, screen.yres() as i32 / 2),
|
||||
|
115
src/main.rs
115
src/main.rs
@ -2,17 +2,17 @@ mod buttons;
|
||||
mod display;
|
||||
|
||||
use buttons::SmartEv3Buttons;
|
||||
use display::{draw_calibration, draw_cycles, draw_driving, draw_finished, font};
|
||||
use display::{draw_calibration, draw_driving, draw_finished, draw_settings, font, Parameter};
|
||||
use ev3dev_lang_rust::{
|
||||
motors::{LargeMotor, MotorPort},
|
||||
sensors::{ColorSensor, SensorPort},
|
||||
Ev3Error, Ev3Result, Screen,
|
||||
};
|
||||
use pid::Pid;
|
||||
use rand::{thread_rng, Rng};
|
||||
use rusttype::Font;
|
||||
use std::{
|
||||
error::Error,
|
||||
hint,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
@ -37,6 +37,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
let white = calibrate_gray(&mut screen, &sensor, &mut buttons, "Weiß", &font)?;
|
||||
let setpoint = (black + white) / 2.0;
|
||||
|
||||
let (k_p, k_i, k_d, v) = select_values(&mut screen, &mut buttons, &font);
|
||||
|
||||
draw_driving(&mut screen, &font);
|
||||
|
||||
let result = follow_line(
|
||||
@ -44,13 +46,13 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
&sensor,
|
||||
&mut buttons,
|
||||
setpoint,
|
||||
(0.3, 0.0, 0.0),
|
||||
20,
|
||||
(k_p / 10.0, k_i, k_d),
|
||||
v,
|
||||
);
|
||||
left_motor.stop().and(right_motor.stop())?;
|
||||
let time = match result {
|
||||
Ok(time) => time,
|
||||
Err(LineFollowError::UserAbort) => return Ok(()),
|
||||
Err(ProgramError::UserAbort) => return Ok(()),
|
||||
e => e?,
|
||||
};
|
||||
|
||||
@ -63,6 +65,103 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn select_values(
|
||||
screen: &mut Screen,
|
||||
buttons: &mut SmartEv3Buttons,
|
||||
font: &Font,
|
||||
) -> (f32, f32, f32, i32) {
|
||||
use Parameter::{Kd, Ki, Kp, Speed};
|
||||
let mut k_p = thread_rng().gen_range(0.01..=10.0);
|
||||
let mut k_i = thread_rng().gen_range(0.01..=10.0);
|
||||
let mut k_d = thread_rng().gen_range(0.01..=10.0);
|
||||
let mut v = thread_rng().gen_range(1..=100);
|
||||
let mut selected = Kp;
|
||||
draw_settings(screen, k_p, k_i, k_d, v, selected, font);
|
||||
|
||||
loop {
|
||||
buttons.process();
|
||||
if buttons.is_enter_pressed() {
|
||||
break;
|
||||
}
|
||||
if buttons.is_right_pressed() {
|
||||
selected = match selected {
|
||||
Kp => Ki,
|
||||
Ki => Kd,
|
||||
Kd => Speed,
|
||||
Speed => Kp,
|
||||
};
|
||||
}
|
||||
if buttons.is_left_pressed() {
|
||||
selected = match selected {
|
||||
Kp => Speed,
|
||||
Ki => Kp,
|
||||
Kd => Ki,
|
||||
Speed => Kd,
|
||||
};
|
||||
}
|
||||
match selected {
|
||||
Speed => {
|
||||
if buttons.is_up() {
|
||||
v = (v + 1).min(100);
|
||||
}
|
||||
if buttons.is_down() {
|
||||
v = (v - 1).max(0);
|
||||
}
|
||||
}
|
||||
p => {
|
||||
let param = match p {
|
||||
Kp => &mut k_p,
|
||||
Ki => &mut k_i,
|
||||
Kd => &mut k_d,
|
||||
Speed => unreachable!(),
|
||||
};
|
||||
if buttons.is_up() {
|
||||
*param = (*param
|
||||
+ if buttons.is_up_pressed() {
|
||||
0.01f32
|
||||
} else {
|
||||
0.1f32
|
||||
})
|
||||
.min(99.99);
|
||||
}
|
||||
if buttons.is_down() {
|
||||
*param = (*param
|
||||
- if buttons.is_down_pressed() {
|
||||
0.01f32
|
||||
} else {
|
||||
0.1f32
|
||||
})
|
||||
.max(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if buttons.is_left_pressed()
|
||||
|| buttons.is_right_pressed()
|
||||
|| buttons.is_up()
|
||||
|| buttons.is_down()
|
||||
{
|
||||
draw_settings(screen, k_p, k_i, k_d, v, selected, font);
|
||||
}
|
||||
if buttons.is_up_pressed() || buttons.is_down_pressed() {
|
||||
sleep(Duration::from_millis(200));
|
||||
} else {
|
||||
sleep(Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
|
||||
(k_p, k_i, k_d, v)
|
||||
}
|
||||
|
||||
fn increase(parameter: &mut f32) {
|
||||
let change = 0.01;
|
||||
*parameter = (*parameter + change).min(99.99);
|
||||
}
|
||||
|
||||
fn decrease(parameter: &mut f32) {
|
||||
let change = 0.01;
|
||||
*parameter = (*parameter - change).max(0.0);
|
||||
}
|
||||
|
||||
fn calibrate_gray(
|
||||
screen: &mut Screen,
|
||||
sensor: &ColorSensor,
|
||||
@ -81,7 +180,7 @@ fn calibrate_gray(
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
enum LineFollowError {
|
||||
enum ProgramError {
|
||||
#[error("working with EV3 peripheral")]
|
||||
Ev3(#[from] Ev3Error),
|
||||
#[error("the user abortet the run")]
|
||||
@ -102,7 +201,7 @@ fn follow_line(
|
||||
setpoint: f32,
|
||||
(k_p, k_i, k_d): (f32, f32, f32),
|
||||
v: i32,
|
||||
) -> Result<Duration, LineFollowError> {
|
||||
) -> Result<Duration, ProgramError> {
|
||||
let mut controller = Pid::new(setpoint, f32::INFINITY);
|
||||
controller
|
||||
.p(k_p, f32::INFINITY)
|
||||
@ -140,7 +239,7 @@ fn follow_line(
|
||||
if let LineFollowState::Finish(time) = state {
|
||||
Ok(time)
|
||||
} else {
|
||||
Err(LineFollowError::UserAbort)
|
||||
Err(ProgramError::UserAbort)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user