From 0d2dcd6a6e10a512be208c2d7a0de6120b9ee0f7 Mon Sep 17 00:00:00 2001 From: Albin Heimerson <albin.heimerson@control.lth.se> Date: Tue, 10 Jan 2023 15:01:30 +0100 Subject: [PATCH] Add delay and gain to the TFs --- src/lib.rs | 27 ++++++++++++++++++--------- src/transfer_functions.rs | 26 ++++++++++++++++++++------ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 450dedf..caef9aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -148,8 +148,17 @@ mod pole_position_app { label, order: Order::First, display: Display::StepResponse, - fo: FirstOrderSystem { T: 1.0, T_lower: 0.1, T_upper: 500.0}, - so: SecondOrderSystem { d: 0.5, w: 0.75, d_lower: 0.01, d_upper: 5.0, w_lower: 0.01, w_upper: 5.0}, + fo: FirstOrderSystem { + T: 1.0, T_lower: 0.1, T_upper: 500.0, + K: 1.0, K_lower: -2.0, K_upper: 2.0, + L: 0.0, L_lower: 0.0, L_upper: 5.0, + }, + so: SecondOrderSystem { + d: 0.5, d_lower: 0.01, d_upper: 5.0, + w: 0.75, w_lower: 0.01, w_upper: 5.0, + K: 1.0, K_lower: -2.0, K_upper: 2.0, + L: 0.0, L_lower: 0.0, L_upper: 5.0, + }, pole_drag_offset: None, } } @@ -210,17 +219,17 @@ mod pole_position_app { fn parameter_sliders(&mut self, ui: &mut Ui) { match self.order { Order::First => { - ui.heading("G(s) = 1/(sT + 1)"); - ui.add( - egui::Slider::new(&mut self.fo.T, self.fo.T_lower..=self.fo.T_upper) - .text("T") - .logarithmic(true), - ); + ui.heading("G(s) = K * exp(-Ls) / (sT + 1)"); + ui.add(egui::Slider::new(&mut self.fo.T, self.fo.T_lower..=self.fo.T_upper).text("T").logarithmic(true)); + ui.add(egui::Slider::new(&mut self.fo.K, self.fo.K_lower..=self.fo.K_upper).text("K")); + ui.add(egui::Slider::new(&mut self.fo.L, self.fo.L_lower..=self.fo.L_upper).text("L")); } Order::Second => { - ui.heading("G(s) = ω^2/(s^2 + 2δωs + ω^2)"); + ui.heading("G(s) = K * exp(-Ls) * ω^2 / (s^2 + 2δωs + ω^2)"); ui.add(egui::Slider::new(&mut self.so.d, self.so.d_lower..=self.so.d_upper).text("δ")); ui.add(egui::Slider::new(&mut self.so.w, self.so.w_lower..=self.so.w_upper).text("ω")); + ui.add(egui::Slider::new(&mut self.so.K, self.so.K_lower..=self.so.K_upper).text("K")); + ui.add(egui::Slider::new(&mut self.so.L, self.so.L_lower..=self.so.L_upper).text("L")); } }; } diff --git a/src/transfer_functions.rs b/src/transfer_functions.rs index 4cf45f9..7ee69e8 100644 --- a/src/transfer_functions.rs +++ b/src/transfer_functions.rs @@ -14,8 +14,14 @@ pub struct FirstOrderSystem { // pole = -1/T // https://www.tutorialspoint.com/control_systems/control_systems_response_first_order.htm pub T: f64, + pub K: f64, + pub L: f64, pub T_lower: f64, pub T_upper: f64, + pub K_lower: f64, + pub K_upper: f64, + pub L_lower: f64, + pub L_upper: f64, } impl TransferFunction for FirstOrderSystem { @@ -24,7 +30,8 @@ impl TransferFunction for FirstOrderSystem { } fn step_response(&self, t: f64) -> f64 { - if t >= 0.0 { + let t = t - self.L; + self.K * if t >= 0.0 { 1.0 - (-t / self.T).exp() } else { 0.0 @@ -32,11 +39,11 @@ impl TransferFunction for FirstOrderSystem { } fn bode_amplitude(&self, w: f64) -> f64 { - 1.0 / (((w * self.T).powi(2) + 1.0).sqrt()) + self.K.abs() / (((w * self.T).powi(2) + 1.0).sqrt()) } fn bode_phase(&self, w: f64) -> f64 { - -(w * self.T).atan() + -self.L * w - (w * self.T).atan() } fn adjust_poles_to(&mut self, re: f64, _im: f64) { @@ -59,10 +66,16 @@ pub struct SecondOrderSystem { // https://www.tutorialspoint.com/control_systems/control_systems_response_second_order.htm pub d: f64, pub w: f64, + pub K: f64, + pub L: f64, pub d_lower: f64, pub d_upper: f64, pub w_lower: f64, pub w_upper: f64, + pub K_lower: f64, + pub K_upper: f64, + pub L_lower: f64, + pub L_upper: f64, } impl TransferFunction for SecondOrderSystem { @@ -88,12 +101,13 @@ impl TransferFunction for SecondOrderSystem { fn step_response(&self, t: f64) -> f64 { let (d, w) = (self.d, self.w); + let t = t - self.L; if t < 0.0 { return 0.0; } - if d == 0.0 { + self.K * if d == 0.0 { 1.0 - (w * t).cos() } else if (0.0 < d) && (d < 1.0) { let d_1_sqrt = (1.0 - d.powi(2)).sqrt(); @@ -111,7 +125,7 @@ impl TransferFunction for SecondOrderSystem { fn bode_amplitude(&self, w: f64) -> f64 { let (d, wp) = (self.d, self.w); - wp.powi(2) / ( ( (wp.powi(2) - w.powi(2)).powi(2) + (2f64*d*wp*w).powi(2) ).sqrt() ) + self.K.abs() * wp.powi(2) / (((wp.powi(2) - w.powi(2)).powi(2) + (2f64*d*wp*w).powi(2)).sqrt()) } fn bode_phase(&self, w: f64) -> f64 { @@ -119,7 +133,7 @@ impl TransferFunction for SecondOrderSystem { let (d, wp) = (self.d, self.w); - let ph = -( (2f64*d*wp*w)/(wp.powi(2) - w.powi(2)) ).atan(); + let ph = -self.L * w - (2.0*d*wp*w / (wp.powi(2) - w.powi(2))).atan(); if ph > 0.0 { ph - PI } else { -- GitLab