Problems with LinearSinkForce in Panda3D

I’m generating particles and applying a LinearSinkForce with 1/r^2 falloff to them, but the system isn’t stable; the orbits diverge. Every lap the radius gets bigger and bigger. Is there something I can do to prevent this, or do I need a different physics engine?

A is the vector specifying where particles are created, vel is their launch velocity, GM is the field constant.

A = orbital_mechanics.latlong(lat1,long1,earthradius)
    vel, GM = orbital_mechanics.getGPSLaunch(lat1,long1,lat2,long2,earthradius,elevation,time,0.00001)
    
    p = ParticleEffect()
    
    p.reset()
    p.setPos(0.000, 0.000, 0.000)
    p.setHpr(0.000, 0.000, 0.000)
    p.setScale(1.000, 1.000, 1.000)
    
    p0 = Particles('kepler-ballistics')
    
    # Particles parameters
    p0.setFactory("PointParticleFactory")
    p0.setRenderer("LineParticleRenderer")
    p0.setEmitter("PointEmitter")
    p0.setPoolSize(2048)
    p0.setBirthRate(10.00100)	# Period, not rate
    p0.setLitterSize(1)
    p0.setLitterSpread(0)
    p0.setSystemLifespan(0.0000)
    p0.setLocalVelocityFlag(1)
    p0.setSystemGrowsOlderFlag(0)
    
    # Factory parameters
    p0.factory.setLifespanBase(10.0)                # Ballistic particles' lifetime
    p0.factory.setLifespanSpread(0.0000)
    p0.factory.setMassBase(1.0000)
    p0.factory.setMassSpread(0.0000)
    p0.factory.setTerminalVelocityBase(4000.0000)
    p0.factory.setTerminalVelocitySpread(0.0000)
    
    # Point factory parameters
    
    # Renderer parameters
    #p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAINOUT)
    p0.renderer.setUserAlpha(1.00)
    
    # Line parameters
    p0.renderer.setHeadColor(Vec4(0.20, 0.70, 1.00, 1.00))
    p0.renderer.setTailColor(Vec4(0.20, 0.25, 0.50, 1.00))
    p0.renderer.setLineScaleFactor(2.00)
    
    # Emitter parameters
    p0.emitter.setEmissionType(BaseParticleEmitter.ETEXPLICIT)
    p0.emitter.setAmplitude(1.0000)
    p0.emitter.setAmplitudeSpread(0.0000)
    p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 0.0000))
    print(vel.getX())
    print(vel.getY())
    print(vel.getZ())
    p0.emitter.setExplicitLaunchVector(Vec3F(vel.getX(),vel.getY(),vel.getZ()))                        # Launch trajectory
    #p0.emitter.setExplicitLaunchVector(Vec3F(0.10,0.10,0.10))
    #p0.emitter.setRadiateOrigin(Point3(0.0000, 0.0000, 0.0000))
    #p0.emitter.setRadiateOrigin(Point3(A.getX(), A.getY(), A.getZ()))
    
    # Point parameters
    p0.emitter.setLocation(Point3(A.getX(), A.getY(), A.getZ()))
    p.addParticles(p0)
    f0 = ForceGroup('gravsink')
    
    # Force parameters
    force0 = LinearSinkForce(Point3(0.0000, 0.0000, 0.0000), LinearDistanceForce.FTONEOVERRSQUARED, 1.0000, GM, 0)
    #force0.setVectorMasks(1, 1, 1)
    force0.setActive(1)
    f0.addForce(force0)
    p.addForceGroup(f0)
    
    return p

Double-checked my calculations by hand, and the LinearSinkForce is also hitting the particles about 50 times harder than it should be. Any thoughts?

Increasing the particles’ lifetime from the 1 second it should take them to complete their trips shows that they track ellipse-like figures that spiral outwards. This is what makes me suspect that something fishy is going on with Panda3D’s physics that I can’t determine for myself, because any particle that starts with a nonzero initial velocity should track a closed shape orbit unless it has the required escape velocity, in which case it’ll never turn around to begin with. Panda3D’s physics is screwing up badly enough to ruin energy and momentum conservation.

Does it matter that I left the particle generator at the origin? I can’t imagine why else they’re getting hit so heavily by the LinearSinkForce, except for some obscure parenting issue. If that is the problem, how do I get the LinearSinkForce to hit the particles and not the parent? Just leave it off near spatial infinity? No more elegant solution?

i honestly dont understand your code because i never used particle system of panda3d. but if a physics engine produces unexpected result, you can check these:

  1. should a vector be normalized or not?
  2. are you aware a computer physics engine dont work continously but incremently so it is never truly accurate?
  3. some variables stored in Panda3d are single float values instead of double float, is there any in your system?
  4. the formula for a constantly orbiting object is a=vv/r or a=omegaomega*r
  1. Yeah, I took good care to keep the right vectors normalized.
  2. Right. This is where I’m worried the problem is. I think Panda3D’s numerical analysis is poorly implemented so as not to properly conserve some important quantities.
  3. Yes. This is probably part of the problem, but I can’t imagine it’s contributing much; this is a pretty small effect unless you try to invert near-singular matrices or divide by nearly-zero.
  4. That’s for an object orbiting in a circular trajectory. My objects are following elliptical trajectories, so they’ll obey Kepler’s laws.

since you are doing serious physics simulation, you should use other physics engine. Panda3D’s physics engine is a simple engine for games, not for scientific use.
writing your own engine may be better. even ODE , Bullet, Nvidia physics in Panda3D can have aspects that are unsuitable. and the officially released Panda3D SDK uses single float only.
you can do your own physics then use Panda3D to visualize your objects. thats what i do.

It’s really not sophisticated enough physics that it should be this big of a problem; it’s just Kerbal Space Program-level stuff.

I get good enough results by adding a mystery factor of 1/72 to the LinearSinkForce. Still no idea why that’s needed. There’s definitely drift in particle physics using LinearSinkForce, so that’s something to look into for future improvements to the physics engine.

Satellite navigation engineer reviewed my code and tells me the math looks good. Neither of us can figure out where that factor of 1/72 is supposed to come from. Is this something to do with Panda3D physics forces? Particles? Weird intersection of both?

at what framerate do you run the program? if framerate=10 or framerate=100, would the result be different?

I have no idea about framerate or how to control it. What’s the default?

default is unlimited framerate( in fact limited by hardware performance). you can set framerate in 2 ways , as in this thread Panda 191 limited clock mode doesnt work.
for physics simulation, the higher framerate, the better.
in other physics engines, framerate of physics can be different(can be much higher) from graphics, panda3d’s simple physics can’t do this, as i remember.

I’m mostly concerned about the missing factor of 1/72, but the drift is concerning too.