@@ 13,11 13,6 @@ id = "main"
apply_force_at_local = [ 0, 0 ]
thrust_vector = [ 0.0, -20000.0 ]
-[[thruster]]
-id = "back"
-apply_force_at_local = [ 0, 0 ]
-thrust_vector = [ 0.0, 20000.0 ]
-
[[joint]]
id = "Top"
target = { translation = [ 0.0, 55.0, 0.0 ], rotation = 0.0 }
@@ 7,9 7,9 @@ spawn_parts_interval_secs = 1
default_height = 50
default_width = 50
default_mass = 100
-joint_align_compliance = 0.0002
-joint_angle_compliance = 0.00000002
-joint_limit_compliance = 0.006
+joint_align_compliance = 0.00002
+joint_angle_compliance = 0.000000002
+joint_limit_compliance = 0.0006
joint_linear_damping = 4.0
joint_angular_damping = 2.0
@@ 55,6 55,7 @@ fn draw_thruster_debug(
}
}
+// TODO: split this into two passes
fn solve_thrust(
me: Query<(Option<&Parts>, &GlobalTransform, Entity), With<Me>>,
parts: Query<&PartThrusters>,
@@ 90,28 91,40 @@ fn solve_thrust(
// +Z == counterclockwise/ccw
// -Z == clockwise/cw
+ const MAGIC_TORQUE_SCALE_FACTOR: f32 = 100.0; // mystery units
+
let mut target_unit_vector = Vec3::ZERO;
+ let mut anything_pressed = false;
+
if input.pressed(&ClientAction::ThrustForward) {
+ anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(0.0, 1.0, 0.0);
}
if input.pressed(&ClientAction::ThrustBackward) {
+ anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(0.0, -1.0, 0.0);
}
if input.pressed(&ClientAction::ThrustRight) {
+ anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(1.0, 0.0, 0.0);
}
if input.pressed(&ClientAction::ThrustLeft) {
+ anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(-1.0, 0.0, 0.0);
}
if input.pressed(&ClientAction::TorqueCw) {
- target_unit_vector += Vec3::new(0.0, 0.0, -1.0);
+ anything_pressed = true;
+ target_unit_vector += Vec3::new(0.0, 0.0, -1.0 / MAGIC_TORQUE_SCALE_FACTOR);
}
if input.pressed(&ClientAction::TorqueCcw) {
- target_unit_vector += Vec3::new(0.0, 0.0, 1.0);
+ anything_pressed = true;
+ target_unit_vector += Vec3::new(0.0, 0.0, 1.0 / MAGIC_TORQUE_SCALE_FACTOR);
}
- if target_unit_vector == Vec3::ZERO {
+ target_unit_vector = target_unit_vector.normalize();
+
+ if target_unit_vector == Vec3::ZERO || !anything_pressed {
trace!("no buttons are pressed; zeroing thrust solution");
trace!("solved thrust in {}ms", start.elapsed().as_millis());
solution.converged = true;
@@ 145,7 158,7 @@ fn solve_thrust(
// determine our rotational offset from hearty
let relative_rotation = thruster_transform.rotation() * -hearty_transform.rotation();
- let thruster_torque = relative_translation.extend(0.0).cross(thruster_vector.extend(0.0)).z;
+ let thruster_torque = relative_translation.extend(0.0).cross(thruster_vector.extend(0.0)).z / MAGIC_TORQUE_SCALE_FACTOR;
// magically assemble the worldspace vector! for the solver (not shipspace)
let target_vector = thruster_vector.extend(thruster_torque);
@@ 162,7 175,22 @@ fn solve_thrust(
}
let coefficients = all_thrusters.iter()
- .map(|u| target_unit_vector.dot(u.1))
+ .map(|u| {
+ trace!("{} dot {}", target_unit_vector, u.1.normalize());
+ target_unit_vector.dot(u.1.normalize())
+ })
+ .map(|u| {
+ trace!("=> {u}");
+ // improve reliability:
+ // if dot is <0.1, zap it entirely (this thruster is not helping)
+ // TODO: figure out how to make this adjustable
+ if u.abs() < 0.1 {
+ 0.0
+ } else {
+ u
+ }
+ })
+ //.map(|u| u.powi(3))
.collect::<Vec<_>>();
trace!("preparing model");
@@ 170,7 198,7 @@ fn solve_thrust(
// add variables to problem
let variables = coefficients.iter()
- .map(|u| problem.add_binary_var(*u as f64))
+ .map(|u| problem.add_var(*u as f64, (0.0, 1.0)))
.collect::<Vec<_>>();
trace!("prepared {} variables; solving", variables.len());
@@ 207,8 235,9 @@ fn solve_thrust(
};
for thruster in all_thrusters.iter().enumerate() {
- trace!("solution: thruster #{} ({:?}): {}", thruster.0, thruster.1.0, ssolution.var_value_rounded(variables[thruster.0]));
- if ssolution.var_value_rounded(variables[thruster.0]) == 1.0 {
+ trace!("solution: thruster #{} ({:?}): {} @ coeff {}", thruster.0, thruster.1.0, ssolution.var_value(variables[thruster.0]), coefficients[thruster.0]);
+ // TODO: make this more easily adjustable
+ if *ssolution.var_value(variables[thruster.0]) > 0.8 {
new_soln.thrusters_on.insert(*thruster.1.0);
}
}