MechJeb2

MechJeb2

4M Downloads

Change the calculating of the ship MoI

sarbian opened this issue · 23 comments

commented

I think the way the ship MoI is calculated is wrong, and I may have a fix.
( non native English incoming)

I did some tinkering with ORDA last month and found out that its formula was wrong too.
So I built some testing module in ORDA. I used a ship without RCS. With no RCS I know that the only way to make it turn is with the CommandModule rotpower.
The rotPower is in kN and applied to the CoM of the ship, so it s the torque applied on the axis

  • I stop de ship rotation
  • Make it turn at full power on 1 axis for t=10s
  • Check the angular velocity on this axis

The rotation formula are
angular velocity = angular acceleration * time
Torque = Moment of Inertia * angular acceleration
so Moment of Inertia = time * Torque / angular velocity

With that I get the MoI for this axis. Then I tried to find a formula that gave me the same number using the ship part info. This code is the closest every time.
I tested it with light & heavy ships, and non symmetric ships.

MoI = Vector3.zero;
foreach (Part p in vessel.parts)
            {
                    double partMass = p.TotalMass();
                if (p.Rigidbody != null)
                {
                    Vector3 partPosition = vessel.transform.InverseTransformDirection(p.Rigidbody.worldCenterOfMass - CoM);
                    MoI += p.Rigidbody.inertiaTensorRotation * p.Rigidbody.inertiaTensor;
                    MoI += new Vector3d(
                    (partPosition.y * partPosition.y + partPosition.z * partPosition.z) * p.TotalMass(),
                    (partPosition.z * partPosition.z + partPosition.x * partPosition.x) * p.TotalMass(),
                    (partPosition.x * partPosition.x + partPosition.y * partPosition.y) * p.TotalMass()
                    );
                }
}

With this change and some tuning of the Attitude PID maybe mechjeb2 can turn the ships even better :)

commented

This looks very nice! I think you are right that the Vessel.findLocalMOI function we are using has some deficiencies; maybe it doesn't take into account the parts' inertiaTensors? That can particularly be a problem for the roll axis, where for a single-stack rocket all of moment of inertia around the roll axis comes from the parts' inertia tensors.

We will try this out; thanks very much for the code! :)

commented

Happily, I don't think it matters where the command pod torque gets applied; for the purposes of this calculation, it's all torque.

commented

"The rotPower is ... applied to the CoM of the ship"

That's definitely not accurate if my space station is anything to judge by. There are two command pods at one end, and a whole bunch of large fuel tanks at the other end, with a fair amount of stuff in between that allows for bending and twisting. If I leave RCS off and try to roll the station around its axis, I can see the command section twist at least 5 degrees relative to the fuel tank section. When letting go of the control it rebounds and twists back and forth a couple times.

I have no way of seeing the exact center of mass in space, but it has to be somewhere near the middle of the fuel tank section, despite that being only 50% or so of the station's length. RotPower is definitely applied to the command pod parts themselves, otherwise this behavior wouldn't occur.

I'm not sure if that distinction actually matters for the purposes of that code, though. If it works better than what currently exists, I'm all for it. :)

commented

By definition, MoI=∫P(V)_R_RdV, where P(V) - density, R - radius-vector from rotation axis, if I remember right KSP approximates it by MoI = ∑M_R_R, where M - mass of part, R - radius-vector of part's CoM with respect to rotation axis, which is accurate since KSP assumes parts are of uniform density.
UPDATE: I wonder what p.Rigidbody.inertiaTensor actually is, since it's surely NOT a tensor (we all remember that tensor is a matrix).
UPDATE2: I got it from here: http://docs.unity3d.com/Documentation/ScriptReference/Rigidbody-inertiaTensor.html It's part's PMI around coordinate axes that are rotated according to inertiaTensorRotation. Then your formula is correct according to Parallel Axis Theorem. And my abovementioned statement is not - while parts' density is uniform, their shape is not.

commented

Tallinu, let me clarify this because no one answered you effectively.

For the purpose of the equations, it's perfectly fine to assume that the craft is an ideal rigid body. In reality, -everything- flexes to a certain extent, so there may be some interesting tortion effects.

