// Basically NAVMODE_KILLROT in a single dimension. Returns true when the rate has been nulled // out, otherwise it returns false. bool NullRate(AXIS Axis) { VESSEL *Vessel = oapiGetFocusInterface(); VESSELSTATUS Status; Vessel->GetStatus(Status); double RateDeadband = Radians(0.001), Thrust, Level, Rate = Status.vrot.data[Axis], Mass = Vessel->GetMass(), MaxThrust = Vessel->GetMaxThrust(ENGINE_ATTITUDE), Size = Vessel->GetSize(); VECTOR3 PMI; Vessel->GetPMI(PMI); if (fabs(Rate) < RATE_NULL) { Vessel->SetAttitudeRotLevel(Axis, 0.0); return true; } Thrust = -(Mass * PMI.data[Axis] * Rate) / (Size); Level = min((Thrust/MaxThrust), 1); Vessel->SetAttitudeRotLevel(Axis, Level); return false; }
// Generates rotational commands in order to achieve a target attitude in a given axis. // Note that the user is responsible for providing an accurate current attitude information. // This allows for greater flexability but also can be a source of problems if you pass // incorrect data to the function. For example, if you invert signs, then the spacecraft will // fly out of control because as it rotates in the correct direction, the DeltaAngle will // increase! Please be careful :-) The function returns true when the desired attitude // has been reached (within the given deadband) and the velocity has been nulled; otherwise, // it returns false. bool SetAttitude(double TargetAttitude, double CurrentAttitude, double RotRate, AXIS Axis, DEADBAND DeadbandLow) { VESSEL *Vessel; // Spacecraft interface double Rate; // Depends on magnitude of DeltaAngle double RateDeadband; // Depends on the magnitude of Rate double Thrust; // Thrust required double Level; // Required thrust level [0 - 1] VECTOR3 PMI; // Prinicple moment of inertia double MaxThrust; // Maximum thrust delivered by the engines double Size; // Spacecraft radius double Mass; // Spacecraft mass double DeltaRate; // The difference between the desired and the actual rate double DeltaAngle = TargetAttitude - CurrentAttitude; // Get State Vessel = oapiGetFocusInterface(); Vessel->GetPMI(PMI); MaxThrust = Vessel->GetMaxThrust(ENGINE_ATTITUDE); Mass = Vessel->GetMass(); Size = Vessel->GetSize(); // Let's take care of the good case first :-) if ((fabs(DeltaAngle) < DeadbandLow)) { //sprintf(oapiDebugString(), "NULL"); if (fabs(RotRate) < RATE_NULL) { Vessel->SetAttitudeRotLevel(Axis, 0); return true; } return (NullRate(Axis)); } // CCK // Now, we actually have to DO something! ;-) Well divide it up into two cases, once // for each direction. There's probably a better way, but not right now :-) //if (fabs(DeltaAngle) < DEADBAND_MID) { // Rate = RATE_LOW; // sprintf(oapiDebugString(), "LOW"); //} else if(fabs(DeltaAngle) < DEADBAND_HIGH) { // Rate = RATE_MID; // sprintf(oapiDebugString(), "MID"); //} else { // Rate = RATE_HIGH; // sprintf(oapiDebugString(), "HIGH"); //} if (fabs(DeltaAngle) < DEADBAND_LOW) { Rate = RATE_FINE; //sprintf(oapiDebugString(), "FINE"); } else if (fabs(DeltaAngle) < DEADBAND_MID) { Rate = RATE_LOW; //sprintf(oapiDebugString(), "LOW"); } else if (fabs(DeltaAngle) < DEADBAND_HIGH) { Rate = RATE_MID; //sprintf(oapiDebugString(), "MID"); } else if (fabs(DeltaAngle) < DEADBAND_MAX) { Rate = RATE_HIGH; //sprintf(oapiDebugString(), "HIGH"); } else { Rate = RATE_MAX; //sprintf(oapiDebugString(), "MAX"); } // CCK End RateDeadband = min(Rate / 2, Radians(0.01/*2*/)); if (DeltaAngle < 0 ) { Rate = -Rate; RateDeadband = -RateDeadband; } DeltaRate = Rate - RotRate; if (DeltaAngle > 0) { if (DeltaRate > RateDeadband) { Thrust = (Mass * PMI.data[Axis] * DeltaRate) / (Size); Level = min((Thrust/MaxThrust), 1); Vessel->SetAttitudeRotLevel(Axis, Level); } else if (DeltaRate < -RateDeadband) { Thrust = (Mass * PMI.data[Axis] * DeltaRate) / (Size); Level = max((Thrust/MaxThrust), -1); Vessel->SetAttitudeRotLevel(Axis, Level); } else { Vessel->SetAttitudeRotLevel(Axis, 0); } } else { if (DeltaRate < RateDeadband) { Thrust = (Mass * PMI.data[Axis] * DeltaRate) / (Size); Level = max((Thrust/MaxThrust), -1); Vessel->SetAttitudeRotLevel(Axis, Level); } else if (DeltaRate > -RateDeadband) { Thrust = (Mass * PMI.data[Axis] * DeltaRate) / (Size); Level = min((Thrust/MaxThrust), 1); Vessel->SetAttitudeRotLevel(Axis, Level); } else { Vessel->SetAttitudeRotLevel(Axis, 0); } } return false; }