Advanced Question Firing RCS thruster to keep ship towards Earth

fausto

FOI SuperMod
Joined
Jul 13, 2008
Messages
797
Reaction score
2
Points
0
Location
Monza (Milan)
Hi all!
My goal is to fire RCS thrusters in order to rotate the vessel and keep it towards Earth. I want to do it exactly as Attitude MFD does, and i gave a look to the avaiable source code. After days of battle, I isolated a function which I think is the center of what i want to do. It's the following one:

Code:
if (etonoff==ENGAGED)
	{
		// Use different function calls to SetAttitude for the rotating reference vector cases than the static reference vector cases
		if ( (fabs(PitchYawRoll.data[YAW]) + fabs(PitchYawRoll.data[PITCH])) > DEADBAND_MAX ) {
			SetAttitude(0, PitchYawRoll.data[PITCH], PITCH, DB_COARSE, RATE_NULL_HIGH, LastTimeElapsed);
			SetAttitude(0, PitchYawRoll.data[YAW], YAW, DB_COARSE, RATE_NULL_HIGH, LastTimeElapsed);
			SetAttitude(0, 0, ROLL, DB_COARSE, RATE_NULL_HIGH, TimeElapsed);
		}
		else {
			if ((RefMode == VELOCITY)||(RefMode == TARGET_RELATIVE)) {
				SetAttitude(0, PitchYawRoll.data[PITCH], PitchYawRollRate.data[PITCH], PITCH, DB_FINE, RATE_NULL_HIGH, LastTimeElapsed);
				SetAttitude(0, PitchYawRoll.data[YAW], PitchYawRollRate.data[YAW], YAW, DB_FINE, RATE_NULL_HIGH, LastTimeElapsed);
				SetAttitude(0, PitchYawRoll.data[ROLL], PitchYawRollRate.data[ROLL], ROLL, DB_FINE, RATE_NULL_HIGH, LastTimeElapsed);
			}
			else {
				SetAttitude(0, PitchYawRoll.data[PITCH], PITCH, DB_MIN, RATE_NULL_LOW, LastTimeElapsed);
				SetAttitude(0, PitchYawRoll.data[YAW], YAW, DB_MIN, RATE_NULL_LOW, LastTimeElapsed);
				SetAttitude(0, PitchYawRoll.data[ROLL], ROLL, DB_MIN, RATE_NULL_LOW, LastTimeElapsed);
			}
		}
	}

etonoff is the condition of earth tracking activation, and I call it in clbkPreStep. I can compile it and it's a good result. The problem is, when I activate it, RCS thrusters start a pitch firing and they don't stop at all!! The vessel rotates over and over again!!
This function is void inline AttitudeMFD::Control() inside attitude MFD source code..
 

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,580
Reaction score
2
Points
0
When do you update PitchYawRoll.data ? The behavior you describe is consistent with either:
- not updating the target as you rotate, so the controller thinks you're still aiming for the original offset, so it keeps going
- not properly feeding the target into the controller, so what it's aiming at isn't what you want it to be aiming at
 

fausto

FOI SuperMod
Joined
Jul 13, 2008
Messages
797
Reaction score
2
Points
0
Location
Monza (Milan)
This function should be very useful to you. Simply get the relative position of Earth to your vessel, normalize it, and then use that as your target vector.

http://www.orbiter-forum.com/showthread.php?t=27280

Thanks a lot!! :) Very useful line codes! I look at that immediately!

---------- Post added at 06:50 PM ---------- Previous post was at 06:03 PM ----------

Little problem:
I have this one:

Code:
Global2Local(antares::RotateVector((rVel+gPos),horizon,90), vNormal);

RotateVector is not a vessel member, so I can't compile it..
 

malisle

Donator
Donator
Joined
Jul 8, 2012
Messages
110
Reaction score
0
Points
16
Here is something I made recently - it orients the vessel's back toward the Sun by firing its RCS thrusters. After everything is aligned it keeps the vessel aligned by using SetRotationMatrix() to keep it stable at higher time compressions (100 000x in equatorial orbit arround Earth without problems). Most of the code was taken from threads similar to this one, I just combined it.

some constants&stuff
Code:
VECTOR3 g1			={0,1,0};				// point in global coordinate system, later used to construct global "up" vector for use in autopilot
VECTOR3 g2			={0,0,0};				// point in global coordinate system, later used to construct global "up" vector for use in autopilot
int atpstpflag		=1;						// autopilot step flag, used for jumping through different stages of autopilot
int atpabrtflag		=0;						// autopilot abort flag, used for turning attitude thrusters off in case user turns autopilot off before atpstpflag==3

this is called later on
Code:
void shipname::f_orientation(void)
{
	Global2Local(g1,l1);
	Global2Local(g2,l2);
	l1=l1/length(l1);
	l2=l2/length(l2);
	VECTOR3 vector=_V(l1.x-l2.x,l1.y-l2.y,l1.z-l2.z);  //global up vector in local coordinate system, used to get roll,yaw,pitch relative to the sun
	double Roll = acos(vector.y/(sqrt(pow(vector.x,2)+pow(vector.y,2)+pow(vector.z,2))));				
	double Pitch = l1.y;
	double Yaw = l1.x;
	orient= _V(Yaw,Pitch,Roll);
}
in clbkPreStep:
Code:
if(bstatus!=0 && atpabrtflag==0) // Activator
	{
		if (atpstpflag==1) //autopilot step flag (1=get pitch&yaw to zero, then roll, 2=turn all thrusters off, 3=keep the nose oriented towards sun without using the thrusters for stability at higher time compressions)
		{
				VECTOR3 vector= orient;								// placeholder vector for receiving orientation data from function that does that
				double Roll = vector.z;									// relative to global up (+y axis)
				double Pitch = vector.y;								// relative to the Suns ecliptic plane
				double Yaw = vector.x;									// relative to the Suns ecliptic plane
				GetAngularVel (avel);									// angular velocity, used as "D" in PD regulator

				static double prevYaw = Yaw;
				static double prevPitch = Pitch;
				static double prevRoll = Roll;
				static double prevSimT = 0;

				double YawThrust = 0;
				double PitchThrust = 0;
				double RollThrust = 0;

				double dYawT	= (Yaw - prevYaw) / (simt - prevSimT);
				double dPitchT	= (Pitch - prevPitch) / (simt - prevSimT);
				double dRollT	= avel.z;
	

					YawThrust = -10*Yaw - 25*dYawT;
					if (YawThrust > 1.0) YawThrust = 1.0;
					if (YawThrust < -1.0) YawThrust = -1.0;                                            
					if (YawThrust>0)
						{
						SetThrusterGroupLevel(THGROUP_ATT_YAWRIGHT, abs(YawThrust));
						SetThrusterGroupLevel(THGROUP_ATT_YAWLEFT, 0);
						}
					else
						{
						SetThrusterGroupLevel(THGROUP_ATT_YAWLEFT, abs(YawThrust));
						SetThrusterGroupLevel(THGROUP_ATT_YAWRIGHT, 0);
						}


					PitchThrust = -10*Pitch - 25*dPitchT;
					if (PitchThrust > 1.0) PitchThrust = 1.0;
					if (PitchThrust < -1.0) PitchThrust = -1.0;                                            
					if(PitchThrust>0)
						{
						SetThrusterGroupLevel(THGROUP_ATT_PITCHUP, abs(PitchThrust));
						SetThrusterGroupLevel(THGROUP_ATT_PITCHDOWN, 0);
						}
					else
						{
						SetThrusterGroupLevel(THGROUP_ATT_PITCHDOWN, abs(PitchThrust));
						SetThrusterGroupLevel(THGROUP_ATT_PITCHUP, 0);
						}
	

				if (abs(Yaw)<0.001 && abs(dYawT)<0.001 && abs(Pitch)<0.001 && abs(dPitchT)<0.001)  //this takes some time to achieve (~5-10s), but there is no ugly jump from orientation achieved by autopilot to the one defined by SetRotationMatrix() 
				{
						RollThrust = -10*Roll - 25*dRollT;
						if (RollThrust > 1.0) RollThrust = 1.0;
						if (RollThrust < -1.0) RollThrust = -1.0;                                            
						if (RollThrust > 0)
							{
							SetThrusterGroupLevel(THGROUP_ATT_BANKRIGHT, abs(RollThrust));
							SetThrusterGroupLevel(THGROUP_ATT_BANKLEFT, 0);
							}
						else
							{
							SetThrusterGroupLevel(THGROUP_ATT_BANKLEFT, abs(RollThrust));
							SetThrusterGroupLevel(THGROUP_ATT_BANKRIGHT, 0);
							}
				}

				prevYaw = Yaw;
				prevPitch = Pitch;
				prevRoll = Roll;
				prevSimT = simt;
				if (abs(Yaw)<0.005 && abs(dYawT)<.005 && abs(Pitch)<.005 && abs(dPitchT)<.005 && abs(Roll)<.005 && abs(dRollT)<.005) atpstpflag=2;
		}

		if(atpstpflag==2)
		{
			SetThrusterGroupLevel(THGROUP_ATT_PITCHUP,	0);
			SetThrusterGroupLevel(THGROUP_ATT_PITCHDOWN,0);
			SetThrusterGroupLevel(THGROUP_ATT_BANKRIGHT,0);
			SetThrusterGroupLevel(THGROUP_ATT_BANKLEFT,	0);
			SetThrusterGroupLevel(THGROUP_ATT_YAWRIGHT,	0);
			SetThrusterGroupLevel(THGROUP_ATT_YAWLEFT,	0);
			atpstpflag=3;
		}

		if(atpstpflag==3)
		{
			OBJHANDLE sun=oapiGetObjectByName("Sun");
			VECTOR3 vesselPos, rspos, dNC, d1, d2, d3;
			oapiGetGlobalPos(sun, &rspos);
			oapiGetGlobalPos(GetHandle(), &vesselPos);
			d3=rspos-vesselPos;            
			d3=-d3/length(d3);
			dNC=_V(0,1,0);
			d1 = crossp(dNC, d3);
			d1=d1/length(d1);
			d2 = crossp(d3, d1);
			for (int i = 0; i < 3; i++) 
			avel.data[i] = 0.0;
			SetAngularVel (avel);
			SetRotationMatrix(_M(d1.x,d2.x,d3.x,d1.y,d2.y,d3.y,d1.z,d2.z,d3.z));	   
		}	
  }
  else if (atpabrtflag!=0)
  {
		SetThrusterGroupLevel(THGROUP_ATT_PITCHUP,	0);
		SetThrusterGroupLevel(THGROUP_ATT_PITCHDOWN,0);
		SetThrusterGroupLevel(THGROUP_ATT_BANKRIGHT,0);
		SetThrusterGroupLevel(THGROUP_ATT_BANKLEFT,	0);
		SetThrusterGroupLevel(THGROUP_ATT_YAWRIGHT,	0);
		SetThrusterGroupLevel(THGROUP_ATT_YAWLEFT,	0);
  }
}
 
