- Home /
Gravity simulation not accurate. Can't understand why
Hello
What I am doing is creating a simple, moderately accurate simulation where you can control a spacecraft. Anyway, to test my physics i created the Earth and the ISS, but made them 100000 times smaller, so instead of the earth being 12742000 meters in diameter, i have made it 127.42 and the distance between earth and ISS is 4 in stead of 400000 meters. Anyway, to make this scaling work in the universal law of gravitation, I have scaled the mass of the of the earth down by 10000000000 because the distance is squared in the equation of universal gravitation (Fg = G(Mm/r^2)) and then so is the scaling. Which means that instead of being 100000 times smaller it's 100000^2 times smaller. Anyway, I scale the mass of the earth down by that amount because the distance is dividing.
Instead of using the rigidbody mass of the earth i made a separate value in the script attached to it because the rigidbody doesn't allow such large values. anyway, I use the formula and the mass of the earth scaled down, the real value of G, the distance scaled down and I don't use m in the equation because since it mass doesn't affect the gravitational attraction on the spacecraft i just set the spacecraft's rigidbody mass to 1 that way when it applies the force i calculated it won't matter that i didn't use mass of the spacecraft.
Also, to keep the ISS in orbit, i give it it's real life velocity scaled down by the same amount> 0.0766
void Attract(GameObject bodyToAttract)
{
Rigidbody rbToAttract = bodyToAttract.GetComponent<Rigidbody>();
direction = transform.position - rbToAttract.position;
distance = direction.magnitude;
if (distance == 0)
return;
double forceMagnitude = G * (mass / Mathf.Pow(distance, 2));
force = direction.normalized * float.Parse(forceMagnitude.ToString());
rbToAttract.AddForce(force, ForceMode.Force);
}
This is the part of the code that deals with the actual attracting. Anyway, the problem lies in that, despite me going over this a thousand times and spending hours trying to figure it out, it just doesn't work, the spacecraft just goes almost straight against the planet. It maintains of course it's initial velocity, but the force just seems way too strong, and it shouldn't be. I have tried using different ForceMode s but nothing works. I don't know if it's a problem with my math or with my code.
I may have explained this poorly so please ask any question you have.
Any help would be infinitely appreciated. This is quite important.
Thanks in advance
I've not taken time yet to study more about your inquiry, but what strikes me first is to ask about time. Have you scaled time?
In a reverse scenario, many students of Unity try their first stack of blocks with unit blocks (dimension is 1.0 to each side). For some reason they tend to think the simulation is too slow, because they're expecting 1.0 to be, perhaps, inches when it is actually meters. In their case the reverse of what I suspect you're observing happens, where ins$$anonymous$$d of the blocks moving like dice on a table, they move like 1 meter boxes on the floor. These students eventually discover how to scale time so the speed of falling looks right to them, but now time is moving too fast for other situations in their work, until they learn to work at more realistic scale.
The physics engine doesn't really "understand" scale, which is to say when you do actively choose to scale objects so, for example, the dimensions of space can fit into the engine's features, one must usually scale time as well. $$anonymous$$y thinking here is that an orbital balance may require a scale of time, because it may be that gravity vs time ends up crashing into the planet. I need more coffee and time to think, and this is one of those tuning efforts that may require more vision (for those of us trying to help) than snippets might reveal.
Thank you for your answer and please take your time. You seem to understand the problem, for this I am fortunate, as I am running out of ideas.
Referring to what you say; I have tried scaling time in past experiments and attempts to obtain accurate results. For instance, I tried a similar setup but it was with the earth and moon, the orbit shape was accurate but it was too fast, the orbital period was approx. 2650 seconds as opposed to 2332800 seconds, which is what it should be. This problem was easily solved by scaling time accordingly, but that leaves much room for inaccuracy, which is precisely what I don't want. It also felt like a temporary patch, but not something to solve this problem once and for all.
If you want I can attach the whole script and screenshots of the components. I don't know if this would be any help to you.
Answer by FredOld · Aug 20, 2018 at 09:32 AM
I have solved the issue. It turned out to be rather simple: I had scaled all the distances down by 100000, so 1 unit was 100000 meters and I had adjusted the mass by the same proportion to make up for that, as I wrote in my question. However, the force appeared to be out of proportion despite my rigorous examination of all the scaling I has done. And finally I found of course that I have to divide the force magnitude by 100000 as well, because 1 N = 1 kg⋅m⋅s^−2 So if I have made 1 unity meter into 100000 real meters, I also have to apply this scaling here.
Thanks for your help @JVene !
Actually you argued the wrong way ^^. What you did no scale is "G". G tells you how much force you get for a given mass and a given distance squared. It actually links meters with kg. However not in a 1:1 ratio.
G is m^3 * kg^-1 * s^-2
. Since you scaled mass and distance both by your scale factor you need scale G by your scale factor squared. btw: You need scale mass only once by your scale factor.
It would be much easier when you simply go the other way round. Just work with the original values and just scale the input and output accordingly. So multiply your worldspace distance by your scalefactor, do the math and scale down the end result by your scale factor. Since we deal with floating point numbers and only multiplication / division the number of significant digits doesn't really change so precision is not an issue.
Btw: Why do you convert the double value to string and parse the float from that string again? You can simply cast the double to float. This is much more performant, doesn't create any garbage and is much safer.
Another optimisation would be to not use "magnitude" and Pow but just use sqr$$anonymous$$agnitude. You essentially calculate the square root and then square it again.
Finally keep in $$anonymous$$d that a simulation like that is only stable for a short time due to floating point precision
Okay thank you. Though I am now super confused. I had it working accurately with what I said, so could you please explain only the scaling part for me? It would be really helpful, because I now have a complete mental block around this whole thing and can't get my head around what you mean.