Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
I
Interactive model comparison
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Albin Heimerson
Interactive model comparison
Commits
efd5770a
Commit
efd5770a
authored
Nov 30, 2022
by
Martin Morin
Browse files
Options
Downloads
Patches
Plain Diff
Add basic pole plot
parent
6f5760d2
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
assets/favicon.ico
+0
-0
0 additions, 0 deletions
assets/favicon.ico
src/lib.rs
+221
-17
221 additions, 17 deletions
src/lib.rs
with
221 additions
and
17 deletions
assets/favicon.ico
100644 → 100755
+
0
−
0
View file @
efd5770a
File mode changed from 100644 to 100755
This diff is collapsed.
Click to expand it.
src/lib.rs
+
221
−
17
View file @
efd5770a
#![warn(clippy::all,
rust_2018_idioms)]
#![allow(non_snake_case)]
#[allow(unused_imports)]
use
basic_print
::
basic_print
;
// basic print for print-debugging
...
...
@@ -21,15 +22,12 @@ impl ControlApp {
// `cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
let
apps
:
Vec
<
Box
<
dyn
CentralApp
>>
=
vec!
[
Box
::
new
(
PolePos
{
label
:
"Pole Positioning"
.to_string
(),
}),
Box
::
new
(
FreqResp
{
label
:
"Frequency Response"
.to_string
(),
}),
Box
::
new
(
PolePos
::
new
(
"Pole Positioning"
.to_string
()
)),
Box
::
new
(
FreqResp
::
new
(
"Frequency Response"
.to_string
()
)),
];
ControlApp
{
cur_app_idx
:
None
,
apps
}
// ControlApp{cur_app_idx: None, apps }
ControlApp
{
cur_app_idx
:
Some
(
0
),
apps
}
}
...
...
@@ -56,7 +54,7 @@ impl ControlApp {
}
ui
.with_layout
(
egui
::
Layout
::
right_to_left
(
egui
::
Align
::
Center
),
|
ui
|
{
ui
.with_layout
(
Layout
::
right_to_left
(
egui
::
Align
::
Center
),
|
ui
|
{
#[cfg(not(target_arch
=
"wasm32"
))]
// no quit on web pages!
{
if
ui
.button
(
"Quit"
)
.clicked
()
{
...
...
@@ -74,7 +72,6 @@ impl ControlApp {
}
impl
eframe
::
App
for
ControlApp
{
fn
update
(
&
mut
self
,
ctx
:
&
egui
::
Context
,
_frame
:
&
mut
eframe
::
Frame
)
{
...
...
@@ -86,26 +83,205 @@ impl eframe::App for ControlApp {
});
egui
::
CentralPanel
::
default
()
.show
(
ctx
,
|
ui
|
{
ui
.centered_and_justified
(
|
ui
|
{
match
self
.cur_app_idx
{
None
=>
{
ui
.label
(
"Select an application in the bar above."
);},
None
=>
{
ui
.centered_and_justified
(|
ui
|
{
ui
.label
(
"Select an application in the bar above."
);
});
},
Some
(
idx
)
=>
{
self
.apps
[
idx
]
.draw_app
(
ui
);},
};
});
});
}
}
use
egui
::
plot
::{
Line
,
LineStyle
,
Plot
,
PlotPoints
,
Points
,
MarkerShape
,
};
use
egui
::{
Color32
,
Vec2
,
Layout
,
InnerResponse
,
};
use
std
::
f64
::
consts
::
PI
;
struct
PolePos
{
label
:
String
,
// first order system 1/(sT + 1)
// pole = -1/T
// https://www.tutorialspoint.com/control_systems/control_systems_response_first_order.htm
T
:
f64
,
// second order system w^2/(s^2 + 2dw s + w^2)
// poles = -dw +- w sqrt(d^2 - 1)
// https://www.tutorialspoint.com/control_systems/control_systems_response_second_order.htm
d
:
f64
,
w
:
f64
,
order
:
Order
,
}
#[allow(dead_code)]
#[derive(PartialEq)]
enum
Order
{
First
,
Second
,
}
impl
PolePos
{
fn
new
(
label
:
String
)
->
PolePos
{
PolePos
{
label
,
T
:
1.0
,
d
:
0.5
,
w
:
1.0
,
order
:
Order
::
First
,
}
}
fn
step_resp_line
(
&
self
,
t_end
:
f64
,
n_steps
:
usize
)
->
Line
{
let
(
T
,
d
,
w
)
=
(
self
.T
,
self
.d
,
self
.w
);
let
f_first
=
move
|
t
:
f64
|
1.0
-
(
-
t
/
T
)
.exp
();
let
f_second
=
move
|
t
:
f64
|
{
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
();
let
th
=
d_1_sqrt
.asin
();
1.0
-
(
(
-
w
*
t
)
.exp
()
)
*
(
(
w
*
t
+
th
)
.sin
()
)
/
d_1_sqrt
}
else
if
d
==
1.0
{
1.0
-
(
(
-
w
*
t
)
.exp
()
)
*
(
1.0
+
w
*
t
)
}
else
{
let
d_1_sqrt
=
(
d
.powi
(
2
)
-
1.0
)
.sqrt
();
1.0
+
(
-
t
*
w
*
(
d
+
d_1_sqrt
))
.exp
()
/
(
2.0
*
(
d
+
d_1_sqrt
)
*
d_1_sqrt
)
-
(
-
t
*
w
*
(
d
-
d_1_sqrt
))
.exp
()
/
(
2.0
*
(
d
-
d_1_sqrt
)
*
d_1_sqrt
)
}
};
match
self
.order
{
Order
::
First
=>
Line
::
new
(
PlotPoints
::
from_explicit_callback
(
f_first
,
0.0
..
t_end
,
n_steps
)),
Order
::
Second
=>
Line
::
new
(
PlotPoints
::
from_explicit_callback
(
f_second
,
0.0
..
t_end
,
n_steps
)),
}
}
// fn bode_amp_line(&self, w_start: f64, w_end: f64, n_steps: usize) -> Line {
// Line::new(PlotPoints::from_explicit_callback(|_w| 1.0, w_start..w_end, n_steps))
// }
// fn bode_phase_line(&self, w_start: f64, w_end: f64, n_steps: usize) -> Line {
// Line::new(PlotPoints::from_explicit_callback(|_w| 0.0, w_start..w_end, n_steps))
// }
fn
poles
(
&
self
)
->
Vec
<
[
f64
;
2
]
>
{
let
(
T
,
d
,
w
)
=
(
self
.T
,
self
.d
,
self
.w
);
match
self
.order
{
Order
::
First
=>
vec!
[[
-
1.0
/
T
,
0.0
]],
Order
::
Second
=>
{
if
d
==
0.0
{
vec!
[
[
0.0
,
w
],
[
0.0
,
-
w
],
]
}
else
if
(
0.0
<
d
)
&&
(
d
<
1.0
)
{
vec!
[
[
-
d
*
w
,
(
1.0
-
d
.powi
(
2
))
.sqrt
()
*
w
],
[
-
d
*
w
,
-
(
1.0
-
d
.powi
(
2
))
.sqrt
()
*
w
],
]
}
else
if
d
==
1.0
{
vec!
[
[
-
w
,
0.0
],
[
-
w
,
0.0
],
]
}
else
{
vec!
[
[
-
d
*
w
+
(
d
.powi
(
2
)
-
1.0
)
.sqrt
()
*
w
,
0.0
],
[
-
d
*
w
-
(
d
.powi
(
2
)
-
1.0
)
.sqrt
()
*
w
,
0.0
],
]
}
}
}
}
fn
pole_markers
(
&
self
)
->
Points
{
Points
::
new
(
self
.poles
())
.shape
(
MarkerShape
::
Cross
)
}
// fn create_dummy_plot(&mut self, ui: &mut egui::Ui) {
// let sr_line =
// self.step_resp_line(10.0, 100)
// .color(Color32::from_rgb(200, 100, 100))
// .style(LineStyle::Solid)
// .name("Step Response");
// let sr_plot =
// fixed_plot("step_response")
// .set_margin_fraction(Vec2::new(0.05,0.05)) ;
// sr_plot.show(ui, |plot_ui| plot_ui.line(sr_line) );
// }
}
impl
CentralApp
for
PolePos
{
fn
draw_app
(
&
mut
self
,
ui
:
&
mut
egui
::
Ui
)
{
ui
.label
(
"In app, Pole Pos"
);
let
Vec2
{
x
,
y
}
=
ui
.available_size
();
ui
.heading
(
"Select System Order"
);
ui
.radio_value
(
&
mut
self
.order
,
Order
::
First
,
"First order"
);
ui
.radio_value
(
&
mut
self
.order
,
Order
::
Second
,
"Second order"
);
ui
.separator
();
match
self
.order
{
Order
::
First
=>
{
ui
.heading
(
"G(s) = 1/(sT - 1)"
);
ui
.add
(
egui
::
Slider
::
new
(
&
mut
self
.T
,
0.2
..=
10.0
)
.text
(
"T"
)
.logarithmic
(
true
)
);
ui
.add_visible
(
false
,
egui
::
Slider
::
new
(
&
mut
self
.T
,
0.2
..=
10.0
));
},
Order
::
Second
=>
{
ui
.heading
(
"G(s) = ω^2/(s^2 + 2δωs+ ω^2)"
);
ui
.add
(
egui
::
Slider
::
new
(
&
mut
self
.d
,
0.0
..=
1.5
)
.text
(
"δ"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
self
.w
,
0.0
..=
2.0
)
.text
(
"ω"
));
},
};
ui
.separator
();
ui
.separator
();
let
mut
plot
=
fixed_plot
(
"pole_plot"
,
y
/
2.0
,
y
/
2.0
);
let
InnerResponse
{
response
,
inner
:
drag_delta
}
=
plot
.show
(
ui
,|
plot_ui
|
{
plot_ui
.line
(
unit_circle
()
.color
(
Color32
::
GRAY
)
);
plot_ui
.points
(
self
.pole_markers
()
.color
(
Color32
::
BLACK
)
.radius
(
10.0
)
);
plot_ui
.pointer_coordinate_drag_delta
()
});
ui
.label
(
format!
(
"{:?}"
,
drag_delta
));
}
fn
get_label
(
&
self
)
->
&
str
{
...
...
@@ -114,12 +290,40 @@ impl CentralApp for PolePos {
}
fn
fixed_plot
(
id
:
&
str
,
width
:
f32
,
height
:
f32
)
->
Plot
{
Plot
::
new
(
id
)
.allow_scroll
(
false
)
.allow_zoom
(
false
)
.allow_boxed_zoom
(
false
)
.allow_drag
(
false
)
.show_x
(
false
)
.show_y
(
false
)
.width
(
width
)
.height
(
height
)
}
fn
unit_circle
()
->
Line
{
Line
::
new
(
PlotPoints
::
from_parametric_callback
(|
t
|
(
t
.sin
(),
t
.cos
()),
0.0
..
(
2.0
*
PI
),
100
))
}
struct
FreqResp
{
label
:
String
,
}
impl
FreqResp
{
fn
new
(
label
:
String
)
->
FreqResp
{
FreqResp
{
label
,
}
}
}
impl
CentralApp
for
FreqResp
{
fn
draw_app
(
&
mut
self
,
ui
:
&
mut
egui
::
Ui
)
{
ui
.label
(
"Frequency response app currently not implemented."
);
...
...
@@ -148,7 +352,7 @@ impl CentralApp for FreqResp {
// *value += 1.0;
// }
// ui.with_layout(
egui::
Layout::bottom_up(egui::Align::LEFT), |ui| {
// ui.with_layout(Layout::bottom_up(egui::Align::LEFT), |ui| {
// ui.horizontal(|ui| {
// ui.spacing_mut().item_spacing.x = 0.0;
// ui.label("powered by ");
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment