Advanced Question Adjusting Center of Gravity?

Ok.

you know, I was thinking... if it has to be realistic there we have to play a lot and I'll go to have a look to a solution for this. If you want just to not rotate regardless realism, what about something like

Code:
SetAngularVel(_V(0,0,0));

and that's it?
 
Well I did that. It stopped me from Horizon Level.

But when I fired main thrusts I still get pitch up and some x rotation

I did this so I could get level
Code:
	if (GetThrusterGroupLevel(THGROUP_MAIN)>0) SetAngularVel(_V(0, 0, 0));

But I get get a steady increase in pitch when I fire main thrusters

---------- Post added 01-11-16 at 05:58 AM ---------- Previous post was 01-10-16 at 07:33 PM ----------

This is what I get for angluar velocity
endurancedock1e_zpsszscmfx0.jpg


I have the code at the end of my
Code:
void ENDURANCE::clbkPostStep(double simt, double simdt, double mjd)
{
.....
VECTOR3 superStructCG,angvel;
	GetSuperstructureCG(superStructCG);
	//sprintf(oapiDebugString(), "x %d  y %d   z %d", superStructCG.x, superStructCG.y, superStructCG.z);
//	sprintf_s(oapiDebugString(), 255, "%s : %s:  %s", superStructCG.x, superStructCG.y, superStructCG.z;
	//void ShiftCG(superStructCG);
	GetAngularVel(angvel);
	SetAngularVel(_V(0, 0, 0));
	
	sprintf(oapiDebugString(), "x %d  y %d   z %d tx %d  ty %d   tz %d", superStructCG.x, superStructCG.y, superStructCG.z, angvel.x, angvel.y, angvel.z);

}
 
Last edited:
all right.

Some points:

- i don't know the power of your burn but careful that if you are getting away from a planet fast enough you will have 0 angular velocity but you will see pitch increasing (that's because you're getting away, not because you are rotating). I cannot know if this is the case, but check
- Instead of using %d why don't you use something like %.0f or %.1f, there is something that doesn't seem right to me in those numbers
- you can try to put the SetAngularVel call also/alternatively in the PreStep to see if that makes any difference in avoiding rotation
 
The stock Atlantis does auto-gimbaling of its upper SSME to compensate for thrust variations of the SRB's during ascent. Have a look into the OrbiterSDK Samples Atlantis.

I guess instead of calculating the engine angle from the thrust level you will need to calculate it from the COG offset. This would be like:

_V (thrust vector) =_V(cog location) - _V (thruster location)
(I guess you have to do it separately for x,y,z components)

Then calculate the vector length sqrt(dx² + dy² + dz²) and divide each direction (dx,dy,dz) / this length to normalize them.
The resulting vector should be the thrust vector for SetThrusterDir().


Sample from the Atlantis code:
Code:
void Atlantis::AutoMainGimbal ()
{
	// Implement automatic gimbal adjustment for main engines to correct for
	// SRB thrust variations. We adjust only the upper engine

	double        F_srb  = SRB_THRUST         *GetThrusterLevel (th_srb[0]);
	double        F_main = ORBITER_MAIN_THRUST*GetThrusterLevel (th_main[0]);
	if (F_main) {
		double        M_srb =   2.51951112*F_srb;  // angular moment from SRB thrust
		double        M_m2  = -12.02495   *F_main; // angular moment from the two lower main engines in neutral position
		double        M_0   = M_srb + M_m2;
		static double ry    =   9.42;  // upper main thruster: y-offset
		static double rz    = -23.295; // upper main thruster: z-offset
		static double ry2   = ry*ry;
		static double rz2   = rz*rz;
		double        F2    = F_main*F_main;
		double        M2    = M_0*M_0;
		double        term  = -M2 + F2*(ry2+rz2);
		double        arg1  = max (0.0, rz2 * term);
		double        scale = 1.0/(F_main*(ry2+rz2));
		double        dz    = (M_0*ry + sqrt (arg1))*scale;
		double		  arg2  = max (0.0, ry2 * term);
		double        dy    =-(M_0*rz + sqrt (arg2))*scale;
		if (!arg1 || !arg2) {
			double len = _hypot(dy,dz);
			dy /= len, dz /= len;
		}
		SetThrusterDir (th_main[2], _V(0,dy,dz));
	}
}
 
