Into a Physics Simulator

Hi, this is my first post in PlanetKDE 🙂 . In this post I will be talking about the new features that I am trying to implement
in the KDE Physics Simualator STEP.
First one is the ‘FRAME-CHANGE’ feature. With this feature STEP will be able to give the users a better feel
of relative motion between the bodies. After enabling frame-change the user can select a body and STEP will observe the motion
of all the bodies on the scene relative to the currently selected body. STEP will be able to show that the path of one projectile
as seen from another projectile is a straight-line ( given the value of acceleration-due-to-gravity is same for both ).

I implemented it using the void QGraphicsView::centerOn(qreal x, qreal y)  method. Since the view is to be fixed to the body
which is currently selected, I take the currentIndex() from the ItemSelectionModel and then pass the co-ordinates of thus obtained
QGraphicsItem  to the QGraphicsView::centerOn(qreal x, qreal y) method.

Next one is the ‘REWIND’ feature. Watching the simulation go forward in time was becoming a littel boring 🙂 . Bring in something new
…. STEP will now have a REWIND button just beside the Simulate button. If the rewind button is pressed while the simulation is
 going on, world->time  begins to decrease and the worldscene travels back in time.

Implementation is quite simple. Integration with a +(ve) timescale gives forward simulation. Change the timescale to -(ve)  and you get
the REWIND feature (Or alternatively we can reverse the velocities of all the bodies ). Adjustments are needed to accomodate collisions
while rewinding. It works fine for simple scenes, but there are issues when using different values of restitution-coefficients and  in
cases where friction is there.

Another feature I am trying to do is the Pulley Joint. STEP already has Anchor, Pin, and Stick Joints. It will be a simple disc with
two handler items ( which can snap to a rigid-body or a particle ). The ration of the Pulley will be fixed and equal to one. Yes,
a very simple pulley. The constraint-eqations of the pulley-joint are causing some serious head-ache at the moment.
The same little problem is there in getting the equations and values correct in case of friction.
I hope to fix it soon….

Adding Straight-Plane and friction

A simple Box or a Polygon can already be created but sometimes their size falls short …i.e. the  disk or particle (or some other polygon) may go beyond it. For that I am adding a ‘Straight-Plane’ object in the palette. Many intersecting Straight-Planes can be created on the scene at the same time. It will be like an infinite fixed surface which will provide a surface with which other objects may collide or slide/roll upon. Straight-PLane

The StraightPlane class will inherit from RigidBody and will have just two specific properties :
point1 (Vector2d)
point2 (Vector2d)
(…. just like we need two points to define a straight line in 2-D plane). The two points will decide its inclination and position.

But here lies the problem , How to keep the straight plane fom moving ?
We could take care of GravitationForce and Weightforce by setting its mass to zero.
to make sure that it doesnt move during collisions we could fix the values of ConstraintsInfo::DynSparseRowMatrix ::jacobian value  , to 1 (at the
correct offset of course..).

We will have to neutralise any force from being applied to it by any SPRING also.

All of this can be taken care of if in the StraightPlaneCreator class we create an ‘Anchor’ just
after the second point of the Plane is set by the user and call
Anchor::setBody() to set the Straight-Plane as the Object of that anchor . The plane will get added to the BodyList and the Anchor will
get added to the JointList of the StepCore::World class.
This way all the problem of keeping the straight-plane fixed will be solved without spreading any dirt around in the previous code.

The functions to check state of collision (Contacted, Separating, Separated, Colliding etc.) have been written.
Although I went through many papers and googled the phrase “Gilbert-johnson-keerthy Distance algorithm” over a hundred times, I still
could not “hundred-percent” understand how to check the state of collision for two polgons (and the code is a mile long..). Thankfully I dont have any use of it
at the moment.

The algorithm to find the state of collision with a Straight-Plane is quite simple. I am using the formula to find the
distance of a point in 2-D space from a straight-line.

if the equation of the line is (Ax + By + C = 0) and the given point is (x1, y1), then the distance of the point
from the straight-line is

abs(Ax1 + By1 + C)/sqrt(pow(A,2) + pow(B, 2))

The value of tolerance is to be checked with a little testing.

But I am having some trouble handling the mouseEvents on the scene ..(due to which StraightPlaneCreator and StraightPlaneGraphicsItem
classes are not yet functional. )
Also I dont know how to paint something that will extend itself with the view (the plane is supposed to be infinite and should
extend if the user scrolls…)

About Friction:

The documentation says :

>>>QHash provides very similar functionality to QMap. The differences are:

