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",
"paste",
"pid",
"rand 0.8.5",
"rusttype",
"thiserror",
]
@ -357,7 +358,7 @@ dependencies = [
"itertools",
"nalgebra",
"num",
"rand",
"rand 0.7.3",
"rand_distr",
"rayon",
"rusttype",
@ -662,11 +663,22 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom 0.1.16",
"libc",
"rand_chacha",
"rand_core",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"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]]
name = "rand_chacha"
version = "0.2.2"
@ -674,7 +686,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"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]]
@ -686,13 +708,22 @@ dependencies = [
"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]]
name = "rand_distr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
dependencies = [
"rand",
"rand 0.7.3",
]
[[package]]
@ -701,7 +732,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
"rand_core 0.5.1",
]
[[package]]

View File

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

View File

@ -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),

View File

@ -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)
}
}