Thanks. How do you get _V(cogLocation)? Is that the get superstructure?

Also Would you need to do this on all rcs thruster?

---------- Post added at 03:54 PM ---------- Previous post was at 01:35 PM ----------

I added it to prestep
Code:
void ENDURANCE::clbkPreStep(double simtt, double simdt, double mjd)
{
	SetAngularVel(_V(0, 0, 0));

}

Code:
	th_main[0] = CreateThruster(_V(0, 0, 0), _V(0, 0, 1), MAXMAINTH, tank, ISP);
const double MAXMAINTH = 12503443;//4.0e5
endurancedock1f_zpsu8zmhba9.jpg
 
I added it to prestep
Code:
void ENDURANCE::clbkPreStep(double simtt, double simdt, double mjd)
{
	SetAngularVel(_V(0, 0, 0));

}

Code:
	th_main[0] = CreateThruster(_V(0, 0, 0), _V(0, 0, 1), MAXMAINTH, tank, ISP);
const double MAXMAINTH = 12503443;//4.0e5
endurancedock1f_zpsu8zmhba9.jpg

and it worked, right?
 
I would assume that GetSuperstructure gives the location of the CoG in relation to the current vessel's centre in its &cg vector. The thrust vector without unwanted rotation would then be vector tip (cg) - end (thruster location).

But honestly I assumed this would only be for the main thrusters.
For the RCS I would rather go for clever thruster locations, so that even in docked conditions the thruster groups produce the correct action. This might include putting RCS thrusters on booms extending from the vessel to increaase their leverage.

This was e.g. planned for the Artemis moon lander, where the RCS was on the ascent stage only, but this RCS had to be able to steer the whole stack, consisting of descent stage + ascent stage + Orion.
 
no. When I fire the main she pitches up.



---------- Post added 01-12-16 at 05:19 AM ---------- Previous post was 01-11-16 at 04:41 PM ----------

Another thing I noticed:
I had the ship and horizon level and no rotation. Docked a DG and she pitched down about 25 degrees.


endurancethrust_zpsvzetlrgv.jpg


Code:
	shift.x = (superStructCG.x)-0;
	shift.y = (superStructCG.y) - 0;
	shift.z = (superStructCG.z) - 0;


	double        dx2 = (sqrt(shift.x));
	double        dy2 = (sqrt(shift.y));
	double       dz2 = (sqrt(shift.z));
	double len = (dx2+dy2+dz2);
	double dx =(dx2/len);
	double dy = (dy2 / len);
	double dz = (dz2 / len);

	SetThrusterDir(th_main[0], _V(dx, dy, dz));

But as I apply forward thrust it pitches down badly

---------- Post added 01-13-16 at 04:54 AM ---------- Previous post was 01-12-16 at 05:19 AM ----------

This is what I have. Not sure if math is right.
th_main[0] = CreateThruster(_V(0, 0, 0), _V(0, 0, 1), MAXMAINTH, tank, ISP);

if the shift is negative then I get weird numbers

Code:
//bool GetSuperstructureCG(COG);   

	VECTOR3 superStructCG,angvel,shift;
	GetSuperstructureCG(superStructCG);
	//sprintf(oapiDebugString(), "x %d  y %d   z %d", superStructCG.x, superStructCG.y, superStructCG.z);
//	sprintf_s(oapiDebugString(), 255, "%s : %s:  %s", superStructCG.x, superStructCG.y, superStructCG.z;
	//void ShiftCG(superStructCG);
	GetAngularVel(angvel);
	//SetAngularVel(_V(0, 0, 0));
	
