centripetal / centrifugal forces, how could it be done?

I made a quick attempt at obtaining the effect of centrifugal force by placing an object on a surface and rotating the object. Even with ODE I seem to get no effect.
Also, no reference to centripetal centrifugal forces on the forum (not even with the brand new google search) which is quite surprising.

What I am looking for is generating a centripetal force on the inside of a sphere so that an object placed on the inside would be pushed towards the inner face of the sphere and simulate gravity in a non-gravitational environment.
Or to put it in another way, rotate a large ring in space and obtain gravity by spin.

I am sorry now I was not paying enough attention to physic classes in high-school, or it may be just my inexperience with game engines, but I definitely need some help here, not just with the physic theory but also on how this could be approached in Panda3d…

That’s the way it should be :slight_smile:
Centrifugal/petal force is not a ‘true’ force, like gravity or electromagnetic force. It’s a fictional force, visible only if you are in an reference frame which not an inertial frame.
What you have attempted is to use an inertial frame, and rotate an object within the inertial frame.

In Lagrangian mechanics when using polar coordinates as generalized coordinates you get generalized forces which are equivalent to centripetal forces.
Up to my knowledge no physics engine used for gaming allows to use generalized coordinates.

But there are workarounds:

(1) PhysX has forcefields. Create a cylindrical force field with a linear falloff to simulate a rotating reference frame (the linear falloff should be proportional to your rotational speed squared, if you want to modify rotational speed with time).

(2) I don’t know if ODE has a force field too. If not you can always manually add a proper force to your bodies each frame.

What’s an “inertial frame”?
This topic sounds interesting.

Thanks Enn0x. Sounds like force-fields is exactly the way to go for this.
There was one mistake in my assertion, but you got the point anyway: “I placed an object on a surface and I rotated the surface, not the object.”
I’ll report back if I have a functional prototype.

Please keep in mind that using PhysX implies sticking to the PhysX license.

If ODE is sufficient for your project except for the centrifugal forces, and there are only a small number of movable object inside your space-ship (a few dozen), then it might be easier to apply forces manually each frame to each object.

I really appreciate your involvement and your knowledge in game engine physics. I am concerned about the licensing issues even if there’s no plan to release anything commercially, I’d still like to invest my efforts in using a really free alternative, so I’d rather go for ODE. I already started lurking their discussion list in search of ideas if not solutions. There is a discussion on a gyro effect that seems to work “by magic”, as they put it, but I would need to test it to see if the magic really happens.

So I am going to share some more details, as my case might be very particular and could support a simple approach while still using ODE.

I am trying to prototype a RingWorld concept, so I cannot use simple directional gravity throughout the entire environment, since “down” will change it’s direction everytime you advance on the ring. I know I could have a pseudo-round ring, so I could use portals and separate the “segments”, but I’d still like to have a solution where the entire world would actually exist in the same “zone” and work with the level of detail to make it work graphic-wise.
So we are talking about an unknown large number of objects and actors, where individual control of each force doesn’t look feasible.

Given the above… I’d appreciate any ideas, even if they are limited to a theoretical approach.

Exactly what I wanted to say :slight_smile:

I would start with adding a force by hand each frame, and see how far you get. If this is getting too slow with time you can move this bit of code to C++. I don’t know how ODE/Panda3D scene graph synchronization works, but this would be a good place to also add a centripetal force.

By the way: I had a quick look at Bullet. Bullet doesn’t seem to have force fields too. I also found a forum post where the main Bullet developer suggest applying a force for each body manually, so this seems to be the right solution.

Hello there, this thread is quite old but, as it happens, I’ve bumped into it just now… I’d be interested to know if radu has achieved any progress with the artificial gravity experiment.

I’d also like to add to the discussion another point. the idea of using a force field might be the right way forward but it would not be entirely realistic.

In fact, one of the issues with an artificial gravity based on rotation is the Coriolis effect on top of the apparent gravitational force. This effect is such that when an object is launched in the air in this artificial environment (like if tossing a coin) it does not go up and down on a straight vertical line but rather follows a parabolic trajectory. Another sensible effect is that motion differs if in the direction of rotation or in the opposite way.

Also the fact that the artificial gravity varies quite sensibly along the radius of the rotation plays a role here.

here is a clear illustration of the artificial gravity spurious effects in action: spacefuture.com/archive/imag … tats.2.gif

I’m sorry, but the coriolis effect is just another fictional force, observed only in a rotating frame of reference. Centripetal force is observed for all masses, while coriolis effect is observed only for moving masses.

If you observe the very same trajectories which you have show in your picture link from an inertial frame then you will see that the objects just move straight to each other.

This is what all game physics engines can do. None provides transform to moving/rotating frames of reference. The reason is that it is simply not needed for games, because the coriolis effect is so very small for “earth surface” scenarios. And it so easy to fake - just apply a self-computed fore if you really need it.

By the way, even if there was such a game physics engine out somewhere, which allows moving/rotating frames of reference (and thus produces centripetal and coriolis forces) - it would still not be realistic, because the next un-realistic assumption is that we have a flat space. We don’t have - space has curvature! The effect is even smaller, barely measurable, but it’s still unrealistic. And the effects are caused by mass, which is just the scalar magnitude of curvature. How ironic.

If you want to understand these things more in-depth I suggest buying a good book on mechanics and theory of relativity.

thank you for your explanation, enn0x.

Actually, that is the reason why I resurrected this topic: I was thinking of a situation where some game characters were taken from the earth environment, with natural gravity, to a space environment, with artificial gravity. Once in space, in the frame of reference of the characters, things would look quite different from here on earth.

I understand that game physics engines do not let you change frame of reference. But is that the only limitation? If so I could continuously move the camera to match the circular motion of the spacecraft and see the right artificial gravity effect on the poor cosmonauts standing inside…

