Add parameter selection

This commit is contained in:
Max Känner 2023-01-29 14:57:57 +01:00
parent ce2919580d
commit 63534c7e05
4 changed files with 151 additions and 16 deletions

43
Cargo.lock generated
View File

@ -209,6 +209,7 @@ dependencies = [
"imageproc", "imageproc",
"paste", "paste",
"pid", "pid",
"rand 0.8.5",
"rusttype", "rusttype",
"thiserror", "thiserror",
] ]
@ -357,7 +358,7 @@ dependencies = [
"itertools", "itertools",
"nalgebra", "nalgebra",
"num", "num",
"rand", "rand 0.7.3",
"rand_distr", "rand_distr",
"rayon", "rayon",
"rusttype", "rusttype",
@ -662,11 +663,22 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [ dependencies = [
"getrandom 0.1.16", "getrandom 0.1.16",
"libc", "libc",
"rand_chacha", "rand_chacha 0.2.2",
"rand_core", "rand_core 0.5.1",
"rand_hc", "rand_hc",
] ]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]] [[package]]
name = "rand_chacha" name = "rand_chacha"
version = "0.2.2" version = "0.2.2"
@ -674,7 +686,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core", "rand_core 0.5.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
] ]
[[package]] [[package]]
@ -686,13 +708,22 @@ dependencies = [
"getrandom 0.1.16", "getrandom 0.1.16",
] ]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.8",
]
[[package]] [[package]]
name = "rand_distr" name = "rand_distr"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
dependencies = [ dependencies = [
"rand", "rand 0.7.3",
] ]
[[package]] [[package]]
@ -701,7 +732,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [ dependencies = [
"rand_core", "rand_core 0.5.1",
] ]
[[package]] [[package]]

View File

@ -11,6 +11,7 @@ rusttype = "0.9"
paste = "1.0" paste = "1.0"
pid = "4.0" pid = "4.0"
thiserror = "1.0" thiserror = "1.0"
rand = "0.8"
[profile.release] [profile.release]
lto = true lto = true

View File

@ -143,6 +143,10 @@ fn draw_setting(
font: &Font, font: &Font,
) { ) {
let text_scale = Scale::uniform(screen.yres() as f32 / 4.0 - 8.0); 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; let x = screen.xres() as i32 / 8 + screen.xres() as i32 * i32::from(index) / 4;
draw_centered_text( draw_centered_text(
screen, screen,
@ -156,9 +160,9 @@ fn draw_setting(
screen, screen,
x, x,
screen.yres() as i32 * 5 / 8 + 4, screen.yres() as i32 * 5 / 8 + 4,
text_scale, value_scale,
font, font,
format!("{value}").as_str(), format!("{value:.2}").as_str(),
); );
let top_triangle = [ let top_triangle = [
Point::new(x, screen.yres() as i32 / 2), Point::new(x, screen.yres() as i32 / 2),

View File

@ -2,17 +2,17 @@ mod buttons;
mod display; mod display;
use buttons::SmartEv3Buttons; 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::{ use ev3dev_lang_rust::{
motors::{LargeMotor, MotorPort}, motors::{LargeMotor, MotorPort},
sensors::{ColorSensor, SensorPort}, sensors::{ColorSensor, SensorPort},
Ev3Error, Ev3Result, Screen, Ev3Error, Ev3Result, Screen,
}; };
use pid::Pid; use pid::Pid;
use rand::{thread_rng, Rng};
use rusttype::Font; use rusttype::Font;
use std::{ use std::{
error::Error, error::Error,
hint,
thread::sleep, thread::sleep,
time::{Duration, Instant}, 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 white = calibrate_gray(&mut screen, &sensor, &mut buttons, "Weiß", &font)?;
let setpoint = (black + white) / 2.0; 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); draw_driving(&mut screen, &font);
let result = follow_line( let result = follow_line(
@ -44,13 +46,13 @@ fn main() -> Result<(), Box<dyn Error>> {
&sensor, &sensor,
&mut buttons, &mut buttons,
setpoint, setpoint,
(0.3, 0.0, 0.0), (k_p / 10.0, k_i, k_d),
20, v,
); );
left_motor.stop().and(right_motor.stop())?; left_motor.stop().and(right_motor.stop())?;
let time = match result { let time = match result {
Ok(time) => time, Ok(time) => time,
Err(LineFollowError::UserAbort) => return Ok(()), Err(ProgramError::UserAbort) => return Ok(()),
e => e?, e => e?,
}; };
@ -63,6 +65,103 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(()) 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( fn calibrate_gray(
screen: &mut Screen, screen: &mut Screen,
sensor: &ColorSensor, sensor: &ColorSensor,
@ -81,7 +180,7 @@ fn calibrate_gray(
} }
#[derive(Error, Debug)] #[derive(Error, Debug)]
enum LineFollowError { enum ProgramError {
#[error("working with EV3 peripheral")] #[error("working with EV3 peripheral")]
Ev3(#[from] Ev3Error), Ev3(#[from] Ev3Error),
#[error("the user abortet the run")] #[error("the user abortet the run")]
@ -102,7 +201,7 @@ fn follow_line(
setpoint: f32, setpoint: f32,
(k_p, k_i, k_d): (f32, f32, f32), (k_p, k_i, k_d): (f32, f32, f32),
v: i32, v: i32,
) -> Result<Duration, LineFollowError> { ) -> Result<Duration, ProgramError> {
let mut controller = Pid::new(setpoint, f32::INFINITY); let mut controller = Pid::new(setpoint, f32::INFINITY);
controller controller
.p(k_p, f32::INFINITY) .p(k_p, f32::INFINITY)
@ -140,7 +239,7 @@ fn follow_line(
if let LineFollowState::Finish(time) = state { if let LineFollowState::Finish(time) = state {
Ok(time) Ok(time)
} else { } else {
Err(LineFollowError::UserAbort) Err(ProgramError::UserAbort)
} }
} }