I'm building a space-sim (yes, another one) with a bit more realistic physics than usual. Instead of setting velocities directly I want the user to set a target angular velocity with its joystick and have the code set torques to reach and maintain that target.
I have this currently working with each axis independently, but it becomes totally unstable when integrating more than one axis of rotation.
I'm not really sure on how to interpret the getAngularVelocity() vector of the rigidbody. My target velocities are independent pitch, yaw and roll (last one not set for the moment) relative to the ship's own local axes.
You can see the code below. The input to this function is a vector of values between -1 and 1 (so that I can set actual target velocities per ship).
As you can see I'm currently using a constant acceleration/torque (yes, I don't include the mass calculation yet). I compute this by first obtaining the delta velocity, then deriving the time needed to apply a certain constant acceleration. If this time is positive, it means I have to apply it still to reach the target (negative is for "braking"). I will make acceleration proportional to time later for smoothness.
This code makes rotation over all axis diverge and spins the ship out of control. What is the correct way to interpret current angular velocity vector? I imagine it is not as I'm doing it now: x() component = angular velocity over x axis, etc.
Note that torque vector is rotated with the ship's current worldtransform rotation so that it is applied relative to the ships local coordinate system. I tried doing the same for the angular velocity (since I see that everything in bullet is relative to world) but I does not fix this.}
Thanks!
Code: Select all
void nos::Ship::Control::set_angular_velocity(const btVector3& velocity_factor) {
btVector3 max_velocity(20, 20, 20);
btVector3 velocity = velocity_factor * max_velocity;
const btVector3& current_velocity = Ship::instance()->body->physics.body->getAngularVelocity(); // TODO: check ang vel component and coord. systs
btVector3 delta_velocity = velocity - current_velocity;
for (int i = 0; i < 3; i++) {
delta_velocity.m_floats[i] = (fabsf(delta_velocity.m_floats[i]) < SIMD_EPSILON ? 0 : delta_velocity.m_floats[i]);
}
cout << "dV " << delta_velocity.x() << " " << delta_velocity.y() << " " << delta_velocity.z() << endl;
btVector3 acceleration(100,100,100);
btVector3 dT = delta_velocity / acceleration;
btVector3 torque = acceleration /* TODO: times mass inertia */;
// TODO: add deltaV check
for (int i = 0; i < 3; i++) {
if (dT.m_floats[i] == 0) torque.m_floats[i] = 0;
else torque.m_floats[i] *= (dT.m_floats[i] < 0 ? -1 : 1);
}
cout << "dt: " << dT.x() << " " << dT.y() << " " << dT.z() << endl;
cout << "t: " << torque.x() << " " << torque.y() << " " << torque.z() << endl;
Ship::instance()->body->apply_torque(torque);
}
void nos::Body::apply_torque(const btVector3& v) {
btTransform trans;
physics.body->getMotionState()->getWorldTransform(trans);
trans.setOrigin(btVector3(0,0,0)); // leave only rotation
physics.body->applyTorque(trans * v);
}
void nos::Body::get_angular_velocity(btVector3& vel) {
btTransform trans;
physics.body->getMotionState()->getWorldTransform(trans);
trans.setOrigin(btVector3(0,0,0)); // leave only rotation
vel = /*trans * */physics.body->getAngularVelocity();
}