From what I’ve been reading while googling on this, I came to the conclusion that the Coriolis term in the cinematic equations gets neglected for good by the physics engines and that, for this reason, no such effect is to be seen in any case. I wonder if characters would get flat against the walls of the spinning spacecraft at all.

Nope. It’s possible to see the coriolis effect using e. g. Bullet or PhysX. Because it is a fictional force. The game engine does not need to apply any force terms (besides gravity). You provided the solution yourself: move the camera with the reference frame you want to have. The same goes for centrifugal/centripetal forces.

The main limitations are numerical considerations. You have to create huge worlds (planet size domensions), while your area of interest is tiny (spacecraft).

Just for fun: Here is a demo showing the coriolis effect, using Bullet physics. You will need the standard misc/sphere modelwith comes with the Panda3D SDK on your model path, and of course a recent Panda3D SDK.

The observers frame of reference is a rotating frame, e. g. like on the surface of a planet. The planet rotates with 10 percent of the orbital velocity.

The observer looks tangetial towards a point of the surface of this planet, indicated by a white sphere. A ball if cast up into the air from this point. Gravity stops the upward movement, and makes the ball fall down again. I did not add a planetary surface, so the ball fall down below surface level. In order to see the coriolis effect better I have added a vertical white ray from the starting point up and down.

If there was no coriolis effect the ball would follow this ray. But it deviates.

The only force I apply each frame is gravity. It is computed by finding the unit vector from the current position of the ball (in global corrdinates!) to the center of the planet (0,0,0). The multiply with a proper magnitud. No extra forces for coriolis or centrifugal/petal forces are added.

Another nice configuration is the spacesphip setting: f=1 to set the rotation velocity of the reference frame to exactly the orbital velocity. And reduce vR to 1, or the object will quickly fly out of camera frustrum.

from pandac.PandaModules import loadPrcFileData
loadPrcFileData('', 'sync-video f')
#loadPrcFileData('', 'bullet-broadphase-algorithm sap')
#loadPrcFileData('', 'bullet-sap-extents 10000000')

import sys
import math

from direct.showbase.ShowBase import ShowBase

from panda3d.core import Vec3
from panda3d.core import Point3
from panda3d.core import LineSegs

from panda3d.bullet import BulletWorld
from panda3d.bullet import BulletRigidBodyNode
from panda3d.bullet import BulletDebugNode
from panda3d.bullet import BulletSphereShape

# Config
G = 10.                       # gravitational constant
M = 10000.                    # mass of earth
m = 10.                       # mass of satelite
R = 100.                      # radius of orbit
vR = 12.                      # initial radial velocity
f = 0.1                       # factor applied to orbital velocity

v1 = f * math.sqrt(G*M/R)     # orbital velocity, times factor
T = 2 * math.pi * R / v1      # period of rotation
omega = 360.0 / T             # angular velocity of reference frame

# Base
demo = ShowBase()
demo.setBackgroundColor(.0,.0,.6,1)
demo.setFrameRateMeter(True)

# Moving frame of reference
frameNP = render.attachNewNode('Helper')

segs = LineSegs()
segs.moveTo(0,0,0)
segs.drawTo(R+10,0,0)
frameNP.attachNewNode(segs.create())

dummyNP = loader.loadModel('misc/sphere')
dummyNP.reparentTo(frameNP)
dummyNP.setPos(R,0,0)
dummyNP.setScale(0.5)

demo.cam.reparentTo(frameNP)
demo.cam.setPos(R-10,100,0)
demo.cam.lookAt(R-10,0,0)
demo.cam.setR(-90)

#demo.cam.setPos(0,-400,0)
#demo.cam.lookAt(0,0,0)

# Physics
debugNP = render.attachNewNode(BulletDebugNode('Debug'))
debugNP.show()
debugNP.node().showWireframe(True)
debugNP.node().showConstraints(True)
debugNP.node().showBoundingBoxes(False)
debugNP.node().showNormals(True)

world = BulletWorld()
world.setGravity(Vec3(0,0,0))
world.setDebugNode(debugNP.node())

ballNP = render.attachNewNode(BulletRigidBodyNode('Sphere'))
ballNP.node().setMass(m)
ballNP.node().addShape(BulletSphereShape(.5))
ballNP.node().setLinearVelocity(Vec3(vR,0,-v1))
ballNP.setPos(R,0,0)
ballNP.node().setDeactivationEnabled(False)
world.attachRigidBody(ballNP.node())

# Task
roll = 0
running = True

def pause():
  global running
  running = not running

def update(task):
  global roll
  if running:
    dt = globalClock.getDt()

    # Move frame
    roll += (omega * dt)
    frameNP.setR(roll)

    # Apply gravity
    gravity = Point3.zero() - ballNP.getPos()
    gravity.normalize()
    gravity *= G * M * m / (R**2)
    ballNP.node().applyCentralForce(gravity)

    # Step simulation
    world.doPhysics(dt, 5, 1./180.)

  return task.cont

globalClock.setMaxDt(0.1)
taskMgr.add(update, 'update')

# Main
demo.accept('escape', sys.exit)
demo.accept('x', pause)
demo.run()

I see your point, enn0x. The Coriolis term is part of the solution to the motion equation only when expressed in the rotating reference frame. What I was reading, dealt with the Coriolis force acting on objects in the frame of reference of earth (non inertial). Physics engines simulating ballistic trajectories on earth neglect the Coriolis term as it’s negligible for usual game dynamics. Instead, If I stay in the inertial frame of reference of fixed stars the Coriolis term is not there at all (both on earth and in the spacecraft).

The large/small scale problem is actually something to think about. Floats are not precise enough to have a tiny spacecraft orbiting a large object as earth… Ouch.