-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add process calibration and simulator app [WIP] #63
Draft
alexhermida
wants to merge
1
commit into
main
Choose a base branch
from
implementing-calibration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "line_sensor_simulator" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
process_calibration = { path = "../../libs/process_calibration" } | ||
|
||
rand = "0.8" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Line sensor simulator | ||
|
||
This apps simulates the calibration of the light sensor for implementing | ||
the calibration logic without the need of the hardware. | ||
|
||
Using the calibration process at `libs/process_calibration`. | ||
|
||
``` | ||
$ cargo xtask run app line_sensor_simulator | ||
Starting calibration simulation... | ||
Sample: [2750, 2750, 1450, 150, 150, 1450, 2750, 2750] | ||
Sample: [2750, 2750, 2750, 2750, 2750, 2750, 2750, 2750] | ||
Sample: [2750, 2750, 2750, 2750, 2750, 2750, 2750, 2750] | ||
Sample: [2750, 1450, 150, 150, 1450, 2750, 2750, 2750] | ||
Sample: [2750, 2750, 2750, 2750, 2750, 2750, 2750, 2750] | ||
Sample: [2750, 2750, 2750, 2750, 2750, 2750, 2750, 2750] | ||
Sample: [2750, 2750, 2750, 2750, 2750, 1450, 150, 150] | ||
Sample: [2750, 2750, 2750, 2750, 2750, 2750, 2750, 2750] | ||
Sample: [2750, 2750, 2750, 2750, 2750, 2750, 2750, 2750] | ||
Sample: [150, 150, 1450, 2750, 2750, 2750, 2750, 2750] | ||
|
||
Calibration results: | ||
Min values: [150, 150, 150, 150, 150, 1450, 150, 150] | ||
Max values: [2750, 2750, 2750, 2750, 2750, 2750, 2750, 2750] | ||
Thresholds: [1450, 1450, 1450, 1450, 1450, 2100, 1450, 1450] | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
mod simulator; | ||
|
||
use simulator::Simulator; | ||
|
||
use process_calibration::process_calibration; | ||
use std::time::{Duration, Instant}; | ||
use std::thread; | ||
|
||
|
||
fn main() { | ||
println!("Starting calibration simulation..."); | ||
let mut simulator = Simulator::new(); | ||
let mut samples = Vec::new(); | ||
let start = Instant::now(); | ||
|
||
while start.elapsed() < Duration::from_secs(10) { | ||
let t = start.elapsed().as_secs_f32(); | ||
simulator.x_pos = 50.0 + 20.0 * f32::sin(t * 2.0); | ||
|
||
let reading = simulator.simulate_sensor_position(); | ||
samples.push(reading.clone()); | ||
println!("Sample: {:?}", reading); | ||
|
||
thread::sleep(Duration::from_millis(500)); | ||
} | ||
|
||
match process_calibration(&samples, simulator::NUM_SENSORS) { | ||
Ok((min_values, max_values, thresholds)) => { | ||
println!("\nCalibration results:"); | ||
println!("Min values: {:?}", min_values); | ||
println!("Max values: {:?}", max_values); | ||
println!("Thresholds: {:?}", thresholds); | ||
}, | ||
Err(e) => { | ||
println!("Calibration failed: {:?}", e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use std::time::SystemTime; | ||
use rand::Rng; | ||
|
||
// Constants for simulation | ||
pub const NUM_SENSORS: usize = 8; | ||
pub const WHITE_VALUE: i32 = 2800; | ||
pub const BLACK_VALUE: i32 = 200; | ||
pub const TRANSITION_VALUE: i32 = 1500; | ||
pub const SAMPLE_TIME_MS: u64 = 500; | ||
|
||
/// Represents the line sensor simulator | ||
pub struct Simulator { | ||
/// Current X position of robot | ||
pub x_pos: f32, | ||
/// Position of the line center | ||
pub line_center: f32, | ||
/// Space between sensors in units | ||
sensor_spacing: f32, | ||
} | ||
|
||
impl Simulator { | ||
/// Creates a new simulator with default values | ||
pub fn new() -> Self { | ||
Self { | ||
x_pos: 50.0, | ||
line_center: 50.0, | ||
sensor_spacing: 2.0, | ||
} | ||
} | ||
|
||
/// Adds random noise to sensor readings | ||
fn add_noise(value: i32) -> i32 { | ||
let noise = rand::thread_rng().gen_range(-50..=50); | ||
(value + noise).clamp(0, 3000) | ||
} | ||
|
||
/// Simulates readings from all sensors | ||
pub fn simulate_sensor_position(&self) -> Vec<i32> { | ||
let mut readings = Vec::with_capacity(NUM_SENSORS); | ||
|
||
for i in 0..NUM_SENSORS { | ||
// Calculate position for each sensor | ||
let sensor_pos = self.x_pos + (i as f32 - NUM_SENSORS as f32/2.0) * self.sensor_spacing; | ||
let distance = (sensor_pos - self.line_center).abs(); | ||
|
||
// Determine sensor value based on distance from line | ||
let raw_value = if distance < 2.0 { | ||
BLACK_VALUE | ||
} else if distance < 4.0 { | ||
TRANSITION_VALUE | ||
} else { | ||
WHITE_VALUE | ||
}; | ||
|
||
readings.push(Self::add_noise(raw_value)); | ||
} | ||
|
||
readings | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_simulator_new() { | ||
let sim = Simulator::new(); | ||
assert_eq!(sim.x_pos, 50.0); | ||
assert_eq!(sim.line_center, 50.0); | ||
} | ||
|
||
#[test] | ||
fn test_sensor_readings() { | ||
let sim = Simulator::new(); | ||
let readings = sim.simulate_sensor_position(); | ||
assert_eq!(readings.len(), NUM_SENSORS); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[package] | ||
name = "process_calibration" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#[derive(Debug)] | ||
pub enum CalibrationError { | ||
InvalidSensorCount, | ||
EmptySamples, | ||
InconsistentSamples, | ||
} | ||
|
||
pub fn process_calibration(samples: &[Vec<i32>], num_sensors: usize) | ||
-> Result<(Vec<i32>, Vec<i32>, Vec<i32>), CalibrationError> { | ||
|
||
if samples.is_empty() { | ||
return Err(CalibrationError::EmptySamples); | ||
} | ||
|
||
if samples.iter().any(|s| s.len() != num_sensors) { | ||
return Err(CalibrationError::InconsistentSamples); | ||
} | ||
|
||
let mut min_values = vec![i32::MAX; num_sensors]; | ||
let mut max_values = vec![i32::MIN; num_sensors]; | ||
|
||
for sample in samples { | ||
for (i, &value) in sample.iter().enumerate() { | ||
min_values[i] = min_values[i].min(value); | ||
max_values[i] = max_values[i].max(value); | ||
} | ||
} | ||
|
||
let thresholds: Vec<i32> = min_values.iter() | ||
.zip(max_values.iter()) | ||
.map(|(&min, &max)| (min + max) / 2) | ||
.collect(); | ||
|
||
Ok((min_values, max_values, thresholds)) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_valid_calibration() { | ||
let samples = vec![ | ||
vec![100, 200], | ||
vec![150, 250], | ||
]; | ||
let result = process_calibration(&samples, 2).unwrap(); | ||
assert_eq!(result.0, vec![100, 200]); // min | ||
assert_eq!(result.1, vec![150, 250]); // max | ||
assert_eq!(result.2, vec![125, 225]); // thresholds | ||
} | ||
|
||
#[test] | ||
fn test_empty_samples() { | ||
let samples: Vec<Vec<i32>> = vec![]; | ||
assert!(matches!( | ||
process_calibration(&samples, 2), | ||
Err(CalibrationError::EmptySamples) | ||
)); | ||
} | ||
|
||
#[test] | ||
fn test_inconsistent_samples() { | ||
let samples = vec![ | ||
vec![100, 200], | ||
vec![150], | ||
]; | ||
assert!(matches!( | ||
process_calibration(&samples, 2), | ||
Err(CalibrationError::InconsistentSamples) | ||
)); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it in Python first, I guess this looks like a port to Rust 🙈