>>>QHash provides faster lookups than QMap. (See Algorithmic Complexity for details.)
When iterating over a QMap, the items are always sorted by key. With QHash, the items are arbitrarily ordered.

Therefore to store the friction-Coefficient and the restitution-Coefficient I am going to use a QHash as I need faster lookups
and at the same time no need to store keys in sorted-order.

Since there will be a ‘FrictionForce’ icon just like ‘Weightforce’ and ‘GravitationForce’ icons on the palette, I will need to
__REGISTER(FrictionForce) and __ADD_TO_PALETTE(FrictionForce) in the constructor of the WorldFactory Class.
There will be a QHash<QPair<RigidBody*, RigidBody*>, QPair<double, double>>
First double of the second QPair to store friction-coefficient and the second double to store the restitution-coefficient
for the pair of rigidbodies.

Or ther can be two QHash-es One for QHash<QPair<RigidBody*, RigidBody*>, double> (for friction-coefficient)
and another QHash<QPair<RigidBody*, RigidBody*>, double> (restitution-coefficient)

(but this will require searching for the same pair of RigidBody- pointers from two different QHashes , so I will go with the
first idea i.e. a single QHash).

I noticed one anomaly, the solveCollisions() function exists but is never called anywhere. I looked everywhere the
StepCore::World:: doEvolve() function led but didn’t find it being used anywhere. The collisions are being solved
by gathering the contacts information int a ‘ConstraintsInfo’ structure and then passing the structure to ConstraintSolver::solve()
function… I still have to do some study on the internals of that ConstraintSolver::solve() function (particularly the ei_constrained_cg() method from
Eigen::Unsupported module..)

But the place to add friction and coefficient of restitution (bounceness) would be in the CollisionSolver::getContactsInfo()
(which I am working on right now..)

SIMULATION:

I did some backtracking on Simulation Start/Stop button.

Step carries out simulation frame by frame. WorldModel contains a _simulationFps (int ) and a _simulationTimer (QTimer) whose interval is (currently) set to
(1000/_simulationFps) i.e. 40 milliseconds…( as the _simulationFps is set to 25 in the constructor of the WorldModel.)

simulationFrameBegin() calls _simulationThread->doWorldEvolve(1.0/_simulationFps) i.e. the ‘delta’ time value for world->doEvolve()
is 4o milliseconds ( same as the frame-width…).
On finishing world->doEvolve(), simulationThread emits the WorldEvelveDone signal which calls WorldModel::simulationFrameEnd(reault)
(result is the value returned by doEvolve()). and the GUI updated…

So Each frame is displayed after a gap of 40 milliseconds. (for _simulationFps = 25).

There is one more interesting thing in StepCore::World class . It is _timeScale. The runSpeedAction group exploits this
variable to make the simulation appear faster.

in World::doEvolve(delta) function targetTime = currentTime + delta * timescale .
So if the timescale is 2 or 4… targetTime becomes greater and while the _simulationTimer and frame-rate remain unaffected.
The outcome is:
If at 1x speed , after one frame you were seeing the state of the world after 40 milliseconds. (in reality also 40 milliseconds are allowed \
for the frame).

Then at 2x after one frame you would see the state of the world after 80 milliseconds. (but in reality only 40 milliseconds are allowed
for the frame).

Thus the simulation appears to go faster.

I am planning to test the simulation with increased values of _simulationFps (may be 40 or 50 ..or at-least 30)
or may be add this option in the configure-step menu item.
and may be convert the radio buttons for runspeed Action-Group to a slider (after all they are just changing the _timescale of the
StepCore::World class).

 

 

 

 

 

 

 

 

 

New ‘Step’

Well, it doesn’t need you to be a scientist or a developer to see that STEP is much behind from where it should be. It doesn’t yet support objects in contact.  If you create two objects touching each  other and try to begin the simulation – a stupid dialogue will appear  telling you – “there are collisions which cannot be resolved automatically, please remove that contact first”. If you cannot create contact , you are only left with few options – projectile motion under the effect of weight, simple collisions (which are assumed elastic, no option to control the coefficient of restitution), spring related stuff, and a little fun with charged particles. What I miss the most in STEP are the pulleys. They can really bring you options, just close your eyes and fit  as many of them any place you want. Would be real fun to watch where which  one goes.  Friction and pulleys alone will provide a lot of options to the user.

Another missing thing is the ability to change the frame of observation during simulation. Imagine you have a lot of projectiles flying around. Where is the fun in watching them standing on the ground. I want STEP to allow users to experience relative-motion. What will the projectiles look like if you yourself were one of those flying things. How great would that be!!….