before cargo fix

This commit is contained in:
Franchioping 2026-01-06 16:41:14 +00:00
parent 04609b2d4f
commit f8c7761d8c
5 changed files with 255 additions and 137 deletions

2
Cargo.lock generated
View File

@ -3,7 +3,7 @@
version = 4
[[package]]
name = "RaylibRustPhysics"
name = "RustPhysicsMQ"
version = "0.1.0"
dependencies = [
"clearscreen",

View File

@ -1,8 +1,8 @@
[package]
name = "RaylibRustPhysics"
name = "RustPhysicsMQ"
version = "0.1.0"
edition = "2024"
default-run = "RaylibRustPhysics"
default-run = "RustPhysicsMQ"
[dependencies]
macroquad = "0.4.14"
@ -17,9 +17,11 @@ serde = {version = "1.0.228", features = ["serde_derive"]}
toml = "0.9.8"
[[bin]]
name = "tools"
path = "src/tools/main.rs"
name = "batch"
path = "src/main_batch.rs"
[profile.dev.package.rapier3d]
opt-level = 3

View File

@ -3,7 +3,7 @@ use std::any::Any;
use crate::drone::controller::DroneController;
use crate::drone::JoystickInput;
pub use crate::drone::JoystickInput;
pub struct FPVController {
input: JoystickInput,

View File

@ -1,154 +1,55 @@
use gilrs;
use macroquad::prelude as mq;
use nalgebra as na;
use rapier3d::prelude::*;
mod engine;
use engine::*;
mod camera;
mod config;
mod drone;
mod helpers;
mod rendering;
mod simulation;
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/";
use crate::{drone::fpvcontroller::JoystickInput, rendering::Renderer};
fn window_conf() -> mq::Conf {
mq::Conf {
window_title: "RustDroneSim".to_owned(),
window_resizable: true,
// fullscreen: true,
platform: mq::miniquad::conf::Platform {
// linux_backend: mq::miniquad::conf::LinuxBackend::WaylandOnly,
..Default::default()
},
..Default::default()
}
}
use std::env;
use std::path::PathBuf;
use std::thread::JoinHandle;
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)]
async fn main() {
match parse_cli() {
RunMode::Batch => run_batch().await,
RunMode::Record { output } => run_record(output).await,
}
}
/* World Setup */
let mut world = World::default();
async fn run_batch() {
fs::remove_dir_all(RESULTS_DIR).unwrap();
fs::create_dir_all(RESULTS_DIR).unwrap();
let input_files = list_files(INPUTS_DIR);
let config_files = list_files(CONFIGS_DIR);
let mut handles: Vec<JoinHandle<()>> = Default::default();
for input_path in input_files {
for config_path in &config_files {
let cp = config_path.clone();
let ip = input_path.clone();
handles.push(std::thread::spawn(move || {
run(&ip, &cp);
}));
}
}
for handle in handles {
handle.join().unwrap();
}
println!("All simulations completed.");
}
fn run(input_path: &PathBuf, config_path: &PathBuf) {
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");
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.register_free_collider(
ColliderBuilder::cuboid(30.0, 1.0, 30.0)
.translation(vector![0.0, -2.0, 0.0])
.restitution(0.5)
.build(),
None,
);
/* World */
let mut world = World::new(config.tickrate);
/* Drone */
let drone = drone::Drone::new(
let mut drone_controller = drone::pidcontroller::PIDController::default();
drone_controller.set_input(JoystickInput {
throttle_input: 0.75,
yaw_input: 0.4,
roll_input: 0.7,
pitch_input: 0.0,
});
let mut drone_obj = 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().unwrap();
}
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()
}),
Box::new(drone_controller),
drone::MotorCharacteristics {
max_thrust: 2.6,
max_torque: 0.5,
@ -157,14 +58,59 @@ async fn run_record(output: String) {
0.350,
);
let mut sim = Simulation::new(
drone,
world,
true,
SimMode::Record(InputRecording::default(), output),
None,
600,
/* Renderer Setup */
let camera = camera::AttachedCamera::new(
drone_obj.rb_handle,
vector![1.0, 0.0, 0.0],
vector![0.5, 0.0, 0.0],
);
let mut renderer = Renderer::new(Box::new(camera));
sim.run().unwrap();
renderer.light.set_location(
vector![70.0, 150.0, -90.0].into(),
vector![-0.4, -0.7, 0.6].into(),
);
renderer.update_light(&world);
let mut input = JoystickInput::default();
loop {
renderer.update_camera(&world);
if mq::is_key_pressed(mq::KeyCode::Q) {
break;
}
// Physics
world.step();
let _ = clearscreen::clear();
drone_obj.process_tick(&mut world);
// Rendering
renderer.draw(&mut world);
if world.tick % (20) == 0 {
// renderer.update_light(&world);
// world.clear_ofb();
mq::next_frame().await;
}
}
}
fn add_objects(world: &mut World) {
for i in 0..1 {
let body = world.register_body(
RigidBodyBuilder::dynamic()
.translation(vector![0.0, 50.0 + i as f32, 0.0])
.rotation(vector![std::f32::consts::PI / 4.2, i as f32, i as f32])
.build(),
);
world.register_collider(
ColliderBuilder::cuboid(2.0, 2.0, 2.0)
.restitution(0.1)
.build(),
body,
None,
);
}
}

170
src/main_batch.rs Normal file
View File

@ -0,0 +1,170 @@
use macroquad::prelude as mq;
mod engine;
use engine::*;
mod camera;
mod config;
mod drone;
mod helpers;
mod rendering;
mod simulation;
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/";
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;
use std::path::PathBuf;
use std::thread::JoinHandle;
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)]
async fn main() {
match parse_cli() {
RunMode::Batch => run_batch().await,
RunMode::Record { output } => run_record(output).await,
}
}
async fn run_batch() {
fs::remove_dir_all(RESULTS_DIR).unwrap();
fs::create_dir_all(RESULTS_DIR).unwrap();
let input_files = list_files(INPUTS_DIR);
let config_files = list_files(CONFIGS_DIR);
let mut handles: Vec<JoinHandle<()>> = Default::default();
for input_path in input_files {
for config_path in &config_files {
let cp = config_path.clone();
let ip = input_path.clone();
handles.push(std::thread::spawn(move || {
run(&ip, &cp);
}));
}
}
for handle in handles {
handle.join().unwrap();
}
println!("All simulations completed.");
}
fn run(input_path: &PathBuf, config_path: &PathBuf) {
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");
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().unwrap();
}
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,
);
let mut sim = Simulation::new(
drone,
world,
true,
SimMode::Record(InputRecording::default(), output),
None,
600,
);
sim.run().unwrap();
}