2025-12-12 11:36:13 +00:00
|
|
|
use gilrs;
|
2025-11-23 18:40:48 +00:00
|
|
|
use macroquad::prelude as mq;
|
2025-12-12 11:36:13 +00:00
|
|
|
use nalgebra as na;
|
2025-11-23 18:40:48 +00:00
|
|
|
use rapier3d::prelude::*;
|
|
|
|
|
|
|
|
|
|
mod engine;
|
|
|
|
|
use engine::*;
|
|
|
|
|
|
2025-11-23 23:43:48 +00:00
|
|
|
mod camera;
|
2025-12-07 00:41:00 +00:00
|
|
|
mod drone;
|
2025-11-28 20:39:09 +00:00
|
|
|
mod rendering;
|
2025-11-23 23:43:48 +00:00
|
|
|
|
2025-11-23 18:40:48 +00:00
|
|
|
mod graphics_util;
|
|
|
|
|
|
2025-12-09 15:47:53 +00:00
|
|
|
use crate::{drone::fpvcontroller::JoystickInput, rendering::Renderer};
|
2025-11-28 20:39:09 +00:00
|
|
|
|
2025-12-08 22:34:01 +00:00
|
|
|
fn window_conf() -> mq::Conf {
|
|
|
|
|
mq::Conf {
|
|
|
|
|
window_title: "RustDroneSim".to_owned(),
|
|
|
|
|
window_resizable: true,
|
|
|
|
|
// fullscreen: true,
|
|
|
|
|
platform: mq::miniquad::conf::Platform {
|
2025-12-10 13:11:51 +00:00
|
|
|
// linux_backend: mq::miniquad::conf::LinuxBackend::WaylandOnly,
|
2025-12-08 22:34:01 +00:00
|
|
|
..Default::default()
|
|
|
|
|
},
|
|
|
|
|
..Default::default()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[macroquad::main(window_conf)]
|
2025-11-23 18:40:48 +00:00
|
|
|
async fn main() {
|
2025-12-12 11:36:13 +00:00
|
|
|
/* World Setup */
|
2025-11-28 20:39:09 +00:00
|
|
|
let mut world = World::default();
|
2025-11-23 18:40:48 +00:00
|
|
|
|
|
|
|
|
world.register_free_collider(
|
2025-12-12 11:36:13 +00:00
|
|
|
ColliderBuilder::cuboid(30.0, 1.0, 30.0)
|
2025-12-10 13:11:51 +00:00
|
|
|
.translation(vector![0.0, -2.0, 0.0])
|
2025-12-03 21:28:27 +00:00
|
|
|
.restitution(0.5)
|
2025-11-23 18:40:48 +00:00
|
|
|
.build(),
|
|
|
|
|
None,
|
|
|
|
|
);
|
2025-11-28 20:39:09 +00:00
|
|
|
|
2025-12-13 15:01:04 +00:00
|
|
|
let mut drone_controller = drone::pidcontroller::PIDController::default();
|
2025-12-12 11:36:13 +00:00
|
|
|
drone_controller.set_input(JoystickInput {
|
2025-12-11 18:08:07 +00:00
|
|
|
throttle_input: 0.75,
|
|
|
|
|
yaw_input: 0.4,
|
|
|
|
|
roll_input: 0.7,
|
2025-12-09 19:23:57 +00:00
|
|
|
pitch_input: 0.0,
|
2025-12-09 15:47:53 +00:00
|
|
|
});
|
2025-12-12 11:36:13 +00:00
|
|
|
let mut drone_obj = drone::Drone::new(
|
2025-12-08 22:34:01 +00:00
|
|
|
&mut world,
|
2025-12-12 11:36:13 +00:00
|
|
|
Box::new(drone_controller),
|
2025-12-08 22:34:01 +00:00
|
|
|
drone::MotorCharacteristics {
|
2025-12-10 13:11:51 +00:00
|
|
|
max_thrust: 2.6,
|
2025-12-12 11:36:13 +00:00
|
|
|
max_torque: 0.5,
|
2025-12-08 22:34:01 +00:00
|
|
|
..Default::default()
|
|
|
|
|
},
|
|
|
|
|
0.350,
|
|
|
|
|
);
|
2025-12-07 00:41:00 +00:00
|
|
|
|
2025-12-12 11:36:13 +00:00
|
|
|
/* 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));
|
|
|
|
|
|
|
|
|
|
renderer.light.set_location(
|
|
|
|
|
vector![70.0, 150.0, -90.0].into(),
|
|
|
|
|
vector![-0.4, -0.7, 0.6].into(),
|
|
|
|
|
);
|
|
|
|
|
renderer.update_light(&world);
|
|
|
|
|
|
|
|
|
|
/* Command Setup */
|
|
|
|
|
// let mut gilrs = gilrs::Gilrs::new().unwrap();
|
|
|
|
|
//
|
|
|
|
|
// // Iterate over all connected gamepads
|
|
|
|
|
// for (_id, gamepad) in gilrs.gamepads() {
|
|
|
|
|
// println!("{} is {:?}", gamepad.name(), gamepad.power_info());
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
let mut input = JoystickInput::default();
|
|
|
|
|
|
2025-11-28 20:39:09 +00:00
|
|
|
loop {
|
2025-12-12 11:36:13 +00:00
|
|
|
renderer.update_camera(&world);
|
2025-11-28 20:39:09 +00:00
|
|
|
if mq::is_key_pressed(mq::KeyCode::L) {
|
|
|
|
|
renderer
|
|
|
|
|
.light
|
2025-12-12 11:36:13 +00:00
|
|
|
.set_location(renderer.camera.get_position(), renderer.camera.get_front());
|
2025-12-03 21:28:27 +00:00
|
|
|
renderer.update_light(&world);
|
2025-11-28 20:39:09 +00:00
|
|
|
}
|
2025-11-23 18:40:48 +00:00
|
|
|
|
2025-12-13 15:01:04 +00:00
|
|
|
if mq::is_key_pressed(mq::KeyCode::Q) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-11-28 20:39:09 +00:00
|
|
|
if mq::is_key_pressed(mq::KeyCode::C) {
|
|
|
|
|
add_objects(&mut world);
|
|
|
|
|
}
|
2025-11-29 23:22:17 +00:00
|
|
|
if mq::is_key_pressed(mq::KeyCode::M) {
|
|
|
|
|
renderer.apply_config();
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-12 11:36:13 +00:00
|
|
|
if mq::is_key_down(mq::KeyCode::W) {
|
|
|
|
|
input.throttle_input += 4.0 * mq::get_frame_time();
|
|
|
|
|
}
|
|
|
|
|
if mq::is_key_down(mq::KeyCode::S) {
|
|
|
|
|
input.throttle_input -= 4.0 * mq::get_frame_time();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mq::is_key_down(mq::KeyCode::A) {
|
|
|
|
|
input.yaw_input = 1.0;
|
|
|
|
|
} else if mq::is_key_down(mq::KeyCode::D) {
|
|
|
|
|
input.yaw_input = -1.0;
|
|
|
|
|
} else {
|
|
|
|
|
input.yaw_input = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mq::is_key_down(mq::KeyCode::Up) {
|
|
|
|
|
input.pitch_input = -1.0;
|
|
|
|
|
} else if mq::is_key_down(mq::KeyCode::Down) {
|
|
|
|
|
input.pitch_input = 1.0;
|
|
|
|
|
} else {
|
|
|
|
|
input.pitch_input = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mq::is_key_down(mq::KeyCode::Left) {
|
|
|
|
|
input.roll_input = -1.0;
|
|
|
|
|
} else if mq::is_key_down(mq::KeyCode::Right) {
|
|
|
|
|
input.roll_input = 1.0;
|
|
|
|
|
} else {
|
|
|
|
|
input.roll_input = 0.0;
|
|
|
|
|
}
|
|
|
|
|
input = input.clamp();
|
|
|
|
|
match drone_obj
|
|
|
|
|
.controller
|
|
|
|
|
.as_mut_any()
|
2025-12-13 15:01:04 +00:00
|
|
|
.downcast_mut::<drone::pidcontroller::PIDController>()
|
2025-12-12 11:36:13 +00:00
|
|
|
{
|
|
|
|
|
Some(cont) => {
|
|
|
|
|
cont.set_input(input);
|
|
|
|
|
}
|
|
|
|
|
None => {}
|
|
|
|
|
};
|
|
|
|
|
|
2025-12-08 22:34:01 +00:00
|
|
|
// Physics
|
2025-12-07 00:41:00 +00:00
|
|
|
world.step();
|
2025-12-08 22:34:01 +00:00
|
|
|
let _ = clearscreen::clear();
|
2025-12-12 11:36:13 +00:00
|
|
|
drone_obj.process_tick(&mut world);
|
2025-12-07 00:41:00 +00:00
|
|
|
|
2025-12-08 22:34:01 +00:00
|
|
|
// Rendering
|
2025-12-06 15:38:01 +00:00
|
|
|
renderer.draw(&mut world);
|
|
|
|
|
|
2025-12-13 15:01:04 +00:00
|
|
|
if world.tick % (20) == 0 {
|
|
|
|
|
// renderer.update_light(&world);
|
|
|
|
|
// world.clear_ofb();
|
|
|
|
|
mq::next_frame().await;
|
2025-12-03 21:28:27 +00:00
|
|
|
}
|
2025-11-28 20:39:09 +00:00
|
|
|
}
|
2025-12-13 15:01:04 +00:00
|
|
|
|
|
|
|
|
match drone_obj
|
|
|
|
|
.controller
|
|
|
|
|
.as_mut_any()
|
|
|
|
|
.downcast_mut::<drone::pidcontroller::PIDController>()
|
|
|
|
|
{
|
|
|
|
|
Some(cont) => {
|
|
|
|
|
let _ = cont.save_logs_to_csv("./pid_logs.csv");
|
|
|
|
|
}
|
|
|
|
|
None => {}
|
|
|
|
|
};
|
2025-11-28 20:39:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn add_objects(world: &mut World) {
|
|
|
|
|
for i in 0..1 {
|
2025-11-23 23:43:48 +00:00
|
|
|
let body = world.register_body(
|
|
|
|
|
RigidBodyBuilder::dynamic()
|
2025-11-28 20:39:09 +00:00
|
|
|
.translation(vector![0.0, 50.0 + i as f32, 0.0])
|
2025-11-23 23:43:48 +00:00
|
|
|
.rotation(vector![std::f32::consts::PI / 4.2, i as f32, i as f32])
|
|
|
|
|
.build(),
|
|
|
|
|
);
|
|
|
|
|
world.register_collider(
|
2025-12-12 11:36:13 +00:00
|
|
|
ColliderBuilder::cuboid(2.0, 2.0, 2.0)
|
|
|
|
|
.restitution(0.1)
|
2025-11-23 23:43:48 +00:00
|
|
|
.build(),
|
|
|
|
|
body,
|
|
|
|
|
None,
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-11-23 18:40:48 +00:00
|
|
|
}
|