//	sprintf(oapiDebugString(), "x %.0f  y %.0f   z %.0f tx %.0f  ty %.0f   tz %.0f", superStructCG.x, superStructCG.y, superStructCG.z, angvel.x, angvel.y, angvel.z);
	
	shift.x = (superStructCG.x)-0;
	shift.y = (superStructCG.y) - 0;
	shift.z = (superStructCG.z) - 0;
	sprintf(oapiDebugString(), "x %.0f  y %.0f   z %.0f tx %.0f  ty %.0f   tz %.0f Sx %.0f  Sy %.0f   Sz %.0f", superStructCG.x, superStructCG.y, superStructCG.z, angvel.x, angvel.y, angvel.z, shift.x, shift.y, shift.z);


	double        dx2 = (sqrt(shift.x));
	double        dy2 = (sqrt(shift.y));
	double       dz2 = (sqrt(shift.z));
	double len = (dx2+dy2+dz2);
	double dx =(dx2/len);
	double dy = (dy2 / len);
	double dz = (dz2 / len);

	if ((superStructCG.x != 0) || (superStructCG.y != 0) || (superStructCG.z != 0)) SetThrusterDir(th_main[0], _V(dx, dy, dz));
	else SetThrusterDir(th_main[0], _V(0, 0, 1));
 
Last edited:
I have this:
Code:
VECTOR3 superStructCG;
	GetSuperstructureCG(superStructCG);
	sprintf(oapiDebugString(), "x %d  y %d   z %d", superStructCG.x, superStructCG.y, superStructCG.z);

With no vessel docked I get 0 0 0

When i dock a DG along the z axis the z value goes -

So how do I shift the COG so it is 0,0,0
You don't. The ShiftCG functions are only there to allow a vessel to register a shift of the centre of mass that isn't handled by Orbiter already (fuel tank depleting, etc.). When docking vessels together, Orbiter figures out directly the new centre of mass from the masses and relative positions of the individual vessels, and applies it accordingly. You should not use ShiftCG to undo that adjustment, just because it's more convenient to have the CoG at the origin of a particular vessel. The result would be unphysical behaviour (i.e. no rotation induced on thruster burn when really there should be). Likewise, adding a fake force vector with AddForce would be cheating, unless you actually put something in place that generates that force (other than a thruster, which is handled directly by Orbiter).


The stock Atlantis does auto-gimbaling of its upper SSME to compensate for thrust variations of the SRB's during ascent. Have a look into the OrbiterSDK Samples Atlantis.
In fact, the Atlantis code in the beta auto-gimbals all SSMEs and the SRBs, not only to compensate for thrust variations, but also to generate all commanded attitude changes. It uses a simple feedback loop (a damped harmonic oscillator). This should work also for this problem.

Thanks. How do you get _V(cogLocation)? Is that the get superstructure?

You don't. That would be cheating - unless you compute it yourself. You could for example recursively ask all docked vessels for their masses and relative positions, and then just compute the barycentre of all components.

But a more robust way would be to drive the gimbals with a feedback loop from the current angular velocity and acceleration. Otherwise you need to recompute the CoG continuously, since the component masses will change all the time.
 
Thanks. So I should use the gimbal code from the Atlantis?

I tried that with the main. of course it could be wrong.

So what do I need to do? I saw/read about the feedback loop
 
Thanks. So I should use the gimbal code from the Atlantis?

I tried that with the main. of course it could be wrong.

So what do I need to do? I saw/read about the feedback loop

Have a look at Atlantis::Autogimbal which sets the SSME gimbal positions for a given target rate. You want to compute the target torque

[math]
T = a (\omega-\omega_\mathrm{tgt}) + b \dot\omega
[/math]

where a and b are design parameters depending on your vessel specs (mass and inertia tensor), and omega is the angular velocity. Essentially, a defines the stiffness, and b the damping of your oscillator. Look up harmonic oscillator on wikipedia for details.

