use crate::move_to::{async_move_to, move_to, MoveToOptions};
use crate::transport::args::TransportArgs;
use crate::transport::async_transport::AsyncRouter;
use crate::transport::singleton::get_singleton_transport;
use crate::transport::transaction::Request;
use crate::Controller;
use clap::Parser;
use std::time::Duration;
#[derive(Parser)]
#[command(about = "Move multiple servos to target positions with coordinated timing")]
struct Args {
#[arg(long, default_value = "1")]
id1: u8,
#[arg(long, default_value = "2")]
id2: u8,
#[arg(long, default_value = "5.0")]
period: f32,
#[arg(long)]
r#async: bool,
#[command(flatten)]
transport: TransportArgs,
}
fn run_blocking(args: &Args) -> Result<(), crate::Error> {
let transport = get_singleton_transport(Some(&args.transport.clone().into()))?;
let mut transport = transport.lock().unwrap();
let c1 = Controller::new(args.id1);
let c2 = Controller::new(args.id2);
let mut stop_requests = vec![
Request::new(c1.make_stop(false).into_frame()),
Request::new(c2.make_stop(false).into_frame()),
];
transport.cycle(&mut stop_requests)?;
let move_duration = args.period / 2.0;
println!("Servo {}: alternating between 0 and 1 rev", args.id1);
println!("Servo {}: alternating between 0 and 3 rev", args.id2);
println!("Period: {}s (each move: {}s)", args.period, move_duration);
println!("Press Ctrl+C to stop");
println!();
let opts = MoveToOptions::new().duration(Duration::from_secs_f32(move_duration));
let mut cycle = 0u64;
loop {
println!("Cycle {}: Moving to position A (c1=0.0, c2=0.0)", cycle);
let results = move_to(
&mut *transport,
&[(&c1, 0.0.into()), (&c2, 0.0.into())],
&opts,
)?;
for r in &results {
println!(" Servo {} arrived at {:.3}", r.id, r.result.position);
}
println!("Cycle {}: Moving to position B (c1=1.0, c2=3.0)", cycle);
let results = move_to(
&mut *transport,
&[(&c1, 1.0.into()), (&c2, 3.0.into())],
&opts,
)?;
for r in &results {
println!(" Servo {} arrived at {:.3}", r.id, r.result.position);
}
cycle += 1;
}
}
#[tokio::main]
async fn run_async(args: &Args) -> Result<(), crate::Error> {
let opts = args.transport.clone().into();
let mut transport = AsyncRouter::with_options(&opts).await?;
let c1 = Controller::new(args.id1);
let c2 = Controller::new(args.id2);
let mut stop_requests = vec![
Request::new(c1.make_stop(false).into_frame()),
Request::new(c2.make_stop(false).into_frame()),
];
transport.cycle(&mut stop_requests).await?;
let move_duration = args.period / 2.0;
println!("Servo {}: alternating between 0 and 1 rev", args.id1);
println!("Servo {}: alternating between 0 and 3 rev", args.id2);
println!("Period: {}s (each move: {}s)", args.period, move_duration);
println!("Press Ctrl+C to stop");
println!();
let move_opts = MoveToOptions::new().duration(Duration::from_secs_f32(move_duration));
let mut cycle = 0u64;
loop {
println!("Cycle {}: Moving to position A (c1=0.0, c2=0.0)", cycle);
let results = async_move_to(
&mut transport,
&[(&c1, 0.0.into()), (&c2, 0.0.into())],
&move_opts,
)
.await?;
for r in &results {
println!(" Servo {} arrived at {:.3}", r.id, r.result.position);
}
println!("Cycle {}: Moving to position B (c1=1.0, c2=3.0)", cycle);
let results = async_move_to(
&mut transport,
&[(&c1, 1.0.into()), (&c2, 3.0.into())],
&move_opts,
)
.await?;
for r in &results {
println!(" Servo {} arrived at {:.3}", r.id, r.result.position);
}
cycle += 1;
}
}
pub fn run(register_transports: impl FnOnce()) -> Result<(), crate::Error> {
let args = Args::parse();
register_transports();
if args.r#async {
run_async(&args)
} else {
run_blocking(&args)
}
}