Last edited:

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,580
Reaction score
2
Points
0
Little problem:
I have this one:

Code:
Global2Local(antares::RotateVector((rVel+gPos),horizon,90), vNormal);

RotateVector is not a vessel member, so I can't compile it..
-> is how you access members of an object pointer, not ::.
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
RotateVector is not a vessel member, so I can't compile it..

Oops sorry about that. RotateVector is from a special orbitermath.h file that I forgot to include in the original thread.

Here is what it looks like...

Code:
// --------------------------------------------------------------
// Rotate inputed coordinates around an arbitrary axis
// --------------------------------------------------------------
VECTOR3 RotateVector (const VECTOR3 &input, double angle, const VECTOR3 &rotationaxis) 
{
	// To rotate a vector in 3D space we'll need to build a matrix, these are the variables required to do so.
	// NOTE: this version of the function takes it's input angle in Radians

	double c = cos(angle);
	double s = sin(angle);
	double t = 1.0 - c;
	double x = rotationaxis.x;
	double y = rotationaxis.y;
	double z = rotationaxis.z;

	// Build rotation matrix
	MATRIX3 rMatrix;
	rMatrix.m11 = (t * x * x + c);
	rMatrix.m12 = (t * x * y - s * z);
	rMatrix.m13 = (t * x * z + s * y);
	rMatrix.m21 = (t * x * y + s * z);
	rMatrix.m22 = (t * y * y + c);
	rMatrix.m23 = (t * y * z - s * x);
	rMatrix.m31 = (t * x * z - s * y);
	rMatrix.m32 = (t * y * z + s * x);
	rMatrix.m33 = (t * z * z + c);

	// Perform Rotation
	VECTOR3 output = mul (rMatrix, input); // multiply the input vector by our rotation matrix to get our output vector
	return output; // Return rotated vector

} // End "RotateVector"
 
Last edited:

fausto

FOI SuperMod
Joined
Jul 13, 2008
Messages
797
Reaction score
2
Points
0
Location
Monza (Milan)
I get very good results: now RCS thrusters ignite and are able to find a precise position.. but my autopilot is still wrong..
I noticed that your code finds a prograde and normal/antinormal vector, and this is not what i'm looking for.. i need a vector toward my target body.
For example i see that you have:

Code:
Global2Local((rVel + gPos), vPrograde);

VECTOR3 horizon = crossp(rVel,rPos);
Global2Local((antares::RotateVector((rVel+gPos),90,horizon)), vNormal);

the first one is prograde vector, the second one is the orbit normal vector, found after horizon calculation with crossp(rVel,rPos).
And what about calculating the "towards" vector?
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
I think one of us missed something.

The "OrientForBurn()" function does not find earth, it simply aligns the vessel with an inputed target vector. It's up to you to tell it what vector you want to target, otherwise it will just orient you prograde.

If you want it to point you towards earth simply call it as

Code:
OrientForBurn (directionofearthinlocalframe)
 

fausto

FOI SuperMod
Joined
Jul 13, 2008
Messages
797
Reaction score
2
Points
0
Location
Monza (Milan)
I found that vector! Now my vessel points perfectly towards Earth!
Thanks a lot!:thumbup:
 
Top