Then you translate the target torque into a gimbal position, depending on the layout of your thruster design. Note that not all thrusters may be able to generate torque in all three axes, depending on how close they are located to the axis around which you want to rotate. For example, to induce a roll moment using the Shuttle SSMEs (by pointing the left one up and the right one down or vice versa) is hard, because they are so close together. Gimballing the SRBs is much more efficient for roll commands.
 
ok. Don't I need to calculate that the main thrust vector would be with a docked vessel so when fired it goes straight and level?

Code:
	th_main[0] = CreateThruster(_V(0, 0, 0), _V(0, 0, 1), MAXMAINTH, tank, ISP);
	thg_main = CreateThrusterGroup(th_main, 1, THGROUP_MAIN);
calculate the difference from 0,0,0 and directs the main thrust so level flight is achieved.
// the vector seems off
Code:
	shift.x = (superStructCG.x)-0;
	shift.y = (superStructCG.y) - 0;
	shift.z = (superStructCG.z) - 0;
	sprintf(oapiDebugString(), "x %.0f  y %.0f   z %.0f tx %.0f  ty %.0f   tz %.0f Sx %.0f  Sy %.0f   Sz %.0f", superStructCG.x, superStructCG.y, superStructCG.z, angvel.x, angvel.y, angvel.z, shift.x, shift.y, shift.z);


	double        dx2 = (sqrt(shift.x));
	double        dy2 = (sqrt(shift.y));
	double       dz2 = (sqrt(shift.z));
	double len = (dx2+dy2+dz2);
	double dx =(dx2/len);
	double dy = (dy2 / len);
	double dz = (dz2 / len);

	if ((superStructCG.x != 0) || (superStructCG.y != 0) || (superStructCG.z != 0)) SetThrusterDir(th_main[0], _V(dx, dy, dz));
	else SetThrusterDir(th_main[0], _V(0, 0, 1));



Code:
void Atlantis::AutoMainGimbal ()
{
	// Implement automatic gimbal adjustment for main engines to correct for
	// SRB thrust variations. We adjust only the upper engine

	double        F_srb  = SRB_THRUST         *GetThrusterLevel (th_srb[0]);
	double        F_main = ORBITER_MAIN_THRUST*GetThrusterLevel (th_main[0]);
	if (F_main) {
		double        M_srb =   2.51951112*F_srb;  // angular moment from SRB thrust
		double        M_m2  = -12.02495   *F_main; // angular moment from the two lower main engines in neutral position
		double        M_0   = M_srb + M_m2;
		static double ry    =   9.42;  // upper main thruster: y-offset
		static double rz    = -23.295; // upper main thruster: z-offset
		static double ry2   = ry*ry;
		static double rz2   = rz*rz;
		double        F2    = F_main*F_main;
		double        M2    = M_0*M_0;
		double        term  = -M2 + F2*(ry2+rz2);
		double        arg1  = max (0.0, rz2 * term);
		double        scale = 1.0/(F_main*(ry2+rz2));
		double        dz    = (M_0*ry + sqrt (arg1))*scale;
		double		  arg2  = max (0.0, ry2 * term);
		double        dy    =-(M_0*rz + sqrt (arg2))*scale;
		if (!arg1 || !arg2) {
			double len = _hypot(dy,dz);
			dy /= len, dz /= len;
		}
		SetThrusterDir (th_main[2], _V(0,dy,dz));
	}
}
 
I am at a loss. I guess I can attach rather than dock but then you can't transfer crew,.....

I tried this cheat but I still spin out of control.
Code:
void ENDURANCE::clbkPreStep(double simtt, double simdt, double mjd)
{

	double thrusterlevel;
	thrusterlevel = GetThrusterLevel(th_main[0]);
	if (thrusterlevel>0) SetAngularVel(_V(0, 0, 0));

}
 
Well, do you know what a control loop is? Or control channels?

What martins is up to is this kind of function:

https://en.wikipedia.org/wiki/PID_controller