Yes, it is true that the part that actually has the torque applied to it, is the command pod, or sas if you are using it, but on an ideal rigid body, that doesn't mater. Any torque will cause rotation around an axis, and that axis will always pass through the center of gravity. So, to simplify things for the equation, we take the fact that effectively any torque applied anywhere acts around the center of gravity, and simplify it to just that any force acts on the center of gravity. (I say force, because even unbalanced directional forces are applied as displacement and torque of and around the center of mass, that's how RCS rockets work, see here for an example: http://goo.gl/Zp3vE)

"But wait!" You say. "You said that -everything- flexes! If that's so, then there is no such thing as an ideal rigid body!" Well, that is true. But what happens when the ship finishes flexing one way? It flexes back, and forth, and back, and forth, and so on and so forth until friction stops it. Luckily, when friction finally brings everything to a standstill, all the wobbles have canceled each other out and we are left with a craft who's center of gravity is exactly where the equations have predicted it would be, as long as you include the effects of the SAS over correcting itself again and again.

So, as Anatid said, for the purposes of the calculation, it's all torque.

commented

nod So basically it all works out to the average, or some approximation thereof. Like if the ship is turning 5 degrees per second on average, regardless of whether it's wobbling or not, and the same goes for angular acceleration. Makes sense.

commented

Tallinu,
Actually your formula calculates "immediate" MOI, and so if wobbling occurs your MOI changes all the time until wobbling stops. So if you base your torque off that instead of "stable" MOI, you won't get the result you're looking for. Doing any better would require you to somehow find out that "stable" MOI.

commented

PS: Sorry if that was over-explaining this but one of my peeves is people telling me that I'm wrong or otherwise dismissing something I bring up without explaining the why of it. It feels so frustrating to not understand why he/she thinks differently when you feel you have a full grasp of the situation. In that case I have two options, either I assume I'm right and the other person is just an ignorant asshole (which makes me closed minded as well as an asshole), or they're right and just want to keep me ignorant as to why, which would make them an asshole. Either way, someone doesn't have a full grasp of the situation, and at least one person always winds up being an asshole.

While I understand most people don't have as strong of a reaction to this as I do, I still feel that just telling someone that they're wrong or that the thing they said doesn't matter is a rather dickish move.

commented

"My" formula? No idea what you're talking about...

commented

Tallinu, sorry it's not your formula, it's sarbian's from the opening post. It's 1am over here :)

commented

Aquilux, you should stop being offensive and think that everyone here is out to get you. Be more friendly, and it will return upon you tenfold.

commented

asmi84: Ah that makes sense now. :)
Aquilux: Not strictly necessary but interesting nonetheless. I think I understand how that works a bit better now. :) Basically the point of my first comment was, "This bit doesn't sound right. Is that a problem?" It sounds like as long as the pod's distance from the CoM is taken into account and the torque scaled down to match, it isn't.

commented

Tallinu,
Yea that sounds about right. The only thing is if you apply torgue to the pod you need to keep in mind that pod's principal axes might be rotated with respect to vessel's axes. So it's not only the distance that needs to be taken into account, but also rotation. You can use inertiaTensorRotation to rotate your torgue vector from vessel coordinates to pod's, and back. Also remember that the order does matter - Rotation * Translation != Translation * Rotation.

commented

Right, I've never studied that sort of physics so I'm not familiar with all of the math involved. I was just leaving things in simple terms. :)

commented

I am impressed by the number of replies in such a short time.
You are right to think I over simplified a bit in my post. I didn't want to write a long post and I have some trouble to write complex sentence in a correct english.
Unity use the collider mesh to approximate the shape of the part and calculate the part MoI, So it's far from real physic.

About the torque from a pod and its distance to the CoM : the game does not seems to take the distance into account.I agree it should but my test show otherwise. Maybe I need to build more complex ship with more pod to prove me wrong.

