Merge branch 'main' into mekf-fix
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
This commit is contained in:
commit
b4ace906bc
10
CHANGELOG.md
10
CHANGELOG.md
@ -16,6 +16,16 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Guidance now uses the coordinate functions from the FSFW.
|
||||||
|
- Idle should now point the STR away from the earth
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Fixed bugs in `Guidance::comparePtg` and corrected overloading
|
||||||
|
- Detumbling State Machine is now robust to commanded mode changes.
|
||||||
|
|
||||||
# [v7.6.0] 2024-01-30
|
# [v7.6.0] 2024-01-30
|
||||||
|
|
||||||
- Bumped `eive-tmtc` to v5.13.0
|
- Bumped `eive-tmtc` to v5.13.0
|
||||||
|
@ -70,6 +70,9 @@ static constexpr Event SAFE_RATE_VIOLATION = MAKE_EVENT(0, severity::MEDIUM);
|
|||||||
static constexpr Event PTG_RATE_VIOLATION = MAKE_EVENT(10, severity::MEDIUM);
|
static constexpr Event PTG_RATE_VIOLATION = MAKE_EVENT(10, severity::MEDIUM);
|
||||||
//! [EXPORT] : [COMMENT] The system has recovered from a rate rotation violation.
|
//! [EXPORT] : [COMMENT] The system has recovered from a rate rotation violation.
|
||||||
static constexpr Event RATE_RECOVERY = MAKE_EVENT(1, severity::MEDIUM);
|
static constexpr Event RATE_RECOVERY = MAKE_EVENT(1, severity::MEDIUM);
|
||||||
|
//! [EXPORT] : [COMMENT] The detumble transition has failed.
|
||||||
|
//! //! P1: Last detumble state before failure.
|
||||||
|
static constexpr Event DETUMBLE_TRANSITION_FAILED = MAKE_EVENT(11, severity::HIGH);
|
||||||
//! [EXPORT] : [COMMENT] Multiple RWs are invalid, uncommandable and therefore higher ACS modes
|
//! [EXPORT] : [COMMENT] Multiple RWs are invalid, uncommandable and therefore higher ACS modes
|
||||||
//! cannot be maintained.
|
//! cannot be maintained.
|
||||||
static constexpr Event MULTIPLE_RW_INVALID = MAKE_EVENT(2, severity::HIGH);
|
static constexpr Event MULTIPLE_RW_INVALID = MAKE_EVENT(2, severity::HIGH);
|
||||||
|
@ -420,8 +420,8 @@ void AcsController::performPointingCtrl() {
|
|||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case acs::PTG_IDLE:
|
case acs::PTG_IDLE:
|
||||||
guidance.targetQuatPtgSun(timeDelta, susDataProcessed.sunIjkModel.value, targetQuat,
|
guidance.targetQuatPtgIdle(timeAbsolute, timeDelta, susDataProcessed.sunIjkModel.value,
|
||||||
targetSatRotRate);
|
gpsDataProcessed.gpsPosition.value, targetQuat, targetSatRotRate);
|
||||||
guidance.comparePtg(quatBI, rotRateB, targetQuat, targetSatRotRate, errorQuat,
|
guidance.comparePtg(quatBI, rotRateB, targetQuat, targetSatRotRate, errorQuat,
|
||||||
errorSatRotRate, errorAngle);
|
errorSatRotRate, errorAngle);
|
||||||
ptgCtrl.ptgLaw(&acsParameters.idleModeControllerParameters, errorQuat, errorSatRotRate,
|
ptgCtrl.ptgLaw(&acsParameters.idleModeControllerParameters, errorQuat, errorSatRotRate,
|
||||||
@ -440,9 +440,9 @@ void AcsController::performPointingCtrl() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case acs::PTG_TARGET:
|
case acs::PTG_TARGET:
|
||||||
guidance.targetQuatPtgThreeAxes(timeAbsolute, timeDelta, gpsDataProcessed.gpsPosition.value,
|
guidance.targetQuatPtgTarget(timeAbsolute, timeDelta, gpsDataProcessed.gpsPosition.value,
|
||||||
gpsDataProcessed.gpsVelocity.value, targetQuat,
|
gpsDataProcessed.gpsVelocity.value, targetQuat,
|
||||||
targetSatRotRate);
|
targetSatRotRate);
|
||||||
guidance.comparePtg(quatBI, rotRateB, targetQuat, targetSatRotRate,
|
guidance.comparePtg(quatBI, rotRateB, targetQuat, targetSatRotRate,
|
||||||
acsParameters.targetModeControllerParameters.quatRef,
|
acsParameters.targetModeControllerParameters.quatRef,
|
||||||
acsParameters.targetModeControllerParameters.refRotRate, errorQuat,
|
acsParameters.targetModeControllerParameters.refRotRate, errorQuat,
|
||||||
@ -483,9 +483,8 @@ void AcsController::performPointingCtrl() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case acs::PTG_NADIR:
|
case acs::PTG_NADIR:
|
||||||
guidance.targetQuatPtgNadirThreeAxes(
|
guidance.targetQuatPtgNadir(timeAbsolute, timeDelta, gpsDataProcessed.gpsPosition.value,
|
||||||
timeAbsolute, timeDelta, gpsDataProcessed.gpsPosition.value,
|
gpsDataProcessed.gpsVelocity.value, targetQuat, targetSatRotRate);
|
||||||
gpsDataProcessed.gpsVelocity.value, targetQuat, targetSatRotRate);
|
|
||||||
guidance.comparePtg(quatBI, rotRateB, targetQuat, targetSatRotRate,
|
guidance.comparePtg(quatBI, rotRateB, targetQuat, targetSatRotRate,
|
||||||
acsParameters.nadirModeControllerParameters.quatRef,
|
acsParameters.nadirModeControllerParameters.quatRef,
|
||||||
acsParameters.nadirModeControllerParameters.refRotRate, errorQuat,
|
acsParameters.nadirModeControllerParameters.refRotRate, errorQuat,
|
||||||
@ -568,9 +567,16 @@ void AcsController::handleDetumbling() {
|
|||||||
break;
|
break;
|
||||||
case DetumbleState::DETUMBLE_FROM_PTG:
|
case DetumbleState::DETUMBLE_FROM_PTG:
|
||||||
triggerEvent(acs::PTG_RATE_VIOLATION);
|
triggerEvent(acs::PTG_RATE_VIOLATION);
|
||||||
|
detumbleTransitionCountdow.resetTimer();
|
||||||
detumbleState = DetumbleState::PTG_TO_SAFE_TRANSITION;
|
detumbleState = DetumbleState::PTG_TO_SAFE_TRANSITION;
|
||||||
break;
|
break;
|
||||||
case DetumbleState::PTG_TO_SAFE_TRANSITION:
|
case DetumbleState::PTG_TO_SAFE_TRANSITION:
|
||||||
|
if (detumbleTransitionCountdow.hasTimedOut()) {
|
||||||
|
triggerEvent(acs::DETUMBLE_TRANSITION_FAILED, 2);
|
||||||
|
detumbleCounter = 0;
|
||||||
|
detumbleState = DetumbleState::NO_DETUMBLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (mode == acs::AcsMode::SAFE) {
|
if (mode == acs::AcsMode::SAFE) {
|
||||||
detumbleState = DetumbleState::DETUMBLE_FROM_SAFE;
|
detumbleState = DetumbleState::DETUMBLE_FROM_SAFE;
|
||||||
}
|
}
|
||||||
@ -578,9 +584,14 @@ void AcsController::handleDetumbling() {
|
|||||||
case DetumbleState::DETUMBLE_FROM_SAFE:
|
case DetumbleState::DETUMBLE_FROM_SAFE:
|
||||||
detumbleCounter = 0;
|
detumbleCounter = 0;
|
||||||
// Triggers detumble mode transition in subsystem
|
// Triggers detumble mode transition in subsystem
|
||||||
triggerEvent(acs::SAFE_RATE_VIOLATION);
|
if (mode == acs::AcsMode::SAFE) {
|
||||||
startTransition(mode, acs::SafeSubmode::DETUMBLE);
|
triggerEvent(acs::SAFE_RATE_VIOLATION);
|
||||||
detumbleState = DetumbleState::IN_DETUMBLE;
|
startTransition(mode, acs::SafeSubmode::DETUMBLE);
|
||||||
|
detumbleState = DetumbleState::IN_DETUMBLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
triggerEvent(acs::DETUMBLE_TRANSITION_FAILED, 3);
|
||||||
|
detumbleState = DetumbleState::NO_DETUMBLE;
|
||||||
break;
|
break;
|
||||||
case DetumbleState::IN_DETUMBLE:
|
case DetumbleState::IN_DETUMBLE:
|
||||||
if (fusedRotRateData.rotRateTotal.isValid() and
|
if (fusedRotRateData.rotRateTotal.isValid() and
|
||||||
@ -885,6 +896,7 @@ ReturnValue_t AcsController::checkModeCommand(Mode_t mode, Submode_t submode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AcsController::modeChanged(Mode_t mode, Submode_t submode) {
|
void AcsController::modeChanged(Mode_t mode, Submode_t submode) {
|
||||||
|
guidance.resetValues();
|
||||||
if (mode == acs::AcsMode::SAFE) {
|
if (mode == acs::AcsMode::SAFE) {
|
||||||
{
|
{
|
||||||
PoolReadGuard pg(&rw1SpeedSet);
|
PoolReadGuard pg(&rw1SpeedSet);
|
||||||
@ -903,7 +915,12 @@ void AcsController::modeChanged(Mode_t mode, Submode_t submode) {
|
|||||||
rw4SpeedSet.setRwSpeed(0, 10);
|
rw4SpeedSet.setRwSpeed(0, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
guidance.resetValues();
|
if (submode == acs::SafeSubmode::DETUMBLE) {
|
||||||
|
detumbleState = DetumbleState::IN_DETUMBLE;
|
||||||
|
}
|
||||||
|
if (detumbleState == DetumbleState::IN_DETUMBLE and submode != acs::SafeSubmode::DETUMBLE) {
|
||||||
|
detumbleState = DetumbleState::NO_DETUMBLE;
|
||||||
|
}
|
||||||
return ExtendedControllerBase::modeChanged(mode, submode);
|
return ExtendedControllerBase::modeChanged(mode, submode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,6 +283,10 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
|||||||
|
|
||||||
// Initial delay to make sure all pool variables have been initialized their owners
|
// Initial delay to make sure all pool variables have been initialized their owners
|
||||||
Countdown initialCountdown = Countdown(INIT_DELAY);
|
Countdown initialCountdown = Countdown(INIT_DELAY);
|
||||||
|
|
||||||
|
// Countdown after which the detumbling mode change should have been finished
|
||||||
|
static constexpr dur_millis_t MAX_DURATION = 60 * 1e3;
|
||||||
|
Countdown detumbleTransitionCountdow = Countdown(MAX_DURATION);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MISSION_CONTROLLER_ACSCONTROLLER_H_ */
|
#endif /* MISSION_CONTROLLER_ACSCONTROLLER_H_ */
|
||||||
|
@ -4,415 +4,200 @@ Guidance::Guidance(AcsParameters *acsParameters_) { acsParameters = acsParameter
|
|||||||
|
|
||||||
Guidance::~Guidance() {}
|
Guidance::~Guidance() {}
|
||||||
|
|
||||||
[[deprecated]] void Guidance::targetQuatPtgSingleAxis(const timeval timeAbsolute, double posSatE[3],
|
void Guidance::targetQuatPtgIdle(timeval timeAbsolute, const double timeDelta,
|
||||||
double velSatE[3], double sunDirI[3],
|
const double sunDirI[3], const double posSatF[4],
|
||||||
double refDirB[3], double quatBI[4],
|
double targetQuat[4], double targetSatRotRate[3]) {
|
||||||
double targetQuat[4],
|
// positive z-Axis of EIVE in direction of sun
|
||||||
double targetSatRotRate[3]) {
|
double zAxisXI[3] = {0, 0, 0};
|
||||||
//-------------------------------------------------------------------------------------
|
VectorOperations<double>::normalize(sunDirI, zAxisXI, 3);
|
||||||
// Calculation of target quaternion to groundstation or given latitude, longitude and altitude
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// transform longitude, latitude and altitude to ECEF
|
|
||||||
double targetE[3] = {0, 0, 0};
|
|
||||||
|
|
||||||
MathOperations<double>::cartesianFromLatLongAlt(
|
// determine helper vector to point x-Axis and therefore the STR away from Earth
|
||||||
acsParameters->targetModeControllerParameters.latitudeTgt,
|
double helperXI[3] = {0, 0, 0}, posSatI[3] = {0, 0, 0};
|
||||||
acsParameters->targetModeControllerParameters.longitudeTgt,
|
CoordinateTransformations::positionEcfToEci(posSatF, posSatI, &timeAbsolute);
|
||||||
acsParameters->targetModeControllerParameters.altitudeTgt, targetE);
|
VectorOperations<double>::normalize(posSatI, helperXI, 3);
|
||||||
|
|
||||||
// target direction in the ECEF frame
|
// construct y-axis from helper vector and z-axis
|
||||||
double targetDirE[3] = {0, 0, 0};
|
double yAxisXI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::subtract(targetE, posSatE, targetDirE, 3);
|
VectorOperations<double>::cross(zAxisXI, helperXI, yAxisXI);
|
||||||
|
VectorOperations<double>::normalize(yAxisXI, yAxisXI, 3);
|
||||||
|
|
||||||
// transformation between ECEF and ECI frame
|
// x-axis completes RHS
|
||||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
double xAxisXI[3] = {0, 0, 0};
|
||||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
VectorOperations<double>::cross(yAxisXI, zAxisXI, xAxisXI);
|
||||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
VectorOperations<double>::normalize(xAxisXI, xAxisXI, 3);
|
||||||
MathOperations<double>::ecfToEciWithNutPre(timeAbsolute, *dcmEI, *dcmEIDot);
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
|
||||||
|
|
||||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
// join transformation matrix
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
double dcmXI[3][3] = {{xAxisXI[0], yAxisXI[0], zAxisXI[0]},
|
||||||
|
{xAxisXI[1], yAxisXI[1], zAxisXI[1]},
|
||||||
|
{xAxisXI[2], yAxisXI[2], zAxisXI[2]}};
|
||||||
|
QuaternionOperations::fromDcm(dcmXI, targetQuat);
|
||||||
|
|
||||||
// transformation between ECEF and Body frame
|
// calculate of reference rotation rate
|
||||||
double dcmBI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
targetRotationRate(timeDelta, targetQuat, targetSatRotRate);
|
||||||
double dcmBE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
|
|
||||||
QuaternionOperations::toDcm(quatBI, dcmBI);
|
|
||||||
MatrixOperations<double>::multiply(*dcmBI, *dcmIE, *dcmBE, 3, 3, 3);
|
|
||||||
|
|
||||||
// target Direction in the body frame
|
|
||||||
double targetDirB[3] = {0, 0, 0};
|
|
||||||
MatrixOperations<double>::multiply(*dcmBE, targetDirE, targetDirB, 3, 3, 1);
|
|
||||||
|
|
||||||
// rotation quaternion from two vectors
|
|
||||||
double refDir[3] = {0, 0, 0};
|
|
||||||
refDir[0] = acsParameters->targetModeControllerParameters.refDirection[0];
|
|
||||||
refDir[1] = acsParameters->targetModeControllerParameters.refDirection[1];
|
|
||||||
refDir[2] = acsParameters->targetModeControllerParameters.refDirection[2];
|
|
||||||
double noramlizedTargetDirB[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::normalize(targetDirB, noramlizedTargetDirB, 3);
|
|
||||||
VectorOperations<double>::normalize(refDir, refDir, 3);
|
|
||||||
double normTargetDirB = VectorOperations<double>::norm(noramlizedTargetDirB, 3);
|
|
||||||
double normRefDir = VectorOperations<double>::norm(refDir, 3);
|
|
||||||
double crossDir[3] = {0, 0, 0};
|
|
||||||
double dotDirections = VectorOperations<double>::dot(noramlizedTargetDirB, refDir);
|
|
||||||
VectorOperations<double>::cross(noramlizedTargetDirB, refDir, crossDir);
|
|
||||||
targetQuat[0] = crossDir[0];
|
|
||||||
targetQuat[1] = crossDir[1];
|
|
||||||
targetQuat[2] = crossDir[2];
|
|
||||||
targetQuat[3] = sqrt(pow(normTargetDirB, 2) * pow(normRefDir, 2) + dotDirections);
|
|
||||||
VectorOperations<double>::normalize(targetQuat, targetQuat, 4);
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// calculation of reference rotation rate
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
double velSatB[3] = {0, 0, 0}, velSatBPart1[3] = {0, 0, 0}, velSatBPart2[3] = {0, 0, 0};
|
|
||||||
// velocity: v_B = dcm_BI * dcmIE * v_E + dcm_BI * DotDcm_IE * v_E
|
|
||||||
MatrixOperations<double>::multiply(*dcmBE, velSatE, velSatBPart1, 3, 3, 1);
|
|
||||||
double dcmBEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MatrixOperations<double>::multiply(*dcmBI, *dcmIEDot, *dcmBEDot, 3, 3, 3);
|
|
||||||
MatrixOperations<double>::multiply(*dcmBEDot, posSatE, velSatBPart2, 3, 3, 1);
|
|
||||||
VectorOperations<double>::add(velSatBPart1, velSatBPart2, velSatB, 3);
|
|
||||||
|
|
||||||
double normVelSatB = VectorOperations<double>::norm(velSatB, 3);
|
|
||||||
double normRefSatRate = normVelSatB / normTargetDirB;
|
|
||||||
|
|
||||||
double satRateDir[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::cross(velSatB, targetDirB, satRateDir);
|
|
||||||
VectorOperations<double>::normalize(satRateDir, satRateDir, 3);
|
|
||||||
VectorOperations<double>::mulScalar(satRateDir, normRefSatRate, targetSatRotRate, 3);
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// Calculation of reference rotation rate in case of star tracker blinding
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
if (acsParameters->targetModeControllerParameters.avoidBlindStr) {
|
|
||||||
double sunDirB[3] = {0, 0, 0};
|
|
||||||
MatrixOperations<double>::multiply(*dcmBI, sunDirI, sunDirB, 3, 3, 1);
|
|
||||||
|
|
||||||
double exclAngle = acsParameters->strParameters.exclusionAngle,
|
|
||||||
blindStart = acsParameters->targetModeControllerParameters.blindAvoidStart,
|
|
||||||
blindEnd = acsParameters->targetModeControllerParameters.blindAvoidStop;
|
|
||||||
double sightAngleSun =
|
|
||||||
VectorOperations<double>::dot(acsParameters->strParameters.boresightAxis, sunDirB);
|
|
||||||
|
|
||||||
if (!(strBlindAvoidFlag)) {
|
|
||||||
double critSightAngle = blindStart * exclAngle;
|
|
||||||
if (sightAngleSun < critSightAngle) {
|
|
||||||
strBlindAvoidFlag = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (sightAngleSun < blindEnd * exclAngle) {
|
|
||||||
double normBlindRefRate = acsParameters->targetModeControllerParameters.blindRotRate;
|
|
||||||
double blindRefRate[3] = {0, 0, 0};
|
|
||||||
if (sunDirB[1] < 0) {
|
|
||||||
blindRefRate[0] = normBlindRefRate;
|
|
||||||
blindRefRate[1] = 0;
|
|
||||||
blindRefRate[2] = 0;
|
|
||||||
} else {
|
|
||||||
blindRefRate[0] = -normBlindRefRate;
|
|
||||||
blindRefRate[1] = 0;
|
|
||||||
blindRefRate[2] = 0;
|
|
||||||
}
|
|
||||||
VectorOperations<double>::add(blindRefRate, targetSatRotRate, targetSatRotRate, 3);
|
|
||||||
} else {
|
|
||||||
strBlindAvoidFlag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// revert calculated quaternion from qBX to qIX
|
|
||||||
double quatIB[4] = {0, 0, 0, 1};
|
|
||||||
QuaternionOperations::inverse(quatBI, quatIB);
|
|
||||||
QuaternionOperations::multiply(quatIB, targetQuat, targetQuat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Guidance::targetQuatPtgThreeAxes(const timeval timeAbsolute, const double timeDelta,
|
void Guidance::targetQuatPtgTarget(timeval timeAbsolute, const double timeDelta, double posSatF[3],
|
||||||
double posSatE[3], double velSatE[3], double targetQuat[4],
|
double velSatF[3], double targetQuat[4],
|
||||||
double targetSatRotRate[3]) {
|
double targetSatRotRate[3]) {
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Calculation of target quaternion for target pointing
|
// Calculation of target quaternion for target pointing
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// transform longitude, latitude and altitude to cartesian coordiantes (ECEF)
|
// transform longitude, latitude and altitude to cartesian coordiantes (ECEF)
|
||||||
double targetE[3] = {0, 0, 0};
|
double targetF[3] = {0, 0, 0};
|
||||||
MathOperations<double>::cartesianFromLatLongAlt(
|
MathOperations<double>::cartesianFromLatLongAlt(
|
||||||
acsParameters->targetModeControllerParameters.latitudeTgt,
|
acsParameters->targetModeControllerParameters.latitudeTgt,
|
||||||
acsParameters->targetModeControllerParameters.longitudeTgt,
|
acsParameters->targetModeControllerParameters.longitudeTgt,
|
||||||
acsParameters->targetModeControllerParameters.altitudeTgt, targetE);
|
acsParameters->targetModeControllerParameters.altitudeTgt, targetF);
|
||||||
double targetDirE[3] = {0, 0, 0};
|
double targetDirF[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::subtract(targetE, posSatE, targetDirE, 3);
|
VectorOperations<double>::subtract(targetF, posSatF, targetDirF, 3);
|
||||||
|
|
||||||
// transformation between ECEF and ECI frame
|
|
||||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::ecfToEciWithNutPre(timeAbsolute, *dcmEI, *dcmEIDot);
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
|
||||||
|
|
||||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
|
||||||
|
|
||||||
// target direction in the ECI frame
|
// target direction in the ECI frame
|
||||||
double posSatI[3] = {0, 0, 0}, targetI[3] = {0, 0, 0}, targetDirI[3] = {0, 0, 0};
|
double posSatI[3] = {0, 0, 0}, targetI[3] = {0, 0, 0}, targetDirI[3] = {0, 0, 0};
|
||||||
MatrixOperations<double>::multiply(*dcmIE, posSatE, posSatI, 3, 3, 1);
|
CoordinateTransformations::positionEcfToEci(posSatF, posSatI, &timeAbsolute);
|
||||||
MatrixOperations<double>::multiply(*dcmIE, targetE, targetI, 3, 3, 1);
|
CoordinateTransformations::positionEcfToEci(targetF, targetI, &timeAbsolute);
|
||||||
VectorOperations<double>::subtract(targetI, posSatI, targetDirI, 3);
|
VectorOperations<double>::subtract(targetI, posSatI, targetDirI, 3);
|
||||||
|
|
||||||
// x-axis aligned with target direction
|
// x-axis aligned with target direction
|
||||||
// this aligns with the camera, E- and S-band antennas
|
// this aligns with the camera, E- and S-band antennas
|
||||||
double xAxis[3] = {0, 0, 0};
|
double xAxisXI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::normalize(targetDirI, xAxis, 3);
|
VectorOperations<double>::normalize(targetDirI, xAxisXI, 3);
|
||||||
|
|
||||||
// transform velocity into inertial frame
|
// transform velocity into inertial frame
|
||||||
double velocityI[3] = {0, 0, 0}, velPart1[3] = {0, 0, 0}, velPart2[3] = {0, 0, 0};
|
double velSatI[3] = {0, 0, 0};
|
||||||
MatrixOperations<double>::multiply(*dcmIE, velSatE, velPart1, 3, 3, 1);
|
CoordinateTransformations::velocityEcfToEci(velSatF, posSatF, velSatI, &timeAbsolute);
|
||||||
MatrixOperations<double>::multiply(*dcmIEDot, posSatE, velPart2, 3, 3, 1);
|
|
||||||
VectorOperations<double>::add(velPart1, velPart2, velocityI, 3);
|
|
||||||
|
|
||||||
// orbital normal vector of target and velocity vector
|
// orbital normal vector of target and velocity vector
|
||||||
double orbitalNormalI[3] = {0, 0, 0};
|
double orbitalNormalI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::cross(posSatI, velocityI, orbitalNormalI);
|
VectorOperations<double>::cross(posSatI, velSatI, orbitalNormalI);
|
||||||
VectorOperations<double>::normalize(orbitalNormalI, orbitalNormalI, 3);
|
VectorOperations<double>::normalize(orbitalNormalI, orbitalNormalI, 3);
|
||||||
|
|
||||||
// y-axis of satellite in orbit plane so that z-axis is parallel to long side of picture
|
// y-axis of satellite in orbit plane so that z-axis is parallel to long side of picture
|
||||||
// resolution
|
// resolution
|
||||||
double yAxis[3] = {0, 0, 0};
|
double yAxisXI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::cross(orbitalNormalI, xAxis, yAxis);
|
VectorOperations<double>::cross(orbitalNormalI, xAxisXI, yAxisXI);
|
||||||
VectorOperations<double>::normalize(yAxis, yAxis, 3);
|
VectorOperations<double>::normalize(yAxisXI, yAxisXI, 3);
|
||||||
|
|
||||||
// z-axis completes RHS
|
// z-axis completes RHS
|
||||||
double zAxis[3] = {0, 0, 0};
|
double zAxisXI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::cross(xAxis, yAxis, zAxis);
|
VectorOperations<double>::cross(xAxisXI, yAxisXI, zAxisXI);
|
||||||
|
|
||||||
// join transformation matrix
|
// join transformation matrix
|
||||||
double dcmIX[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
double dcmIX[3][3] = {{xAxisXI[0], yAxisXI[0], zAxisXI[0]},
|
||||||
{xAxis[1], yAxis[1], zAxis[1]},
|
{xAxisXI[1], yAxisXI[1], zAxisXI[1]},
|
||||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
{xAxisXI[2], yAxisXI[2], zAxisXI[2]}};
|
||||||
QuaternionOperations::fromDcm(dcmIX, targetQuat);
|
QuaternionOperations::fromDcm(dcmIX, targetQuat);
|
||||||
|
|
||||||
int8_t timeElapsedMax = acsParameters->targetModeControllerParameters.timeElapsedMax;
|
targetRotationRate(timeDelta, targetQuat, targetSatRotRate);
|
||||||
targetRotationRate(timeElapsedMax, timeDelta, targetQuat, targetSatRotRate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Guidance::targetQuatPtgGs(const timeval timeAbsolute, const double timeDelta,
|
void Guidance::targetQuatPtgGs(timeval timeAbsolute, const double timeDelta, double posSatF[3],
|
||||||
double posSatE[3], double sunDirI[3], double targetQuat[4],
|
double sunDirI[3], double targetQuat[4],
|
||||||
double targetSatRotRate[3]) {
|
double targetSatRotRate[3]) {
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Calculation of target quaternion for ground station pointing
|
// Calculation of target quaternion for ground station pointing
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// transform longitude, latitude and altitude to cartesian coordiantes (ECEF)
|
// transform longitude, latitude and altitude to cartesian coordiantes (ECEF)
|
||||||
double groundStationE[3] = {0, 0, 0};
|
double posGroundStationF[3] = {0, 0, 0};
|
||||||
|
|
||||||
MathOperations<double>::cartesianFromLatLongAlt(
|
MathOperations<double>::cartesianFromLatLongAlt(
|
||||||
acsParameters->gsTargetModeControllerParameters.latitudeTgt,
|
acsParameters->gsTargetModeControllerParameters.latitudeTgt,
|
||||||
acsParameters->gsTargetModeControllerParameters.longitudeTgt,
|
acsParameters->gsTargetModeControllerParameters.longitudeTgt,
|
||||||
acsParameters->gsTargetModeControllerParameters.altitudeTgt, groundStationE);
|
acsParameters->gsTargetModeControllerParameters.altitudeTgt, posGroundStationF);
|
||||||
double targetDirE[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::subtract(groundStationE, posSatE, targetDirE, 3);
|
|
||||||
|
|
||||||
// transformation between ECEF and ECI frame
|
|
||||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::ecfToEciWithNutPre(timeAbsolute, *dcmEI, *dcmEIDot);
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
|
||||||
|
|
||||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
|
||||||
|
|
||||||
// target direction in the ECI frame
|
// target direction in the ECI frame
|
||||||
double posSatI[3] = {0, 0, 0}, groundStationI[3] = {0, 0, 0}, groundStationDirI[3] = {0, 0, 0};
|
double posSatI[3] = {0, 0, 0}, posGroundStationI[3] = {0, 0, 0}, groundStationDirI[3] = {0, 0, 0};
|
||||||
MatrixOperations<double>::multiply(*dcmIE, posSatE, posSatI, 3, 3, 1);
|
CoordinateTransformations::positionEcfToEci(posSatF, posSatI, &timeAbsolute);
|
||||||
MatrixOperations<double>::multiply(*dcmIE, groundStationE, groundStationI, 3, 3, 1);
|
CoordinateTransformations::positionEcfToEci(posGroundStationI, posGroundStationI, &timeAbsolute);
|
||||||
VectorOperations<double>::subtract(groundStationI, posSatI, groundStationDirI, 3);
|
VectorOperations<double>::subtract(posGroundStationI, posSatI, groundStationDirI, 3);
|
||||||
|
|
||||||
// negative x-axis aligned with target direction
|
// negative x-axis aligned with target direction
|
||||||
// this aligns with the camera, E- and S-band antennas
|
// this aligns with the camera, E- and S-band antennas
|
||||||
double xAxis[3] = {0, 0, 0};
|
double xAxisXI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::normalize(groundStationDirI, xAxis, 3);
|
VectorOperations<double>::normalize(groundStationDirI, xAxisXI, 3);
|
||||||
VectorOperations<double>::mulScalar(xAxis, -1, xAxis, 3);
|
VectorOperations<double>::mulScalar(xAxisXI, -1, xAxisXI, 3);
|
||||||
|
|
||||||
// get sun vector model in ECI
|
// get sun vector model in ECI
|
||||||
VectorOperations<double>::normalize(sunDirI, sunDirI, 3);
|
VectorOperations<double>::normalize(sunDirI, sunDirI, 3);
|
||||||
|
|
||||||
// calculate z-axis as projection of sun vector into plane defined by x-axis as normal vector
|
// calculate z-axis as projection of sun vector into plane defined by x-axis as normal vector
|
||||||
// z = sPerpenticular = s - sParallel = s - (x*s)/norm(x)^2 * x
|
// z = sPerpenticular = s - sParallel = s - (x*s)/norm(x)^2 * x
|
||||||
double xDotS = VectorOperations<double>::dot(xAxis, sunDirI);
|
double xDotS = VectorOperations<double>::dot(xAxisXI, sunDirI);
|
||||||
xDotS /= pow(VectorOperations<double>::norm(xAxis, 3), 2);
|
xDotS /= pow(VectorOperations<double>::norm(xAxisXI, 3), 2);
|
||||||
double sunParallel[3], zAxis[3];
|
double sunParallel[3], zAxisXI[3];
|
||||||
VectorOperations<double>::mulScalar(xAxis, xDotS, sunParallel, 3);
|
VectorOperations<double>::mulScalar(xAxisXI, xDotS, sunParallel, 3);
|
||||||
VectorOperations<double>::subtract(sunDirI, sunParallel, zAxis, 3);
|
VectorOperations<double>::subtract(sunDirI, sunParallel, zAxisXI, 3);
|
||||||
VectorOperations<double>::normalize(zAxis, zAxis, 3);
|
VectorOperations<double>::normalize(zAxisXI, zAxisXI, 3);
|
||||||
|
|
||||||
// y-axis completes RHS
|
// y-axis completes RHS
|
||||||
double yAxis[3];
|
double yAxisXI[3];
|
||||||
VectorOperations<double>::cross(zAxis, xAxis, yAxis);
|
VectorOperations<double>::cross(zAxisXI, xAxisXI, yAxisXI);
|
||||||
VectorOperations<double>::normalize(yAxis, yAxis, 3);
|
VectorOperations<double>::normalize(yAxisXI, yAxisXI, 3);
|
||||||
|
|
||||||
// join transformation matrix
|
// join transformation matrix
|
||||||
double dcmTgt[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
double dcmXI[3][3] = {{xAxisXI[0], yAxisXI[0], zAxisXI[0]},
|
||||||
{xAxis[1], yAxis[1], zAxis[1]},
|
{xAxisXI[1], yAxisXI[1], zAxisXI[1]},
|
||||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
{xAxisXI[2], yAxisXI[2], zAxisXI[2]}};
|
||||||
QuaternionOperations::fromDcm(dcmTgt, targetQuat);
|
QuaternionOperations::fromDcm(dcmXI, targetQuat);
|
||||||
|
|
||||||
int8_t timeElapsedMax = acsParameters->gsTargetModeControllerParameters.timeElapsedMax;
|
targetRotationRate(timeDelta, targetQuat, targetSatRotRate);
|
||||||
targetRotationRate(timeElapsedMax, timeDelta, targetQuat, targetSatRotRate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Guidance::targetQuatPtgSun(double timeDelta, double sunDirI[3], double targetQuat[4],
|
void Guidance::targetQuatPtgNadir(timeval timeAbsolute, const double timeDelta, double posSatE[3],
|
||||||
double targetSatRotRate[3]) {
|
double velSatE[3], double targetQuat[4], double refSatRate[3]) {
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// Calculation of target quaternion to sun
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// positive z-Axis of EIVE in direction of sun
|
|
||||||
double zAxis[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::normalize(sunDirI, zAxis, 3);
|
|
||||||
|
|
||||||
// assign helper vector (north pole inertial)
|
|
||||||
double helperVec[3] = {0, 0, 1};
|
|
||||||
|
|
||||||
// construct y-axis from helper vector and z-axis
|
|
||||||
double yAxis[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::cross(zAxis, helperVec, yAxis);
|
|
||||||
VectorOperations<double>::normalize(yAxis, yAxis, 3);
|
|
||||||
|
|
||||||
// x-axis completes RHS
|
|
||||||
double xAxis[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::cross(yAxis, zAxis, xAxis);
|
|
||||||
VectorOperations<double>::normalize(xAxis, xAxis, 3);
|
|
||||||
|
|
||||||
// join transformation matrix
|
|
||||||
double dcmTgt[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
|
||||||
{xAxis[1], yAxis[1], zAxis[1]},
|
|
||||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
|
||||||
QuaternionOperations::fromDcm(dcmTgt, targetQuat);
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// Calculation of reference rotation rate
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
int8_t timeElapsedMax = acsParameters->gsTargetModeControllerParameters.timeElapsedMax;
|
|
||||||
targetRotationRate(timeElapsedMax, timeDelta, targetQuat, targetSatRotRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[deprecated]] void Guidance::targetQuatPtgNadirSingleAxis(const timeval timeAbsolute,
|
|
||||||
double posSatE[3], double quatBI[4],
|
|
||||||
double targetQuat[4], double refDirB[3],
|
|
||||||
double refSatRate[3]) {
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Calculation of target quaternion for Nadir pointing
|
// Calculation of target quaternion for Nadir pointing
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
double targetDirE[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::mulScalar(posSatE, -1, targetDirE, 3);
|
|
||||||
|
|
||||||
// transformation between ECEF and ECI frame
|
|
||||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::ecfToEciWithNutPre(timeAbsolute, *dcmEI, *dcmEIDot);
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
|
||||||
|
|
||||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
|
||||||
|
|
||||||
// transformation between ECEF and Body frame
|
|
||||||
double dcmBI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmBE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
QuaternionOperations::toDcm(quatBI, dcmBI);
|
|
||||||
MatrixOperations<double>::multiply(*dcmBI, *dcmIE, *dcmBE, 3, 3, 3);
|
|
||||||
|
|
||||||
// target Direction in the body frame
|
|
||||||
double targetDirB[3] = {0, 0, 0};
|
|
||||||
MatrixOperations<double>::multiply(*dcmBE, targetDirE, targetDirB, 3, 3, 1);
|
|
||||||
|
|
||||||
// rotation quaternion from two vectors
|
|
||||||
double refDir[3] = {0, 0, 0};
|
|
||||||
refDir[0] = acsParameters->nadirModeControllerParameters.refDirection[0];
|
|
||||||
refDir[1] = acsParameters->nadirModeControllerParameters.refDirection[1];
|
|
||||||
refDir[2] = acsParameters->nadirModeControllerParameters.refDirection[2];
|
|
||||||
double noramlizedTargetDirB[3] = {0, 0, 0};
|
|
||||||
VectorOperations<double>::normalize(targetDirB, noramlizedTargetDirB, 3);
|
|
||||||
VectorOperations<double>::normalize(refDir, refDir, 3);
|
|
||||||
double normTargetDirB = VectorOperations<double>::norm(noramlizedTargetDirB, 3);
|
|
||||||
double normRefDir = VectorOperations<double>::norm(refDir, 3);
|
|
||||||
double crossDir[3] = {0, 0, 0};
|
|
||||||
double dotDirections = VectorOperations<double>::dot(noramlizedTargetDirB, refDir);
|
|
||||||
VectorOperations<double>::cross(noramlizedTargetDirB, refDir, crossDir);
|
|
||||||
targetQuat[0] = crossDir[0];
|
|
||||||
targetQuat[1] = crossDir[1];
|
|
||||||
targetQuat[2] = crossDir[2];
|
|
||||||
targetQuat[3] = sqrt(pow(normTargetDirB, 2) * pow(normRefDir, 2) + dotDirections);
|
|
||||||
VectorOperations<double>::normalize(targetQuat, targetQuat, 4);
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// Calculation of reference rotation rate
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
refSatRate[0] = 0;
|
|
||||||
refSatRate[1] = 0;
|
|
||||||
refSatRate[2] = 0;
|
|
||||||
|
|
||||||
// revert calculated quaternion from qBX to qIX
|
|
||||||
double quatIB[4] = {0, 0, 0, 1};
|
|
||||||
QuaternionOperations::inverse(quatBI, quatIB);
|
|
||||||
QuaternionOperations::multiply(quatIB, targetQuat, targetQuat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Guidance::targetQuatPtgNadirThreeAxes(const timeval timeAbsolute, const double timeDelta,
|
|
||||||
double posSatE[3], double velSatE[3],
|
|
||||||
double targetQuat[4], double refSatRate[3]) {
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// Calculation of target quaternion for Nadir pointing
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
// transformation between ECEF and ECI frame
|
|
||||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::ecfToEciWithNutPre(timeAbsolute, *dcmEI, *dcmEIDot);
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
|
||||||
|
|
||||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
|
||||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
|
||||||
|
|
||||||
// satellite position in inertial reference frame
|
// satellite position in inertial reference frame
|
||||||
double posSatI[3] = {0, 0, 0};
|
double posSatI[3] = {0, 0, 0};
|
||||||
MatrixOperations<double>::multiply(*dcmIE, posSatE, posSatI, 3, 3, 1);
|
CoordinateTransformations::positionEcfToEci(posSatE, posSatI, &timeAbsolute);
|
||||||
|
|
||||||
// negative x-axis aligned with position vector
|
// negative x-axis aligned with position vector
|
||||||
// this aligns with the camera, E- and S-band antennas
|
// this aligns with the camera, E- and S-band antennas
|
||||||
double xAxis[3] = {0, 0, 0};
|
double xAxisXI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::normalize(posSatI, xAxis, 3);
|
VectorOperations<double>::normalize(posSatI, xAxisXI, 3);
|
||||||
VectorOperations<double>::mulScalar(xAxis, -1, xAxis, 3);
|
VectorOperations<double>::mulScalar(xAxisXI, -1, xAxisXI, 3);
|
||||||
|
|
||||||
// make z-Axis parallel to major part of camera resolution
|
// make z-Axis parallel to major part of camera resolution
|
||||||
double zAxis[3] = {0, 0, 0};
|
double zAxisXI[3] = {0, 0, 0};
|
||||||
double velocityI[3] = {0, 0, 0}, velPart1[3] = {0, 0, 0}, velPart2[3] = {0, 0, 0};
|
double velSatI[3] = {0, 0, 0};
|
||||||
MatrixOperations<double>::multiply(*dcmIE, velSatE, velPart1, 3, 3, 1);
|
CoordinateTransformations::velocityEcfToEci(velSatE, posSatE, velSatI, &timeAbsolute);
|
||||||
MatrixOperations<double>::multiply(*dcmIEDot, posSatE, velPart2, 3, 3, 1);
|
VectorOperations<double>::cross(xAxisXI, velSatI, zAxisXI);
|
||||||
VectorOperations<double>::add(velPart1, velPart2, velocityI, 3);
|
VectorOperations<double>::normalize(zAxisXI, zAxisXI, 3);
|
||||||
VectorOperations<double>::cross(xAxis, velocityI, zAxis);
|
|
||||||
VectorOperations<double>::normalize(zAxis, zAxis, 3);
|
|
||||||
|
|
||||||
// y-Axis completes RHS
|
// y-Axis completes RHS
|
||||||
double yAxis[3] = {0, 0, 0};
|
double yAxisXI[3] = {0, 0, 0};
|
||||||
VectorOperations<double>::cross(zAxis, xAxis, yAxis);
|
VectorOperations<double>::cross(zAxisXI, xAxisXI, yAxisXI);
|
||||||
|
|
||||||
// join transformation matrix
|
// join transformation matrix
|
||||||
double dcmTgt[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
double dcmXI[3][3] = {{xAxisXI[0], yAxisXI[0], zAxisXI[0]},
|
||||||
{xAxis[1], yAxis[1], zAxis[1]},
|
{xAxisXI[1], yAxisXI[1], zAxisXI[1]},
|
||||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
{xAxisXI[2], yAxisXI[2], zAxisXI[2]}};
|
||||||
QuaternionOperations::fromDcm(dcmTgt, targetQuat);
|
QuaternionOperations::fromDcm(dcmXI, targetQuat);
|
||||||
|
|
||||||
int8_t timeElapsedMax = acsParameters->nadirModeControllerParameters.timeElapsedMax;
|
targetRotationRate(timeDelta, targetQuat, refSatRate);
|
||||||
targetRotationRate(timeElapsedMax, timeDelta, targetQuat, refSatRate);
|
}
|
||||||
|
|
||||||
|
void Guidance::targetRotationRate(const double timeDelta, double quatIX[4], double *refSatRate) {
|
||||||
|
if (VectorOperations<double>::norm(quatIXprev, 4) == 0) {
|
||||||
|
std::memcpy(quatIXprev, quatIX, sizeof(quatIXprev));
|
||||||
|
}
|
||||||
|
if (timeDelta != 0.0) {
|
||||||
|
QuaternionOperations::rotationFromQuaternions(quatIX, quatIXprev, timeDelta, refSatRate);
|
||||||
|
} else {
|
||||||
|
std::memcpy(refSatRate, ZERO_VEC3, 3 * sizeof(double));
|
||||||
|
}
|
||||||
|
std::memcpy(quatIXprev, quatIX, sizeof(quatIXprev));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
||||||
double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3],
|
double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3],
|
||||||
double errorQuat[4], double errorSatRotRate[3], double &errorAngle) {
|
double errorQuat[4], double errorSatRotRate[3], double &errorAngle) {
|
||||||
// First calculate error quaternion between current and target orientation
|
// First calculate error quaternion between current and target orientation without reference
|
||||||
double invTargetQuat[4] = {0, 0, 0, 0};
|
// quaternion
|
||||||
QuaternionOperations::inverse(targetQuat, invTargetQuat);
|
double errorQuatWoRef[4] = {0, 0, 0, 0};
|
||||||
QuaternionOperations::multiply(currentQuat, invTargetQuat, errorQuat);
|
QuaternionOperations::multiply(currentQuat, targetQuat, errorQuatWoRef);
|
||||||
// Last calculate add rotation from reference quaternion
|
// Then add rotation from reference quaternion
|
||||||
QuaternionOperations::multiply(refQuat, errorQuat, errorQuat);
|
QuaternionOperations::multiply(refQuat, errorQuatWoRef, errorQuat);
|
||||||
// Keep scalar part of quaternion positive
|
// Keep scalar part of quaternion positive
|
||||||
if (errorQuat[3] < 0) {
|
if (errorQuat[3] < 0) {
|
||||||
VectorOperations<double>::mulScalar(errorQuat, -1, errorQuat, 4);
|
VectorOperations<double>::mulScalar(errorQuat, -1, errorQuat, 4);
|
||||||
@ -435,30 +220,9 @@ void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], do
|
|||||||
void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
||||||
double targetSatRotRate[3], double errorQuat[4],
|
double targetSatRotRate[3], double errorQuat[4],
|
||||||
double errorSatRotRate[3], double &errorAngle) {
|
double errorSatRotRate[3], double &errorAngle) {
|
||||||
// First calculate error quaternion between current and target orientation
|
double refQuat[4] = {0, 0, 0, 1}, refSatRotRate[3] = {0, 0, 0};
|
||||||
QuaternionOperations::multiply(currentQuat, targetQuat, errorQuat);
|
comparePtg(currentQuat, currentSatRotRate, targetQuat, targetSatRotRate, refQuat, refSatRotRate,
|
||||||
// Keep scalar part of quaternion positive
|
errorQuat, errorSatRotRate, errorAngle);
|
||||||
if (errorQuat[3] < 0) {
|
|
||||||
VectorOperations<double>::mulScalar(errorQuat, -1, errorQuat, 4);
|
|
||||||
}
|
|
||||||
// Calculate error angle
|
|
||||||
errorAngle = QuaternionOperations::getAngle(errorQuat, true);
|
|
||||||
|
|
||||||
// Calculate error satellite rotational rate
|
|
||||||
VectorOperations<double>::subtract(currentSatRotRate, targetSatRotRate, errorSatRotRate, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Guidance::targetRotationRate(const int8_t timeElapsedMax, const double timeDelta,
|
|
||||||
double quatIX[4], double *refSatRate) {
|
|
||||||
if (VectorOperations<double>::norm(quatIXprev, 4) == 0) {
|
|
||||||
std::memcpy(quatIXprev, quatIX, sizeof(quatIXprev));
|
|
||||||
}
|
|
||||||
if (timeDelta != 0.0) {
|
|
||||||
QuaternionOperations::rotationFromQuaternions(quatIX, quatIXprev, timeDelta, refSatRate);
|
|
||||||
} else {
|
|
||||||
std::memcpy(refSatRate, ZERO_VEC3, 3 * sizeof(double));
|
|
||||||
}
|
|
||||||
std::memcpy(quatIXprev, quatIX, sizeof(quatIXprev));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Guidance::getDistributionMatrixRw(ACS::SensorValues *sensorValues,
|
ReturnValue_t Guidance::getDistributionMatrixRw(ACS::SensorValues *sensorValues,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef GUIDANCE_H_
|
#ifndef GUIDANCE_H_
|
||||||
#define GUIDANCE_H_
|
#define GUIDANCE_H_
|
||||||
|
|
||||||
|
#include <fsfw/coordinates/CoordinateTransformations.h>
|
||||||
#include <fsfw/datapool/PoolReadGuard.h>
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||||
@ -24,33 +25,18 @@ class Guidance {
|
|||||||
ReturnValue_t solarArrayDeploymentComplete();
|
ReturnValue_t solarArrayDeploymentComplete();
|
||||||
void resetValues();
|
void resetValues();
|
||||||
|
|
||||||
// Function to get the target quaternion and reference rotation rate from gps position and
|
void targetQuatPtgIdle(timeval timeAbsolute, const double timeDelta, const double sunDirI[3],
|
||||||
// position of the ground station
|
const double posSatF[4], double targetQuat[4], double targetSatRotRate[3]);
|
||||||
void targetQuatPtgSingleAxis(const timeval timeAbsolute, double posSatE[3], double velSatE[3],
|
void targetQuatPtgTarget(timeval timeAbsolute, const double timeDelta, double posSatF[3],
|
||||||
double sunDirI[3], double refDirB[3], double quatBI[4],
|
double velSatE[3], double quatIX[4], double targetSatRotRate[3]);
|
||||||
double targetQuat[4], double targetSatRotRate[3]);
|
void targetQuatPtgGs(timeval timeAbsolute, const double timeDelta, double posSatF[3],
|
||||||
void targetQuatPtgThreeAxes(const timeval timeAbsolute, const double timeDelta, double posSatE[3],
|
|
||||||
double velSatE[3], double quatIX[4], double targetSatRotRate[3]);
|
|
||||||
void targetQuatPtgGs(const timeval timeAbsolute, const double timeDelta, double posSatE[3],
|
|
||||||
double sunDirI[3], double quatIX[4], double targetSatRotRate[3]);
|
double sunDirI[3], double quatIX[4], double targetSatRotRate[3]);
|
||||||
|
void targetQuatPtgNadir(timeval timeAbsolute, const double timeDelta, double posSatF[3],
|
||||||
|
double velSatF[3], double targetQuat[4], double refSatRate[3]);
|
||||||
|
|
||||||
// Function to get the target quaternion and reference rotation rate for sun pointing after ground
|
void targetRotationRate(const double timeDelta, double quatInertialTarget[4],
|
||||||
// station
|
double *targetSatRotRate);
|
||||||
void targetQuatPtgSun(const double timeDelta, double sunDirI[3], double targetQuat[4],
|
|
||||||
double targetSatRotRate[3]);
|
|
||||||
|
|
||||||
// Function to get the target quaternion and refence rotation rate from gps position for Nadir
|
|
||||||
// pointing
|
|
||||||
void targetQuatPtgNadirSingleAxis(const timeval timeAbsolute, double posSatE[3], double quatBI[4],
|
|
||||||
double targetQuat[4], double refDirB[3], double refSatRate[3]);
|
|
||||||
void targetQuatPtgNadirThreeAxes(const timeval timeAbsolute, const double timeDelta,
|
|
||||||
double posSatE[3], double velSatE[3], double targetQuat[4],
|
|
||||||
double refSatRate[3]);
|
|
||||||
|
|
||||||
// @note: Calculates the error quaternion between the current orientation and the target
|
|
||||||
// quaternion, considering a reference quaternion. Additionally the difference between the actual
|
|
||||||
// and a desired satellite rotational rate is calculated, again considering a reference rotational
|
|
||||||
// rate. Lastly gives back the error angle of the error quaternion.
|
|
||||||
void comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
void comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
||||||
double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3],
|
double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3],
|
||||||
double errorQuat[4], double errorSatRotRate[3], double &errorAngle);
|
double errorQuat[4], double errorSatRotRate[3], double &errorAngle);
|
||||||
@ -58,11 +44,6 @@ class Guidance {
|
|||||||
double targetSatRotRate[3], double errorQuat[4], double errorSatRotRate[3],
|
double targetSatRotRate[3], double errorQuat[4], double errorSatRotRate[3],
|
||||||
double &errorAngle);
|
double &errorAngle);
|
||||||
|
|
||||||
void targetRotationRate(const int8_t timeElapsedMax, const double timeDelta,
|
|
||||||
double quatInertialTarget[4], double *targetSatRotRate);
|
|
||||||
|
|
||||||
// @note: will give back the pseudoinverse matrix for the reaction wheel depending on the valid
|
|
||||||
// reation wheel maybe can be done in "commanding.h"
|
|
||||||
ReturnValue_t getDistributionMatrixRw(ACS::SensorValues *sensorValues, double *rwPseudoInv);
|
ReturnValue_t getDistributionMatrixRw(ACS::SensorValues *sensorValues, double *rwPseudoInv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user