You can do this for pitch, yaw and bank individually, the outputs of the three channels then just must be projected on your thrusters.

What you just need for avoiding strange wobbling is a good first guess of the cg position for trimming your thrusters initially - setting the initial angles so the angular rates are not going wild when the thrusters fire, but instead stay in a region that your control loops handle without large oscillations.

If you have a too tightly controlling the attitude, you can actually have oscillations going out of control by resonance - your response is in the same phase with the spacecraft motion.
 
Yes. Let me retry the code part.

So let me see if I understand,
In a ideal ship when you apply forward thrust 0,0,1 the ship goes forward straight and level. COG (0,0,0)
So when a ship is docked that changes the COG

So don't we calculate the difference and adjust the vector to make straight and level flight?
 
Yes. Let me retry the code part.

So let me see if I understand,
In a ideal ship when you apply forward thrust 0,0,1 the ship goes forward straight and level. COG (0,0,0)
So when a ship is docked that changes the COG

So don't we calculate the difference and adjust the vector to make straight and level flight?

Yes. What I could suggest you to try is to create a small test project only for the control system development and learning the principles and code patterns. I would suspect your current project is progressed to far to ruin it with experiments.

Just make a simple rocket with two engines and then for example disable one engine by disconnecting it from the propellant source. And then observe how your PID reacts. Or use the keyboard for setting an intended attitude rate and observe how the PID tries to achieve it.

Just for learning, playing around. And once you have something that you like, start using a similar engine configuration and similar masses as the Endeavour. And play again. Cut engines. Add payloads. Try to fly by TVC only. Use different TVC trim angles for maneuvers.

And when you have that experiment done, you should have code that works and which you can easily include into your primary add-on project without many problems.

You could just calculate the vector of course. But I can tell you one good reason why you will not like the results:

It is dynamic data that will change during flight. When you query it, the input data is of time t0. When your calculated control outputs are applied, it gets propagated to t0 + deltat.

An adaptive algorithm like martins suggests does not care about the changes, it learns and compensates changes, if you have properly implemented it. When you undock a spacecraft during a burn (remember the Oberth maneuver at the end of the movie), the control loop will simply adapt to the changes, causing not more than a small vibration in the spacecraft.

And querying the superstructure cg is cheating. ;)
 
Thanks.

I will give her a shot.

So Martin had suggested the Atlantis auto gimbal.

So Use that code just for the main thrust since I don't have SRB
 
Thanks.

I will give her a shot.

So Martin had suggested the Atlantis auto gimbal.

So Use that code just for the main thrust since I don't have SRB

Yes, but in this case, because you need to understand something underlying the code, I would recommend you to write your own version of it, use your own variable names and even allow yourself to not be too optimized or brief.

If you just take the Atlantis code without understanding the concepts inside and around the code, you will fail to use it or wonder why it behaves strange. Making your own gives you the chance to go back one step and think about it again.

Also it is not that complicated or a high effort to do it yourself, since it is all rather a few lines of code, but when to execute which line of code and how to react to abnormal behavior is the thing you need to learn.
 
OK.
lots of questions.

How do I calculate or measure these?
Code:
double        M_m2 = -12.02495   *F_main; // angular moment from the two lower main engines in neutral position
		double        M_0 =  M_m2;
		static double ry = 9.42;  // upper main thruster: y-offset
		static double rz = -23.295; // upper main thruster: z-offset
 
OK.
lots of questions.

How do I calculate or measure these?

Well, the comments are generally pretty good there to help you, but this one is not correct:

angular moment

It is just scalar torque or moment, without the angular. Its just either radius multiplied by force (assuming radius is perpendicular to force) or that force vector is at an constant angle to the radius vector (in which case the 12.something is radius * cos(angle)) .

Again: Better make your own code and DON'T use the Atlantis example before you understood the basics. You are risking cargo cult coding otherwise.

If you are not understanding the basics - you will not notice what goes on.
 
Back
Top