begin implementing stick filter algorithms
This commit is contained in:
parent
5244f1a75e
commit
baa1ab1235
4 changed files with 218 additions and 48 deletions
82
src/filter.rs
Normal file
82
src/filter.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
use libm::{fmin, fminf};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
input::{ControllerConfig, Stick},
|
||||||
|
stick::FilterGains,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct WaveshapingValues {
|
||||||
|
pub old_x_pos: f32,
|
||||||
|
pub old_y_pos: f32,
|
||||||
|
pub old_x_vel: f32,
|
||||||
|
pub old_y_vel: f32,
|
||||||
|
pub old_x_out: f32,
|
||||||
|
pub old_y_out: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calc_waveshaping_mult(setting: u8) -> f32 {
|
||||||
|
if setting > 0 && setting <= 5 {
|
||||||
|
1. / (440. - 40. * setting as f32)
|
||||||
|
} else if setting > 5 && setting <= 15 {
|
||||||
|
1. / (340. - 20. * setting as f32)
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This simulates an idealized sort of pode:
|
||||||
|
///
|
||||||
|
/// if the stick is moving fast, it responds poorly, while
|
||||||
|
/// if the stick is moving slowly, it follows closely.
|
||||||
|
///
|
||||||
|
/// It's not suitable to be the sole filter, but when put after
|
||||||
|
/// the smart snapback filter, it should be able to hold the
|
||||||
|
/// output at the rim longer when released.
|
||||||
|
///
|
||||||
|
/// Output is a tuple of the x and y positions.
|
||||||
|
pub fn run_waveshaping(
|
||||||
|
x_pos: f32,
|
||||||
|
y_pos: f32,
|
||||||
|
which_stick: Stick,
|
||||||
|
waveshaping_values: &mut WaveshapingValues,
|
||||||
|
controller_config: &ControllerConfig,
|
||||||
|
filter_gains: &FilterGains,
|
||||||
|
) -> (f32, f32) {
|
||||||
|
let x_vel = x_pos - waveshaping_values.old_x_pos;
|
||||||
|
let y_vel = y_pos - waveshaping_values.old_y_pos;
|
||||||
|
|
||||||
|
let x_vel_smooth = 0.5 * (x_vel + waveshaping_values.old_x_vel);
|
||||||
|
let y_vel_smooth = 0.5 * (y_vel + waveshaping_values.old_y_vel);
|
||||||
|
|
||||||
|
let x_factor = calc_waveshaping_mult(match which_stick {
|
||||||
|
Stick::ControlStick => controller_config.ax_waveshaping,
|
||||||
|
Stick::CStick => controller_config.cx_waveshaping,
|
||||||
|
});
|
||||||
|
let y_factor = calc_waveshaping_mult(match which_stick {
|
||||||
|
Stick::ControlStick => controller_config.ay_waveshaping,
|
||||||
|
Stick::CStick => controller_config.cy_waveshaping,
|
||||||
|
});
|
||||||
|
|
||||||
|
let old_x_pos_weight = fminf(
|
||||||
|
1.,
|
||||||
|
x_vel_smooth * x_vel_smooth * filter_gains.vel_thresh * x_factor,
|
||||||
|
);
|
||||||
|
let new_x_pos_weight = 1. - old_x_pos_weight;
|
||||||
|
let old_y_pos_weight = fminf(
|
||||||
|
1.,
|
||||||
|
y_vel_smooth * y_vel_smooth * filter_gains.vel_thresh * y_factor,
|
||||||
|
);
|
||||||
|
let new_y_pos_weight = 1. - old_y_pos_weight;
|
||||||
|
|
||||||
|
let x_out = x_pos * new_x_pos_weight + waveshaping_values.old_x_out * old_x_pos_weight;
|
||||||
|
let y_out = y_pos * new_y_pos_weight + waveshaping_values.old_y_out * old_y_pos_weight;
|
||||||
|
|
||||||
|
waveshaping_values.old_x_pos = x_pos;
|
||||||
|
waveshaping_values.old_y_pos = y_pos;
|
||||||
|
waveshaping_values.old_x_vel = x_vel_smooth;
|
||||||
|
waveshaping_values.old_y_vel = y_vel_smooth;
|
||||||
|
waveshaping_values.old_x_out = x_out;
|
||||||
|
waveshaping_values.old_y_out = y_out;
|
||||||
|
|
||||||
|
(x_out, y_out)
|
||||||
|
}
|
106
src/input.rs
106
src/input.rs
|
@ -17,6 +17,7 @@ use embassy_time::{Instant, Timer};
|
||||||
use packed_struct::derive::PackedStruct;
|
use packed_struct::derive::PackedStruct;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
filter::{run_waveshaping, WaveshapingValues},
|
||||||
gcc_hid::GcReport,
|
gcc_hid::GcReport,
|
||||||
stick::{linearize, run_kalman, FilterGains, StickParams},
|
stick::{linearize, run_kalman, FilterGains, StickParams},
|
||||||
PackedFloat, ADDR_OFFSET, FLASH_SIZE,
|
PackedFloat, ADDR_OFFSET, FLASH_SIZE,
|
||||||
|
@ -31,14 +32,14 @@ static STICK_SIGNAL: Signal<CriticalSectionRawMutex, StickState> = Signal::new()
|
||||||
pub struct ControllerConfig {
|
pub struct ControllerConfig {
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(size_bits = "8")]
|
||||||
pub config_version: u8,
|
pub config_version: u8,
|
||||||
#[packed_field(size_bits = "32")]
|
#[packed_field(size_bits = "8")]
|
||||||
pub ax_waveshaping: PackedFloat,
|
pub ax_waveshaping: u8,
|
||||||
#[packed_field(size_bits = "32")]
|
#[packed_field(size_bits = "8")]
|
||||||
pub ay_waveshaping: PackedFloat,
|
pub ay_waveshaping: u8,
|
||||||
#[packed_field(size_bits = "32")]
|
#[packed_field(size_bits = "8")]
|
||||||
pub cx_waveshaping: PackedFloat,
|
pub cx_waveshaping: u8,
|
||||||
#[packed_field(size_bits = "32")]
|
#[packed_field(size_bits = "8")]
|
||||||
pub cy_waveshaping: PackedFloat,
|
pub cy_waveshaping: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StickState {
|
struct StickState {
|
||||||
|
@ -48,14 +49,36 @@ struct StickState {
|
||||||
cy: u8,
|
cy: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StickPositions {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
cx: f32,
|
||||||
|
cy: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RawStickValues {
|
||||||
|
ax_linearized: f32,
|
||||||
|
ay_linearized: f32,
|
||||||
|
cx_linearized: f32,
|
||||||
|
cy_linearized: f32,
|
||||||
|
ax_raw: f32,
|
||||||
|
ay_raw: f32,
|
||||||
|
cx_raw: f32,
|
||||||
|
cy_raw: f32,
|
||||||
|
ax_unfiltered: f32,
|
||||||
|
ay_unfiltered: f32,
|
||||||
|
cx_unfiltered: f32,
|
||||||
|
cy_unfiltered: f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
enum Stick {
|
pub enum Stick {
|
||||||
ControlStick,
|
ControlStick,
|
||||||
CStick,
|
CStick,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
enum StickAxis {
|
pub enum StickAxis {
|
||||||
XAxis,
|
XAxis,
|
||||||
YAxis,
|
YAxis,
|
||||||
}
|
}
|
||||||
|
@ -104,11 +127,14 @@ async fn update_stick_states<
|
||||||
mut spi: &mut Spi<'a, I, M>,
|
mut spi: &mut Spi<'a, I, M>,
|
||||||
mut spi_acs: &mut Output<'a, Acs>,
|
mut spi_acs: &mut Output<'a, Acs>,
|
||||||
mut spi_ccs: &mut Output<'a, Ccs>,
|
mut spi_ccs: &mut Output<'a, Ccs>,
|
||||||
adc_scale: f32,
|
|
||||||
controlstick_params: &StickParams,
|
controlstick_params: &StickParams,
|
||||||
cstick_params: &StickParams,
|
cstick_params: &StickParams,
|
||||||
controller_config: &ControllerConfig,
|
controller_config: &ControllerConfig,
|
||||||
filter_gains: &FilterGains,
|
filter_gains: &FilterGains,
|
||||||
|
controlstick_waveshaping_values: &mut WaveshapingValues,
|
||||||
|
cstick_waveshaping_values: &mut WaveshapingValues,
|
||||||
|
old_stick_pos: &mut StickPositions,
|
||||||
|
raw_stick_values: &mut RawStickValues,
|
||||||
) {
|
) {
|
||||||
let mut adc_count = 0u32;
|
let mut adc_count = 0u32;
|
||||||
let mut ax_sum = 0u32;
|
let mut ax_sum = 0u32;
|
||||||
|
@ -158,10 +184,15 @@ async fn update_stick_states<
|
||||||
|
|
||||||
timer.await;
|
timer.await;
|
||||||
|
|
||||||
let raw_controlstick_x = (ax_sum as f32) / (adc_count as f32) / 4096.0f32 * adc_scale;
|
let raw_controlstick_x = (ax_sum as f32) / (adc_count as f32) / 4096.0f32;
|
||||||
let raw_controlstick_y = (ay_sum as f32) / (adc_count as f32) / 4096.0f32 * adc_scale;
|
let raw_controlstick_y = (ay_sum as f32) / (adc_count as f32) / 4096.0f32;
|
||||||
let raw_cstick_x = (cx_sum as f32) / (adc_count as f32) / 4096.0f32 * adc_scale;
|
let raw_cstick_x = (cx_sum as f32) / (adc_count as f32) / 4096.0f32;
|
||||||
let raw_cstick_y = (cy_sum as f32) / (adc_count as f32) / 4096.0f32 * adc_scale;
|
let raw_cstick_y = (cy_sum as f32) / (adc_count as f32) / 4096.0f32;
|
||||||
|
|
||||||
|
raw_stick_values.ax_raw = raw_controlstick_x;
|
||||||
|
raw_stick_values.ay_raw = raw_controlstick_y;
|
||||||
|
raw_stick_values.cx_raw = raw_cstick_x;
|
||||||
|
raw_stick_values.cy_raw = raw_cstick_y;
|
||||||
|
|
||||||
let x_z = linearize(raw_controlstick_x, &controlstick_params.fit_coeffs_x);
|
let x_z = linearize(raw_controlstick_x, &controlstick_params.fit_coeffs_x);
|
||||||
let y_z = linearize(raw_controlstick_y, &controlstick_params.fit_coeffs_y);
|
let y_z = linearize(raw_controlstick_y, &controlstick_params.fit_coeffs_y);
|
||||||
|
@ -169,8 +200,53 @@ async fn update_stick_states<
|
||||||
let pos_cx = linearize(raw_cstick_x, &cstick_params.fit_coeffs_x);
|
let pos_cx = linearize(raw_cstick_x, &cstick_params.fit_coeffs_x);
|
||||||
let pos_cy = linearize(raw_cstick_y, &cstick_params.fit_coeffs_y);
|
let pos_cy = linearize(raw_cstick_y, &cstick_params.fit_coeffs_y);
|
||||||
|
|
||||||
|
raw_stick_values.ax_linearized = x_z;
|
||||||
|
raw_stick_values.ay_linearized = y_z;
|
||||||
|
raw_stick_values.cx_linearized = pos_cx;
|
||||||
|
raw_stick_values.cy_linearized = pos_cy;
|
||||||
|
|
||||||
let (x_pos_filt, y_pos_filt) = run_kalman(x_z, y_z, controller_config, filter_gains);
|
let (x_pos_filt, y_pos_filt) = run_kalman(x_z, y_z, controller_config, filter_gains);
|
||||||
|
|
||||||
|
let (shaped_x, shaped_y) = run_waveshaping(
|
||||||
|
x_pos_filt,
|
||||||
|
y_pos_filt,
|
||||||
|
Stick::ControlStick,
|
||||||
|
controlstick_waveshaping_values,
|
||||||
|
controller_config,
|
||||||
|
filter_gains,
|
||||||
|
);
|
||||||
|
|
||||||
|
let pos_x =
|
||||||
|
filter_gains.x_smoothing * shaped_x + (1.0 - filter_gains.x_smoothing) * old_stick_pos.x;
|
||||||
|
let pos_y =
|
||||||
|
filter_gains.y_smoothing * shaped_y + (1.0 - filter_gains.y_smoothing) * old_stick_pos.y;
|
||||||
|
old_stick_pos.x = pos_x;
|
||||||
|
old_stick_pos.y = pos_y;
|
||||||
|
|
||||||
|
let (shaped_cx, shaped_cy) = run_waveshaping(
|
||||||
|
pos_cx,
|
||||||
|
pos_cy,
|
||||||
|
Stick::CStick,
|
||||||
|
cstick_waveshaping_values,
|
||||||
|
controller_config,
|
||||||
|
filter_gains,
|
||||||
|
);
|
||||||
|
|
||||||
|
let old_cx_pos = old_stick_pos.cx;
|
||||||
|
let old_cy_pos = old_stick_pos.cy;
|
||||||
|
old_stick_pos.cx = shaped_cx;
|
||||||
|
old_stick_pos.cy = shaped_cy;
|
||||||
|
|
||||||
|
let x_weight_1 = filter_gains.c_xsmoothing;
|
||||||
|
let x_weight_2 = 1.0 - x_weight_1;
|
||||||
|
let y_weight_1 = filter_gains.c_ysmoothing;
|
||||||
|
let y_weight_2 = 1.0 - y_weight_1;
|
||||||
|
|
||||||
|
let pos_cx_filt = x_weight_1 * shaped_cx + x_weight_2 * old_cx_pos;
|
||||||
|
let pos_cy_filt = y_weight_1 * shaped_cy + y_weight_2 * old_cy_pos;
|
||||||
|
|
||||||
|
// phob optionally runs a median filter here, but we leave it for now
|
||||||
|
|
||||||
STICK_SIGNAL.signal(StickState {
|
STICK_SIGNAL.signal(StickState {
|
||||||
ax: 127,
|
ax: 127,
|
||||||
ay: 127,
|
ay: 127,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
mod filter;
|
||||||
mod gcc_hid;
|
mod gcc_hid;
|
||||||
mod input;
|
mod input;
|
||||||
mod stick;
|
mod stick;
|
||||||
|
|
77
src/stick.rs
77
src/stick.rs
|
@ -7,15 +7,15 @@ use crate::input::ControllerConfig;
|
||||||
|
|
||||||
/// fit order for the linearization
|
/// fit order for the linearization
|
||||||
const FIT_ORDER: usize = 3;
|
const FIT_ORDER: usize = 3;
|
||||||
const N_COEFFS: usize = FIT_ORDER + 1;
|
const NUM_COEFFS: usize = FIT_ORDER + 1;
|
||||||
const NO_OF_NOTCHES: usize = 16;
|
const NO_OF_NOTCHES: usize = 16;
|
||||||
const MAX_ORDER: usize = 20;
|
const MAX_ORDER: usize = 20;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Format)]
|
#[derive(Clone, Debug, Default, Format)]
|
||||||
pub struct StickParams {
|
pub struct StickParams {
|
||||||
// these are the linearization coefficients
|
// these are the linearization coefficients
|
||||||
pub fit_coeffs_x: [f32; N_COEFFS],
|
pub fit_coeffs_x: [f32; NUM_COEFFS],
|
||||||
pub fit_coeffs_y: [f32; N_COEFFS],
|
pub fit_coeffs_y: [f32; NUM_COEFFS],
|
||||||
|
|
||||||
// these are the notch remap parameters
|
// these are the notch remap parameters
|
||||||
pub affine_coeffs_x: [[f32; 16]; 4], // affine transformation coefficients for all regions of the stick
|
pub affine_coeffs_x: [[f32; 16]; 4], // affine transformation coefficients for all regions of the stick
|
||||||
|
@ -60,8 +60,8 @@ pub struct FilterGains {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
struct LinearizeCalibrationOutput {
|
struct LinearizeCalibrationOutput {
|
||||||
pub fit_coeffs_x: [f64; N_COEFFS],
|
pub fit_coeffs_x: [f64; NUM_COEFFS],
|
||||||
pub fit_coeffs_y: [f64; N_COEFFS],
|
pub fit_coeffs_y: [f64; NUM_COEFFS],
|
||||||
|
|
||||||
pub out_x: [f32; NO_OF_NOTCHES],
|
pub out_x: [f32; NO_OF_NOTCHES],
|
||||||
pub out_y: [f32; NO_OF_NOTCHES],
|
pub out_y: [f32; NO_OF_NOTCHES],
|
||||||
|
@ -76,12 +76,14 @@ pub fn run_kalman(
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate the power of a number
|
||||||
fn curve_fit_power(base: f64, exponent: u32) -> f64 {
|
fn curve_fit_power(base: f64, exponent: u32) -> f64 {
|
||||||
if exponent == 0 {
|
if exponent == 0 {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut val = base;
|
let mut val = base;
|
||||||
|
|
||||||
for _ in 1..exponent {
|
for _ in 1..exponent {
|
||||||
val *= base;
|
val *= base;
|
||||||
}
|
}
|
||||||
|
@ -89,6 +91,7 @@ fn curve_fit_power(base: f64, exponent: u32) -> f64 {
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Substitutes a column in a matrix with a vector
|
||||||
fn sub_col<const N: usize>(
|
fn sub_col<const N: usize>(
|
||||||
matrix: &[[f64; N]; N],
|
matrix: &[[f64; N]; N],
|
||||||
t: &[f64; MAX_ORDER],
|
t: &[f64; MAX_ORDER],
|
||||||
|
@ -96,24 +99,32 @@ fn sub_col<const N: usize>(
|
||||||
n: usize,
|
n: usize,
|
||||||
) -> [[f64; N]; N] {
|
) -> [[f64; N]; N] {
|
||||||
let mut m = *matrix;
|
let mut m = *matrix;
|
||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
m[i][col] = t[i];
|
m[i][col] = t[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate the determinant of a matrix
|
||||||
fn det<const N: usize>(matrix: &[[f64; N]; N]) -> f64 {
|
fn det<const N: usize>(matrix: &[[f64; N]; N]) -> f64 {
|
||||||
let sign = trianglize(matrix);
|
let sign = trianglize(matrix);
|
||||||
|
|
||||||
if sign == 0 {
|
if sign == 0 {
|
||||||
return 0.;
|
return 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut p = 1f64;
|
let mut p = 1f64;
|
||||||
|
|
||||||
for i in 0..N {
|
for i in 0..N {
|
||||||
p *= matrix[i][i];
|
p *= matrix[i][i];
|
||||||
}
|
}
|
||||||
|
|
||||||
p * (sign as f64)
|
p * (sign as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trianglize a matrix
|
||||||
fn trianglize<const N: usize>(matrix: &[[f64; N]; N]) -> i32 {
|
fn trianglize<const N: usize>(matrix: &[[f64; N]; N]) -> i32 {
|
||||||
let mut sign = 1;
|
let mut sign = 1;
|
||||||
let mut matrix = *matrix;
|
let mut matrix = *matrix;
|
||||||
|
@ -148,22 +159,22 @@ fn trianglize<const N: usize>(matrix: &[[f64; N]; N]) -> i32 {
|
||||||
sign
|
sign
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fit_curve<const N: usize, const NCoeffs: usize>(
|
fn fit_curve<const N: usize, const NCOEFFS: usize>(
|
||||||
order: i32,
|
order: i32,
|
||||||
px: &[f64; N],
|
px: &[f64; N],
|
||||||
py: &[f64; N],
|
py: &[f64; N],
|
||||||
) -> [f64; NCoeffs] {
|
) -> [f64; NCOEFFS] {
|
||||||
let mut coeffs = [0f64; NCoeffs];
|
let mut coeffs = [0f64; NCOEFFS];
|
||||||
|
|
||||||
if NCoeffs != (order + 1) as usize {
|
if NCOEFFS != (order + 1) as usize {
|
||||||
panic!(
|
panic!(
|
||||||
"Invalid coefficients length, expected {}, but got {}",
|
"Invalid coefficients length, expected {}, but got {}",
|
||||||
order + 1,
|
order + 1,
|
||||||
NCoeffs
|
NCOEFFS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if NCoeffs > MAX_ORDER || NCoeffs < 2 {
|
if NCOEFFS > MAX_ORDER || NCOEFFS < 2 {
|
||||||
panic!("Matrix size out of bounds");
|
panic!("Matrix size out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,27 +188,27 @@ fn fit_curve<const N: usize, const NCoeffs: usize>(
|
||||||
for i in 0..N {
|
for i in 0..N {
|
||||||
let x = px[i];
|
let x = px[i];
|
||||||
let y = py[i];
|
let y = py[i];
|
||||||
for j in 0..NCoeffs * 2 - 1 {
|
for j in 0..NCOEFFS * 2 - 1 {
|
||||||
s[j] += curve_fit_power(x, j as u32);
|
s[j] += curve_fit_power(x, j as u32);
|
||||||
}
|
}
|
||||||
for j in 0..NCoeffs {
|
for j in 0..NCOEFFS {
|
||||||
t[j] += y * curve_fit_power(x, j as u32);
|
t[j] += y * curve_fit_power(x, j as u32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Master matrix LHS of linear equation
|
//Master matrix LHS of linear equation
|
||||||
let mut matrix = [[0f64; NCoeffs]; NCoeffs];
|
let mut matrix = [[0f64; NCOEFFS]; NCOEFFS];
|
||||||
|
|
||||||
for i in 0..NCoeffs {
|
for i in 0..NCOEFFS {
|
||||||
for j in 0..NCoeffs {
|
for j in 0..NCOEFFS {
|
||||||
matrix[i][j] = s[i + j];
|
matrix[i][j] = s[i + j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let denom = det(&matrix);
|
let denom = det(&matrix);
|
||||||
|
|
||||||
for i in 0..NCoeffs {
|
for i in 0..NCOEFFS {
|
||||||
coeffs[NCoeffs - i - 1] = det(&sub_col(&matrix, &t, i, NCoeffs)) / denom;
|
coeffs[NCOEFFS - i - 1] = det(&sub_col(&matrix, &t, i, NCOEFFS)) / denom;
|
||||||
}
|
}
|
||||||
|
|
||||||
coeffs
|
coeffs
|
||||||
|
@ -218,27 +229,27 @@ pub fn linearize(point: f32, coefficients: &[f32; 4]) -> f32 {
|
||||||
///
|
///
|
||||||
/// Outputs:
|
/// Outputs:
|
||||||
/// linearization fit coefficients for X and Y
|
/// linearization fit coefficients for X and Y
|
||||||
pub fn linearize_calibration(in_x: [f32; 17], in_y: [f32; 17]) -> LinearizeCalibrationOutput {
|
pub fn linearize_calibration(in_x: &[f64; 17], in_y: &[f64; 17]) -> LinearizeCalibrationOutput {
|
||||||
let mut fit_points_x = [0f64; 5];
|
let mut fit_points_x = [0f64; 5];
|
||||||
let mut fit_points_y = [0f64; 5];
|
let mut fit_points_y = [0f64; 5];
|
||||||
|
|
||||||
fit_points_x[0] = in_x[8 + 1] as f64;
|
fit_points_x[0] = in_x[8 + 1];
|
||||||
fit_points_x[1] = (in_x[6 + 1] as f64 + in_x[10 + 1] as f64) / 2.0f64;
|
fit_points_x[1] = (in_x[6 + 1] + in_x[10 + 1]) / 2.0f64;
|
||||||
fit_points_x[2] = in_x[0] as f64;
|
fit_points_x[2] = in_x[0];
|
||||||
fit_points_x[3] = (in_x[2 + 1] as f64 + in_x[14 + 1] as f64) / 2.0f64;
|
fit_points_x[3] = (in_x[2 + 1] + in_x[14 + 1]) / 2.0f64;
|
||||||
fit_points_x[4] = in_x[0 + 1] as f64;
|
fit_points_x[4] = in_x[0 + 1];
|
||||||
|
|
||||||
fit_points_y[0] = in_y[12 + 1] as f64;
|
fit_points_y[0] = in_y[12 + 1];
|
||||||
fit_points_y[1] = (in_y[10 + 1] as f64 + in_y[14 + 1] as f64) / 2.0f64;
|
fit_points_y[1] = (in_y[10 + 1] + in_y[14 + 1]) / 2.0f64;
|
||||||
fit_points_y[2] = in_y[0] as f64;
|
fit_points_y[2] = in_y[0];
|
||||||
fit_points_y[3] = (in_y[6 + 1] as f64 + in_y[2 + 1] as f64) / 2.0f64;
|
fit_points_y[3] = (in_y[6 + 1] + in_y[2 + 1]) / 2.0f64;
|
||||||
fit_points_y[4] = in_y[4 + 1] as f64;
|
fit_points_y[4] = in_y[4 + 1];
|
||||||
|
|
||||||
let x_output: [f64; 5] = [27.5, 53.2537879754, 127.5, 201.7462120246, 227.5];
|
let x_output: [f64; 5] = [27.5, 53.2537879754, 127.5, 201.7462120246, 227.5];
|
||||||
let y_output: [f64; 5] = [27.5, 53.2537879754, 127.5, 201.7462120246, 227.5];
|
let y_output: [f64; 5] = [27.5, 53.2537879754, 127.5, 201.7462120246, 227.5];
|
||||||
|
|
||||||
let mut fit_coeffs_x = fit_curve::<5, N_COEFFS>(FIT_ORDER as i32, &fit_points_x, &x_output);
|
let mut fit_coeffs_x = fit_curve::<5, NUM_COEFFS>(FIT_ORDER as i32, &fit_points_x, &x_output);
|
||||||
let mut fit_coeffs_y = fit_curve::<5, N_COEFFS>(FIT_ORDER as i32, &fit_points_y, &y_output);
|
let mut fit_coeffs_y = fit_curve::<5, NUM_COEFFS>(FIT_ORDER as i32, &fit_points_y, &y_output);
|
||||||
|
|
||||||
let x_zero_error = linearize(fit_points_x[2] as f32, &fit_coeffs_x.map(|e| e as f32));
|
let x_zero_error = linearize(fit_points_x[2] as f32, &fit_coeffs_x.map(|e| e as f32));
|
||||||
let y_zero_error = linearize(fit_points_y[2] as f32, &fit_coeffs_y.map(|e| e as f32));
|
let y_zero_error = linearize(fit_points_y[2] as f32, &fit_coeffs_y.map(|e| e as f32));
|
||||||
|
@ -250,8 +261,8 @@ pub fn linearize_calibration(in_x: [f32; 17], in_y: [f32; 17]) -> LinearizeCalib
|
||||||
let mut out_y = [0f32; NO_OF_NOTCHES];
|
let mut out_y = [0f32; NO_OF_NOTCHES];
|
||||||
|
|
||||||
for i in 0..=NO_OF_NOTCHES {
|
for i in 0..=NO_OF_NOTCHES {
|
||||||
out_x[i] = linearize(in_x[i], &fit_coeffs_x.map(|e| e as f32));
|
out_x[i] = linearize(in_x[i] as f32, &fit_coeffs_x.map(|e| e as f32));
|
||||||
out_y[i] = linearize(in_y[i], &fit_coeffs_y.map(|e| e as f32));
|
out_y[i] = linearize(in_y[i] as f32, &fit_coeffs_y.map(|e| e as f32));
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearizeCalibrationOutput {
|
LinearizeCalibrationOutput {
|
||||||
|
|
Loading…
Reference in a new issue