//------------------------------------------------------------------------------ void EndFiniteBurn::ValidateThrusters() { thrusters.clear(); for (std::vector<Spacecraft*>::iterator current = sats.begin(); current != sats.end(); ++current) { #ifdef DEBUG_EFB_THRUSTER MessageInterface::ShowMessage ("EndFiniteBurn::ValidateThrusters() entered, checking Spacecraft " "<%p>'%s' for Thrusters\n", *current, (*current)->GetName().c_str()); #endif StringArray thrusterNames = (*current)->GetStringArrayParameter( (*current)->GetParameterID("Thrusters")); StringArray engines = (maneuver)->GetStringArrayParameter( (maneuver)->GetParameterID("Thrusters")); #ifdef DEBUG_EFB_THRUSTER MessageInterface::ShowMessage (" Spacecraft has %d Thrusters and FiniteBurn has %d thrusters\n", thrusterNames.size(), engines.size()); #endif for (StringArray::iterator i = engines.begin(); i != engines.end(); ++i) { if (find(thrusterNames.begin(), thrusterNames.end(), *i) == thrusterNames.end()) { thrusters.clear(); throw CommandException("EndFiniteBurn: Spacecraft " + (*current)->GetName() + " does not have a thruster named \"" + (*i) + "\""); } Thruster* th = (Thruster*)((*current)->GetRefObject( Gmat::THRUSTER, *i)); if (th) { #ifdef DEBUG_EFB_THRUSTER MessageInterface::ShowMessage ("EndFiniteBurn::ValidateThrusters() addding the Thruster " "<%p>'%s' to thrusters\n", th, th->GetName().c_str()); #endif thrusters.push_back(th); } else { thrusters.clear(); throw CommandException("EndFiniteBurn: Thruster object \"" + (*i) + "\" was not set on Spacecraft \"" + (*current)->GetName() + "\""); } } } #ifdef DEBUG_EFB_THRUSTER MessageInterface::ShowMessage ("EndFiniteBurn::ValidateThrusters() leaving\n"); #endif }
//------------------------------------------------------------------------------ bool BeginFiniteBurn::Execute() { ValidateThrusters(); // Turn on all of the referenced thrusters #ifdef DEBUG_BEGIN_MANEUVER_EXE MessageInterface::ShowMessage ("BeginFiniteBurn::Execute() <%p>'%s' entered\n " "There are %d thruster(s) in use\n", this, GetGeneratingString(Gmat::NO_COMMENTS).c_str(), thrusters.size()); #endif for (std::vector<Thruster*>::iterator i = thrusters.begin(); i != thrusters.end(); ++i) { Thruster *th = *i; #ifdef DEBUG_BEGIN_MANEUVER_EXE MessageInterface::ShowMessage ("Activating engine <%p>'%s'\n", th, th->GetName().c_str()); #endif th->SetBooleanParameter(th->GetParameterID("IsFiring"), true); #ifdef DEBUG_BEGIN_MANEUVER_EXE MessageInterface::ShowMessage ("Checking to see if engine is active: returned %s\n", (th->GetBooleanParameter(th->GetParameterID("IsFiring")) ? "true" : "false")); #endif } // Tell active spacecraft that they are now firing for (std::vector<Spacecraft*>::iterator s=sats.begin(); s!=sats.end(); ++s) { (*s)->IsManeuvering(true); } if (transientForces == NULL) throw CommandException("Transient force list was NOT initialized; " "ABORTING RUN!!!\n\n"); // Insert the force into the list of transient forces if not found if (transientForces->size() == 0) { #ifdef DEBUG_TRANSIENT_FORCES MessageInterface::ShowMessage ("BeginFiniteBurn::Execute() Adding first burnForce<%p>'%s' to " "transientForces\n", burnForce, burnForce->GetName().c_str()); #endif transientForces->push_back(burnForce); } else { bool alreadyThere = false; for (std::vector<PhysicalModel*>::iterator i = transientForces->begin(); i !=transientForces->end(); ++i) { if ((*i)->IsOfType("FiniteThrust")) { FiniteThrust *transient = (FiniteThrust*)(*i); if (transient == burnForce) { alreadyThere = true; } if ((*transient) == (*burnForce)) { MessageInterface::ShowMessage("Burn activated by the line\n " "%s\noverlaps with an active finite burn. No new finite " "burn will be applied.\n", GetGeneratingString(Gmat::NO_COMMENTS).c_str()); alreadyThere = true; } } } if (alreadyThere == false) { #ifdef DEBUG_TRANSIENT_FORCES MessageInterface::ShowMessage("BeginFiniteBurn::Execute() Adding " "burnForce<%p>'%s' to transientForces\n", burnForce, burnForce->GetName().c_str()); #endif transientForces->push_back(burnForce); } } // Set maneuvering to Publisher so that any subscriber can do its own action if (!sats.empty()) { Real epoch = sats[0]->GetEpoch(); publisher->SetManeuvering(this, true, epoch, satNames, "begin of finite maneuver"); } #ifdef DEBUG_BEGIN_MANEUVER_EXE MessageInterface::ShowMessage ("There are %d transient force(s)\n", transientForces->size()); MessageInterface::ShowMessage("Current TransientForces list:\n"); for (std::vector<PhysicalModel*>::iterator j = transientForces->begin(); j != transientForces->end(); ++j) MessageInterface::ShowMessage(" %s\n", (*j)->GetName().c_str()); #endif BuildCommandSummary(true); return true; }
//------------------------------------------------------------------------------ bool EndFiniteBurn::Execute() { ValidateThrusters(); // Only do this if the FiniteBurn is the one this command controls... bool forceActive = false; for (std::vector<PhysicalModel*>::iterator j = transientForces->begin(); j != transientForces->end(); ++j) { if (((*j)->GetName()) == thrustName) { // ... and if it is set for the right spacecraft StringArray burnSatNames = (*j)->GetRefObjectNameArray(Gmat::SPACECRAFT); bool foundSats = false; UnsignedInt numberFound = 0; for (UnsignedInt i = 0; i < satNames.size(); ++i) { if (find(burnSatNames.begin(), burnSatNames.end(), satNames[i]) != burnSatNames.end()) { foundSats = true; ++numberFound; } } if (foundSats) { #ifdef DEBUG_TRANSIENT_FORCES MessageInterface::ShowMessage("EndFiniteBurn::Execute(): The burn " "is active\n"); #endif forceActive = true; if (numberFound != satNames.size()) MessageInterface::ShowMessage("*** WARNING *** Turning off the " "finite burn %s, but the EndFiniteBurn command did not " "list all of the spacecraft that are no longer " "maneuvering.\n", burnName.c_str()); break; } } } if (forceActive) { // Turn off all of the referenced thrusters for (std::vector<Thruster*>::iterator i = thrusters.begin(); i != thrusters.end(); ++i) { Thruster *th = *i; #ifdef DEBUG_END_MANEUVER_EXE MessageInterface::ShowMessage ("EndFiniteBurn::Execute() Deactivating engine <%p>'%s'\n", th, th->GetName().c_str()); #endif th->SetBooleanParameter(th->GetParameterID("IsFiring"), false); #ifdef DEBUG_END_MANEUVER_EXE MessageInterface::ShowMessage ("Checking to see if engine is inactive: returned %s\n", (th->GetBooleanParameter(th->GetParameterID("IsFiring")) ? "true" : "false")); #endif } // Tell active spacecraft that they are no longer firing for (std::vector<Spacecraft*>::iterator s=sats.begin(); s!=sats.end(); ++s) { #ifdef DEBUG_END_MANEUVER_EXE MessageInterface::ShowMessage ("EndFiniteBurn::Execute() Deactivating maneuvers on Spacecraft " "<%p>'%s'\n", *s, (*s)->GetName().c_str()); #endif /// todo: Be sure that no other maneuver has the spacecraft maneuvering; /// for R2013a this is not an issue since only 1 burn per spacecraft is /// allowed. We'll need to fix this when that restriction is removed. (*s)->IsManeuvering(false); } // Remove the force from the list of transient forces for (std::vector<PhysicalModel*>::iterator j = transientForces->begin(); j != transientForces->end(); ++j) { if (((*j)->GetName()) == thrustName) { #ifdef DEBUG_TRANSIENT_FORCES MessageInterface::ShowMessage ("EndFiniteBurn::Execute() Removing burnForce<%p>'%s' from " "transientForces\n", *j, (*j)->GetName().c_str()); #endif transientForces->erase(j); break; } } // Reset maneuvering to Publisher so that any subscriber can do its own action if (!sats.empty()) { Real epoch = sats[0]->GetEpoch(); publisher->SetManeuvering(this, false, epoch, satNames, "end of finite " "maneuver"); } #ifdef DEBUG_END_MANEUVER_EXE MessageInterface::ShowMessage("EndFiniteBurn::Execute() Current TransientForces list:\n"); for (std::vector<PhysicalModel*>::iterator j = transientForces->begin(); j != transientForces->end(); ++j) MessageInterface::ShowMessage(" %s\n", (*j)->GetName().c_str()); #endif } BuildCommandSummary(true); return true; }
//------------------------------------------------------------------------------ bool FiniteBurn::Fire(Real *burnData, Real epoch) { #ifdef DEBUG_FINITEBURN_FIRE MessageInterface::ShowMessage ("FiniteBurn::Fire() this<%p>'%s' entered, epoch=%f, spacecraft=<%p>'%s'\n", this, instanceName.c_str(), epoch, spacecraft, spacecraft ? spacecraft->GetName().c_str() : "NULL"); #endif if (isInitialized == false) Initialize(); if (!spacecraft) throw BurnException("Maneuver initial state undefined (No spacecraft?)"); // Accumulate the individual accelerations from the thrusters Real dm = 0.0, tMass, tOverM, *dir, norm; deltaV[0] = deltaV[1] = deltaV[2] = 0.0; Thruster *current; tMass = spacecraft->GetRealParameter("TotalMass"); #ifdef DEBUG_BURN_ORIGIN Real *satState = spacecraft->GetState().GetState(); MessageInterface::ShowMessage ("FiniteBurn Vectors:\n " "Sat = [%.15f %.15f %.15f %.15f %.15f %.15f]\n " "Frame = [%.15f %.15f %.15f\n " " %.15f %.15f %.15f\n " " %.15f %.15f %.15f]\n\n", satState[0], satState[1], satState[2], satState[3], satState[4], satState[5], frameBasis[0][0], frameBasis[0][1], frameBasis[0][2], frameBasis[1][0], frameBasis[1][1], frameBasis[1][2], frameBasis[2][0], frameBasis[2][1], frameBasis[2][2]); #endif for (StringArray::iterator i = thrusterNames.begin(); i != thrusterNames.end(); ++i) { #ifdef DEBUG_FINITE_BURN MessageInterface::ShowMessage (" Accessing thruster '%s' from spacecraft <%p>'%s'\n", (*i).c_str(), spacecraft, spacecraft->GetName().c_str()); #endif current = (Thruster *)spacecraft->GetRefObject(Gmat::THRUSTER, *i); if (!current) throw BurnException("FiniteBurn::Fire requires thruster named \"" + (*i) + "\" on spacecraft " + spacecraft->GetName()); // Save current thruster so that GetRefObject() can return it (LOJ: 2009.08.28) thrusterMap[current->GetName()] = current; // FiniteBurn class is friend of Thruster class, so we can access // member data directly current->ComputeInertialDirection(epoch); dir = current->inertialDirection; norm = sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]); #ifdef DEBUG_FINITE_BURN MessageInterface::ShowMessage (" Thruster Direction: %.15f %.15f %.15f\n" " norm: %.15f\n", dir[0], dir[1], dir[2], norm); #endif if (norm == 0.0) throw BurnException("FiniteBurn::Fire thruster " + (*i) + " on spacecraft " + spacecraft->GetName() + " has no direction."); dm += current->CalculateMassFlow(); //tOverM = current->thrust / (tMass * norm * 1000.0); //old code tOverM = current->thrust * current->thrustScaleFactor * current->dutyCycle / (tMass * norm * 1000.0); deltaV[0] += dir[0] * tOverM; deltaV[1] += dir[1] * tOverM; deltaV[2] += dir[2] * tOverM; #ifdef DEBUG_FINITE_BURN MessageInterface::ShowMessage(" Thruster %s = %s details:\n", (*i).c_str(), current->GetName().c_str()); MessageInterface::ShowMessage( " thrust = %.15f\n" " dM = %.15e\n Mass = %.15f\n" " TSF = %.15f\n |Acc| = %.15e\n " "Acc = [%.15e %.15e %.15e]\n", current->thrust, dm, tMass, current->thrustScaleFactor, tOverM, deltaV[0], deltaV[1], deltaV[2]); #endif } // Build the acceleration burnData[0] = deltaV[0]*frameBasis[0][0] + deltaV[1]*frameBasis[0][1] + deltaV[2]*frameBasis[0][2]; burnData[1] = deltaV[0]*frameBasis[1][0] + deltaV[1]*frameBasis[1][1] + deltaV[2]*frameBasis[1][2]; burnData[2] = deltaV[0]*frameBasis[2][0] + deltaV[1]*frameBasis[2][1] + deltaV[2]*frameBasis[2][2]; burnData[3] = dm; #ifdef DEBUG_FINITEBURN_FIRE MessageInterface::ShowMessage( "FiniteBurn::Fire() this<%p>'%s' returning\n" " Acceleration: %.15e %.15e %.15e dm: %.15e\n", this, GetName().c_str(), burnData[0], burnData[1], burnData[2], dm); #endif hasFired = true; epochAtLastFire = epoch; return true; }