pub struct TipController { /* private fields */ }Expand description
Enhanced tip controller with pulse voltage stepping
Implementations§
Source§impl TipController
impl TipController
Sourcepub fn new(
driver: ActionDriver,
signal_index: SignalIndex,
pulse_voltage: f32,
bound: (f32, f32),
) -> Self
pub fn new( driver: ActionDriver, signal_index: SignalIndex, pulse_voltage: f32, bound: (f32, f32), ) -> Self
Create new tip controller with basic signal bounds
Examples found in repository?
16fn main() -> Result<(), Box<dyn std::error::Error>> {
17 env_logger::init();
18
19 // Create ActionDriver
20 let driver = ActionDriver::new("127.0.0.1", 6501)?;
21
22 // Create controller with custom pulse stepping parameters
23 let mut custom_controller = TipController::new(driver, SignalIndex(76), 2.0, (-2.0, 0.0));
24
25 let file_path = create_log_file_path()?;
26 println!("{file_path:?}");
27
28 // Configure custom pulse stepping parameters with dynamic threshold
29 custom_controller
30 //.set_pulse_stepping(1.5, Box::new(|signal| signal.abs() / 10.0), 4, 8.0)
31 .set_pulse_stepping_fixed(1.5, 2.0, 4, 10.0)
32 .set_stability_threshold(5)
33 .with_logger(Logger::new(file_path, 5));
34
35 // Create atomic flag for graceful shutdown
36 let running = Arc::new(AtomicBool::new(true));
37 let running_clone = Arc::clone(&running);
38
39 // Wrap controller in Arc<Mutex<>> for signal handler
40 let controller = Arc::new(Mutex::new(custom_controller));
41 let controller_clone = Arc::clone(&controller);
42
43 // Set up Ctrl-C handler to flush logger and signal stop
44 ctrlc::set_handler(move || {
45 info!("Received Ctrl-C, signaling stop and flushing logger...");
46 running_clone.store(false, Ordering::SeqCst);
47
48 if let Ok(mut ctrl) = controller_clone.lock() {
49 // Force flush the logger
50 match ctrl.flush_logger() {
51 Ok(()) => info!("Logger flushed successfully on exit"),
52 Err(e) => info!("Failed to flush logger on exit: {}", e),
53 }
54 }
55 })?;
56
57 // Run control loop with periodic checks for the stop signal
58 let result: Result<(), Box<dyn std::error::Error>> = {
59 let mut ctrl = controller.lock().unwrap();
60
61 // Run in shorter intervals so we can check the stop signal
62 let mut total_elapsed = Duration::from_secs(0);
63 let max_duration = Duration::from_secs(1000);
64 let check_interval = Duration::from_secs(5);
65
66 while total_elapsed < max_duration && running.load(Ordering::SeqCst) {
67 let remaining = max_duration - total_elapsed;
68 let run_duration = check_interval.min(remaining);
69
70 match ctrl.run(run_duration) {
71 Ok(final_state) => {
72 info!("Controller finished with state: {:?}", final_state);
73 break;
74 }
75 Err(e) if e.to_string().contains("Loop timeout") => {
76 // Expected timeout, continue if still running
77 total_elapsed += run_duration;
78 if !running.load(Ordering::SeqCst) {
79 info!("Stop signal received, exiting gracefully");
80 break;
81 }
82 }
83 Err(e) => {
84 info!("Controller failed: {}", e);
85 break;
86 }
87 }
88 }
89
90 Ok(())
91 };
92
93 match result {
94 Ok(()) => {
95 info!("Controller loop completed");
96 }
97 Err(e) => {
98 info!("Controller loop failed: {}", e);
99 }
100 }
101
102 Ok(())
103}Sourcepub fn set_pulse_stepping(
&mut self,
pulse_step: f32,
change_threshold: Box<dyn Fn(f32) -> f32 + Send + Sync>,
cycles_before_step: u32,
max_pulse: f32,
) -> &mut Self
pub fn set_pulse_stepping( &mut self, pulse_step: f32, change_threshold: Box<dyn Fn(f32) -> f32 + Send + Sync>, cycles_before_step: u32, max_pulse: f32, ) -> &mut Self
Set pulse stepping parameters with closure-based threshold
Sourcepub fn set_pulse_stepping_fixed(
&mut self,
pulse_step: f32,
change_threshold: f32,
cycles_before_step: u32,
max_pulse: f32,
) -> &mut Self
pub fn set_pulse_stepping_fixed( &mut self, pulse_step: f32, change_threshold: f32, cycles_before_step: u32, max_pulse: f32, ) -> &mut Self
Set pulse stepping parameters with fixed threshold (convenience method)
Examples found in repository?
16fn main() -> Result<(), Box<dyn std::error::Error>> {
17 env_logger::init();
18
19 // Create ActionDriver
20 let driver = ActionDriver::new("127.0.0.1", 6501)?;
21
22 // Create controller with custom pulse stepping parameters
23 let mut custom_controller = TipController::new(driver, SignalIndex(76), 2.0, (-2.0, 0.0));
24
25 let file_path = create_log_file_path()?;
26 println!("{file_path:?}");
27
28 // Configure custom pulse stepping parameters with dynamic threshold
29 custom_controller
30 //.set_pulse_stepping(1.5, Box::new(|signal| signal.abs() / 10.0), 4, 8.0)
31 .set_pulse_stepping_fixed(1.5, 2.0, 4, 10.0)
32 .set_stability_threshold(5)
33 .with_logger(Logger::new(file_path, 5));
34
35 // Create atomic flag for graceful shutdown
36 let running = Arc::new(AtomicBool::new(true));
37 let running_clone = Arc::clone(&running);
38
39 // Wrap controller in Arc<Mutex<>> for signal handler
40 let controller = Arc::new(Mutex::new(custom_controller));
41 let controller_clone = Arc::clone(&controller);
42
43 // Set up Ctrl-C handler to flush logger and signal stop
44 ctrlc::set_handler(move || {
45 info!("Received Ctrl-C, signaling stop and flushing logger...");
46 running_clone.store(false, Ordering::SeqCst);
47
48 if let Ok(mut ctrl) = controller_clone.lock() {
49 // Force flush the logger
50 match ctrl.flush_logger() {
51 Ok(()) => info!("Logger flushed successfully on exit"),
52 Err(e) => info!("Failed to flush logger on exit: {}", e),
53 }
54 }
55 })?;
56
57 // Run control loop with periodic checks for the stop signal
58 let result: Result<(), Box<dyn std::error::Error>> = {
59 let mut ctrl = controller.lock().unwrap();
60
61 // Run in shorter intervals so we can check the stop signal
62 let mut total_elapsed = Duration::from_secs(0);
63 let max_duration = Duration::from_secs(1000);
64 let check_interval = Duration::from_secs(5);
65
66 while total_elapsed < max_duration && running.load(Ordering::SeqCst) {
67 let remaining = max_duration - total_elapsed;
68 let run_duration = check_interval.min(remaining);
69
70 match ctrl.run(run_duration) {
71 Ok(final_state) => {
72 info!("Controller finished with state: {:?}", final_state);
73 break;
74 }
75 Err(e) if e.to_string().contains("Loop timeout") => {
76 // Expected timeout, continue if still running
77 total_elapsed += run_duration;
78 if !running.load(Ordering::SeqCst) {
79 info!("Stop signal received, exiting gracefully");
80 break;
81 }
82 }
83 Err(e) => {
84 info!("Controller failed: {}", e);
85 break;
86 }
87 }
88 }
89
90 Ok(())
91 };
92
93 match result {
94 Ok(()) => {
95 info!("Controller loop completed");
96 }
97 Err(e) => {
98 info!("Controller loop failed: {}", e);
99 }
100 }
101
102 Ok(())
103}Sourcepub fn with_logger(&mut self, logger: Logger<LogLine>) -> &mut Self
pub fn with_logger(&mut self, logger: Logger<LogLine>) -> &mut Self
Provide Json File logger for inspecting behavior
Examples found in repository?
16fn main() -> Result<(), Box<dyn std::error::Error>> {
17 env_logger::init();
18
19 // Create ActionDriver
20 let driver = ActionDriver::new("127.0.0.1", 6501)?;
21
22 // Create controller with custom pulse stepping parameters
23 let mut custom_controller = TipController::new(driver, SignalIndex(76), 2.0, (-2.0, 0.0));
24
25 let file_path = create_log_file_path()?;
26 println!("{file_path:?}");
27
28 // Configure custom pulse stepping parameters with dynamic threshold
29 custom_controller
30 //.set_pulse_stepping(1.5, Box::new(|signal| signal.abs() / 10.0), 4, 8.0)
31 .set_pulse_stepping_fixed(1.5, 2.0, 4, 10.0)
32 .set_stability_threshold(5)
33 .with_logger(Logger::new(file_path, 5));
34
35 // Create atomic flag for graceful shutdown
36 let running = Arc::new(AtomicBool::new(true));
37 let running_clone = Arc::clone(&running);
38
39 // Wrap controller in Arc<Mutex<>> for signal handler
40 let controller = Arc::new(Mutex::new(custom_controller));
41 let controller_clone = Arc::clone(&controller);
42
43 // Set up Ctrl-C handler to flush logger and signal stop
44 ctrlc::set_handler(move || {
45 info!("Received Ctrl-C, signaling stop and flushing logger...");
46 running_clone.store(false, Ordering::SeqCst);
47
48 if let Ok(mut ctrl) = controller_clone.lock() {
49 // Force flush the logger
50 match ctrl.flush_logger() {
51 Ok(()) => info!("Logger flushed successfully on exit"),
52 Err(e) => info!("Failed to flush logger on exit: {}", e),
53 }
54 }
55 })?;
56
57 // Run control loop with periodic checks for the stop signal
58 let result: Result<(), Box<dyn std::error::Error>> = {
59 let mut ctrl = controller.lock().unwrap();
60
61 // Run in shorter intervals so we can check the stop signal
62 let mut total_elapsed = Duration::from_secs(0);
63 let max_duration = Duration::from_secs(1000);
64 let check_interval = Duration::from_secs(5);
65
66 while total_elapsed < max_duration && running.load(Ordering::SeqCst) {
67 let remaining = max_duration - total_elapsed;
68 let run_duration = check_interval.min(remaining);
69
70 match ctrl.run(run_duration) {
71 Ok(final_state) => {
72 info!("Controller finished with state: {:?}", final_state);
73 break;
74 }
75 Err(e) if e.to_string().contains("Loop timeout") => {
76 // Expected timeout, continue if still running
77 total_elapsed += run_duration;
78 if !running.load(Ordering::SeqCst) {
79 info!("Stop signal received, exiting gracefully");
80 break;
81 }
82 }
83 Err(e) => {
84 info!("Controller failed: {}", e);
85 break;
86 }
87 }
88 }
89
90 Ok(())
91 };
92
93 match result {
94 Ok(()) => {
95 info!("Controller loop completed");
96 }
97 Err(e) => {
98 info!("Controller loop failed: {}", e);
99 }
100 }
101
102 Ok(())
103}Sourcepub fn flush_logger(&mut self) -> Result<(), NanonisError>
pub fn flush_logger(&mut self) -> Result<(), NanonisError>
Flush the logger (useful for signal handlers)
Examples found in repository?
16fn main() -> Result<(), Box<dyn std::error::Error>> {
17 env_logger::init();
18
19 // Create ActionDriver
20 let driver = ActionDriver::new("127.0.0.1", 6501)?;
21
22 // Create controller with custom pulse stepping parameters
23 let mut custom_controller = TipController::new(driver, SignalIndex(76), 2.0, (-2.0, 0.0));
24
25 let file_path = create_log_file_path()?;
26 println!("{file_path:?}");
27
28 // Configure custom pulse stepping parameters with dynamic threshold
29 custom_controller
30 //.set_pulse_stepping(1.5, Box::new(|signal| signal.abs() / 10.0), 4, 8.0)
31 .set_pulse_stepping_fixed(1.5, 2.0, 4, 10.0)
32 .set_stability_threshold(5)
33 .with_logger(Logger::new(file_path, 5));
34
35 // Create atomic flag for graceful shutdown
36 let running = Arc::new(AtomicBool::new(true));
37 let running_clone = Arc::clone(&running);
38
39 // Wrap controller in Arc<Mutex<>> for signal handler
40 let controller = Arc::new(Mutex::new(custom_controller));
41 let controller_clone = Arc::clone(&controller);
42
43 // Set up Ctrl-C handler to flush logger and signal stop
44 ctrlc::set_handler(move || {
45 info!("Received Ctrl-C, signaling stop and flushing logger...");
46 running_clone.store(false, Ordering::SeqCst);
47
48 if let Ok(mut ctrl) = controller_clone.lock() {
49 // Force flush the logger
50 match ctrl.flush_logger() {
51 Ok(()) => info!("Logger flushed successfully on exit"),
52 Err(e) => info!("Failed to flush logger on exit: {}", e),
53 }
54 }
55 })?;
56
57 // Run control loop with periodic checks for the stop signal
58 let result: Result<(), Box<dyn std::error::Error>> = {
59 let mut ctrl = controller.lock().unwrap();
60
61 // Run in shorter intervals so we can check the stop signal
62 let mut total_elapsed = Duration::from_secs(0);
63 let max_duration = Duration::from_secs(1000);
64 let check_interval = Duration::from_secs(5);
65
66 while total_elapsed < max_duration && running.load(Ordering::SeqCst) {
67 let remaining = max_duration - total_elapsed;
68 let run_duration = check_interval.min(remaining);
69
70 match ctrl.run(run_duration) {
71 Ok(final_state) => {
72 info!("Controller finished with state: {:?}", final_state);
73 break;
74 }
75 Err(e) if e.to_string().contains("Loop timeout") => {
76 // Expected timeout, continue if still running
77 total_elapsed += run_duration;
78 if !running.load(Ordering::SeqCst) {
79 info!("Stop signal received, exiting gracefully");
80 break;
81 }
82 }
83 Err(e) => {
84 info!("Controller failed: {}", e);
85 break;
86 }
87 }
88 }
89
90 Ok(())
91 };
92
93 match result {
94 Ok(()) => {
95 info!("Controller loop completed");
96 }
97 Err(e) => {
98 info!("Controller loop failed: {}", e);
99 }
100 }
101
102 Ok(())
103}Sourcepub fn set_stability_threshold(&mut self, threshold: u32) -> &mut Self
pub fn set_stability_threshold(&mut self, threshold: u32) -> &mut Self
Set stability threshold (how many good readings needed for stable)
Examples found in repository?
16fn main() -> Result<(), Box<dyn std::error::Error>> {
17 env_logger::init();
18
19 // Create ActionDriver
20 let driver = ActionDriver::new("127.0.0.1", 6501)?;
21
22 // Create controller with custom pulse stepping parameters
23 let mut custom_controller = TipController::new(driver, SignalIndex(76), 2.0, (-2.0, 0.0));
24
25 let file_path = create_log_file_path()?;
26 println!("{file_path:?}");
27
28 // Configure custom pulse stepping parameters with dynamic threshold
29 custom_controller
30 //.set_pulse_stepping(1.5, Box::new(|signal| signal.abs() / 10.0), 4, 8.0)
31 .set_pulse_stepping_fixed(1.5, 2.0, 4, 10.0)
32 .set_stability_threshold(5)
33 .with_logger(Logger::new(file_path, 5));
34
35 // Create atomic flag for graceful shutdown
36 let running = Arc::new(AtomicBool::new(true));
37 let running_clone = Arc::clone(&running);
38
39 // Wrap controller in Arc<Mutex<>> for signal handler
40 let controller = Arc::new(Mutex::new(custom_controller));
41 let controller_clone = Arc::clone(&controller);
42
43 // Set up Ctrl-C handler to flush logger and signal stop
44 ctrlc::set_handler(move || {
45 info!("Received Ctrl-C, signaling stop and flushing logger...");
46 running_clone.store(false, Ordering::SeqCst);
47
48 if let Ok(mut ctrl) = controller_clone.lock() {
49 // Force flush the logger
50 match ctrl.flush_logger() {
51 Ok(()) => info!("Logger flushed successfully on exit"),
52 Err(e) => info!("Failed to flush logger on exit: {}", e),
53 }
54 }
55 })?;
56
57 // Run control loop with periodic checks for the stop signal
58 let result: Result<(), Box<dyn std::error::Error>> = {
59 let mut ctrl = controller.lock().unwrap();
60
61 // Run in shorter intervals so we can check the stop signal
62 let mut total_elapsed = Duration::from_secs(0);
63 let max_duration = Duration::from_secs(1000);
64 let check_interval = Duration::from_secs(5);
65
66 while total_elapsed < max_duration && running.load(Ordering::SeqCst) {
67 let remaining = max_duration - total_elapsed;
68 let run_duration = check_interval.min(remaining);
69
70 match ctrl.run(run_duration) {
71 Ok(final_state) => {
72 info!("Controller finished with state: {:?}", final_state);
73 break;
74 }
75 Err(e) if e.to_string().contains("Loop timeout") => {
76 // Expected timeout, continue if still running
77 total_elapsed += run_duration;
78 if !running.load(Ordering::SeqCst) {
79 info!("Stop signal received, exiting gracefully");
80 break;
81 }
82 }
83 Err(e) => {
84 info!("Controller failed: {}", e);
85 break;
86 }
87 }
88 }
89
90 Ok(())
91 };
92
93 match result {
94 Ok(()) => {
95 info!("Controller loop completed");
96 }
97 Err(e) => {
98 info!("Controller loop failed: {}", e);
99 }
100 }
101
102 Ok(())
103}Sourcepub fn current_pulse_voltage(&self) -> f32
pub fn current_pulse_voltage(&self) -> f32
Get current pulse voltage
Sourcepub fn signal_history(&self) -> Option<&VecDeque<f32>>
pub fn signal_history(&self) -> Option<&VecDeque<f32>>
Get signal history (most recent first) for the frequency shift signal
Sourcepub fn average_signal(&self) -> Option<f32>
pub fn average_signal(&self) -> Option<f32>
Calculate average of recent signals for the frequency shift signal
Sourcepub fn average_signal_for(&self, signal_index: SignalIndex) -> Option<f32>
pub fn average_signal_for(&self, signal_index: SignalIndex) -> Option<f32>
Calculate average of recent signals for a specific signal
Sourcepub fn track_signal(&mut self, signal_index: SignalIndex, value: f32)
pub fn track_signal(&mut self, signal_index: SignalIndex, value: f32)
Track a signal value in history
Sourcepub fn get_signal_change(&self, signal_index: SignalIndex) -> Option<f32>
pub fn get_signal_change(&self, signal_index: SignalIndex) -> Option<f32>
Get signal change (latest - previous) for a specific signal
Sourcepub fn get_signal_history(
&self,
signal_index: SignalIndex,
) -> Option<&VecDeque<f32>>
pub fn get_signal_history( &self, signal_index: SignalIndex, ) -> Option<&VecDeque<f32>>
Get signal history for a specific signal (most recent first)
pub fn get_last_signal(&self, signal_index: SignalIndex) -> Option<f32>
Sourcepub fn clear_all_histories(&mut self)
pub fn clear_all_histories(&mut self)
Clear all signal histories (useful for logger integration)
Sourcepub fn clear_signal_history(&mut self, signal_index: SignalIndex)
pub fn clear_signal_history(&mut self, signal_index: SignalIndex)
Clear history for a specific signal