mod commands;
use clap::{Parser, Subcommand};
use tracing_subscriber::EnvFilter;
use commands::{
add_model, bench, compare, import_pytorch, inspect, latency, new_project, record, replay, run,
test, validate_model, visualize,
};
const BRAND: &str = "clankeRS";
#[derive(Parser)]
#[command(name = "clankers", about = "clankeRS — Rust robotics SDK CLI", version)]
pub struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
New {
name: String,
#[arg(long, default_value = "basic-node")]
template: String,
},
Run,
Test,
Inspect { file: String },
Replay {
file: String,
#[arg(long)]
node: Option<String>,
},
Latency { file: String },
Compare { expected: String, actual: String },
Record {
#[arg(long, default_value = "logs/run.mcap")]
output: String,
},
Bench {
#[arg(long)]
model: String,
#[arg(long, default_value = "onnxruntime")]
backend: String,
#[arg(long)]
input: Option<String>,
#[arg(long, default_value = "50")]
warmup: u32,
#[arg(long, default_value = "1000")]
iters: u32,
},
ValidateModel {
#[arg(long)]
pytorch: Option<String>,
#[arg(long)]
checkpoint: Option<String>,
#[arg(long)]
onnx: String,
#[arg(long, default_value = "sample_data/policy_inputs/")]
samples: String,
#[arg(long, default_value = "0.001")]
tolerance: f32,
},
ImportPytorch {
#[arg(long)]
model: String,
#[arg(long)]
checkpoint: String,
#[arg(long)]
output: String,
#[arg(long)]
opset: Option<u32>,
},
AddModel { path: String },
Visualize { file: String },
Demo {
#[arg(default_value = "camera-perception")]
name: String,
},
}
pub async fn run() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
)
.init();
let cli = Cli::parse();
match cli.command {
Commands::New { name, template } => new_project::execute(&name, &template)?,
Commands::Run => run::execute()?,
Commands::Test => test::execute().await?,
Commands::Inspect { file } => inspect::execute(&file)?,
Commands::Replay { file, node } => replay::execute(&file, node.as_deref()).await?,
Commands::Latency { file } => latency::execute(&file).await?,
Commands::Compare { expected, actual } => compare::execute(&expected, &actual)?,
Commands::Bench {
model,
backend,
input,
warmup,
iters,
} => bench::execute(&model, &backend, input.as_deref(), warmup, iters)?,
Commands::Record { output } => record::execute(&output).await?,
Commands::ValidateModel {
pytorch,
checkpoint,
onnx,
samples,
tolerance,
} => validate_model::execute(
pytorch.as_deref(),
checkpoint.as_deref(),
&onnx,
&samples,
tolerance,
)?,
Commands::ImportPytorch {
model,
checkpoint,
output,
opset,
} => import_pytorch::execute(&model, &checkpoint, &output, opset)?,
Commands::AddModel { path } => add_model::execute(&path)?,
Commands::Visualize { file } => visualize::execute(&file)?,
Commands::Demo { name } => commands::demo::execute(&name).await?,
}
Ok(())
}
pub fn print_banner(msg: &str) {
println!("{BRAND} {msg}");
}