RustPhysicsMQ/src/main.rs

157 lines
4.0 KiB
Rust
Raw Normal View History

2025-11-23 18:40:48 +00:00
use macroquad::prelude as mq;
mod engine;
use engine::*;
2025-11-23 23:43:48 +00:00
mod camera;
mod config;
2025-12-07 00:41:00 +00:00
mod drone;
mod helpers;
2025-11-28 20:39:09 +00:00
mod rendering;
mod simulation;
2025-11-23 23:43:48 +00:00
2025-11-23 18:40:48 +00:00
mod graphics_util;
use crate::drone::input::*;
use crate::simulation::{SimMode, Simulation};
use crate::config::SimulationConfig;
use helpers::list_files;
use std::fs;
const INPUTS_DIR: &str = "inputs/";
const CONFIGS_DIR: &str = "configurations/";
const RESULTS_DIR: &str = "results/";
2025-11-28 20:39:09 +00:00
fn window_conf() -> mq::Conf {
mq::Conf {
window_title: "RustDroneSim".to_owned(),
window_resizable: true,
platform: mq::miniquad::conf::Platform {
..Default::default()
},
..Default::default()
}
}
use std::env;
enum RunMode {
Batch,
Record { output: String },
}
fn parse_cli() -> RunMode {
let mut args = env::args().skip(1);
match args.next().as_deref() {
Some("record") => {
let output = args.next().expect("record mode requires output file path");
RunMode::Record { output }
}
Some("batch") | None => RunMode::Batch,
Some(other) => panic!("Unknown mode: {}", other),
}
}
#[macroquad::main(window_conf)]
2025-11-23 18:40:48 +00:00
async fn main() {
match parse_cli() {
RunMode::Batch => run_batch().await,
RunMode::Record { output } => run_record(output).await,
}
}
async fn run_batch() {
fs::create_dir_all(RESULTS_DIR).unwrap();
let input_files = list_files(INPUTS_DIR);
let config_files = list_files(CONFIGS_DIR);
for input_path in input_files {
let input_name = input_path.file_stem().unwrap().to_string_lossy();
let inputs = InputRecording::load_inputs_from_csv(input_path.to_str().unwrap())
.expect("Failed to load input recording");
for config_path in &config_files {
let config_name = config_path.file_stem().unwrap().to_string_lossy();
let config: SimulationConfig =
toml::from_str(&fs::read_to_string(config_path).unwrap())
.expect("Invalid config file");
println!(
"Running simulation: input={} config={}",
input_name, config_name
);
/* World */
let mut world = World::new(config.tickrate);
/* Drone */
let drone = drone::Drone::new(
&mut world,
Box::new(drone::pidcontroller::PIDController {
target_rate: config.target_rate,
proportional_multiplier: config.proportional(),
integral_multiplier: config.integral(),
diferential_multiplier: config.diferential(),
..Default::default()
}),
drone::MotorCharacteristics {
max_thrust: config.max_thrust,
max_torque: config.max_torque,
..Default::default()
},
config.mass,
);
let result_file = format!("{}/{}_{}.csv", RESULTS_DIR, input_name, config_name);
let mut sim = Simulation::new(
drone,
world,
false,
SimMode::Playback(inputs.clone(), 0.0),
Some(result_file),
config.drone_tick_rate,
);
sim.run().await.unwrap();
}
}
2025-11-28 20:39:09 +00:00
println!("All simulations completed.");
}
async fn run_record(output: String) {
println!("Recording inputs to {}", output);
let tickrate = 60000.0;
let mut world = World::new(tickrate);
let drone = drone::Drone::new(
&mut world,
Box::new(drone::pidcontroller::PIDController {
..Default::default()
}),
drone::MotorCharacteristics {
max_thrust: 2.6,
max_torque: 0.5,
..Default::default()
},
0.350,
);
2025-12-07 00:41:00 +00:00
let mut sim = Simulation::new(
drone,
world,
true,
SimMode::Record(InputRecording::default(), output),
None,
600,
);
sim.run().await.unwrap();
2025-11-23 18:40:48 +00:00
}