All I can say it that "my" formula seem to work when I test it. My ORDA version can turn around a rigid 370 ton ship as fast as it can without overshooting ( as long as I don't use those evil RCS). I had some other trouble but the MJ2 devs have those under control already.

commented

sarbian is correct with his formula, unfortunately, I already fixed the broken KSP MoI a long time ago. Not sure if the results are exactly like that formula, but at least when I tried it it was. The full code of MoI calculation in VesselState is:

MoI = vessel.findLocalMOI(CoM); // This does the second MoI += line in sarbian code
foreach (Part p in vessel.parts)
{
    if (p.Rigidbody != null) MoI += p.Rigidbody.inertiaTensor; // This should do the first MoI += line. I'm not using inertiaTensorRotation. I remember I saw this, but either it's always the identity or it was doing something wrong (I wrote this several months ago, I don't remember the details)
}

If someone wants to test with the inertiaTensorRotation to see if it fixes anything, open this again and I'll add it there.

commented

r4m0n I just checked and vessel.findLocalMOI use only p.mass and don't add p.GetResourceMass() to it.

As for the inertiaTensorRotation it does not seems to matter indeed.

commented

So, MoI change is not incorporated into 2.0.7? If the videos are correct, and the second is not "stock" 2.0.7, then this should be reopened.

commented

Here is 2 tests I made with a 350 tons ship. The pod rotpower is set to 60 to make it turn faster.

MJ 2.0.7
http://youtu.be/EmOhoCg49NQ

MJ 2.0.7 + MoI change
http://youtu.be/wNaaHwkt4ug

Without the change it takes more than twice the time to go form a stable prograde to a stable retrograde. With some PiD tunning I am sure it can do even better.

commented

Forget the time required, just look at the difference in the amount of overshoot on the first turn! From 90 degrees to at most 10 degrees? That's one heck of an impressive reduction! Want.

commented

I'll reopen this issue briefly, since I did some tests myself and saw that, indeed, vessel.findLocalMoI is ignoring resource masses. I just committed some improved code that I believe should address all issues raised in this thread: cad6c55.

The new code calculates full 3x3 inertia tensor from scratch, using the correct masses and correctly (I hope) taking into account each part's inertiaTensor. This last bit is slightly less trivial than suggested in the original comment here, since inertiaTensorRotation apparently only gives the rotation of the part's principal axes in the part's local coordinates, so this has to be rotated into vessel coordinates. This is needed to account for parts that have been rotated before being attached to the vessel.

To do this calculation properly it was simplest to compute the full 3x3 inertia tensor, and then set VesselState.MoI to be the diagonal components of this tensor, which are the main ones that we care about.

Thanks very much to sarbian for pointing out this issue. I think this fix should resolve all the issues raised here, but I've reopened the issue for discussion.

commented

Pantheis and I just did some tests similar to what Sarbian showed in the videos, after incorporating that code he listed in the OP. (I'll have to rerun them as soon as I can get Pan to send me a recompiled DLL, since I don't have the software set up here yet.) Based on your "less trivial" comment, these must be taken with a grain of salt, but one result caught my attention:

If the ship being tested had command pods placed symmetrically at both ends of the CoM, the overshoot from practically any maneuver I threw at it was consistently 0.1 degrees or less! However if they were offset, for instance if I left the launch stage attached so that one pod was near the CoM and the other was at the far end, that resulted in a fairly consistent 6 degree overshoot for a 90 degree attitude change not involving a roll, and around 4.5 degrees when it did do its "roll so target is on yaw plane" thing. Not sure why the more straightforward maneuvers resulted in greater overshoot, but the point is that calculated torque from command pods may need another look, unless what I was seeing is a result of that "less trivial" issue.

*The craft I used for those tests, in 400km orbit:
https://dl.dropboxusercontent.com/u/203721/Asterisk%20SHL%20%2B%20Fuel%20Tankers%2011%20T.craft

And since it takes a while to get this beast INTO orbit, here's a save file with it already there:
https://dl.dropboxusercontent.com/u/203721/persistent.sfs

Load that up, do a quicksave, try maneuvering it with the launcher still attached, then drop it and maneuver the payload on its own. I haven't tried it with RCS enabled, I was only concerned with the command pod torque.

Here are the results I get with this craft and the current dev build including the change Anatid just made.

Overshoot from 180 degree yaw (normal + to -) with launcher attached: 26.5 degrees / without launcher attached: 0.0 degrees

Same maneuver with RCS enabled: 0.0 degrees whether launcher is attached or not

It seems clear that asymmetric pod torque is still a problem. Otherwise, the PID controller is now doing maneuvers so close to perfect I can't tell the difference (except for that weird roll thing as in #57).

commented

The improved MoI calculation is included in the just-released 2.0.8, so I'm closing this.