Infinite mass moving platform

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Infinite mass moving platform

Postby Cannos » Mon Sep 19, 2016 8:46 pm

First, I apologize if this has been asked and answered before. I searched through the forums and saw many threads discussing similar things. But some info is old, incomplete, or confusing. So here goes:

I want to move an infinite mass body and for it to push dynamic objects around. Basically a moving platform with infinite mass. What is the best way to do this?

Notes:
  • In other physics engines, this might be called kinematic, but one of the posts I read suggested that Newton kinematic bodies needed a finite mass. So I wasn't sure if kinematic bodies were the right thing.
  • Plus, I am still on Newton 2.0 and it doesn't have NewtonCreateKinematicBody.
  • I tried using a joint as suggested here but that also doesn't work with infinite mass bodies either.

I am willing to move to Newton 3.0 if I need to, but a solution for Newton 2.0 would be appreciated too, if possible. Thanks for the help!
Cannos
 
Posts: 129
Joined: Thu Mar 04, 2010 5:41 pm

Re: Infinite mass moving platform

Postby JoeJ » Tue Sep 20, 2016 3:33 am

1. You can attach a kinematic joint to a dynamic body with mass, and so move it at will.
This works for 2.0. You can also set a maximum force for the joint ('maxFriction'), so the body will still stop, e.g. if a barrel is below an elevator.

2. You can use a kinematic body and move it at will.
You should also set the velocity of that body to the correct value to ensure other bodies move properly, e.g. to make a barrel on top a platform move along with it as expected.
This works with infinite mass, but is not recommended. IIRC infinite mass can cause huge contact forces, setting mass keeps them in reasonable values.
Looking at elevator above barrel example again, with this method the barrel will either go through the elevator or the floor, but the elevator will follow your settings exactly.

The update to 3.x should only take a hour, recommended anyways :)
User avatar
JoeJ
 
Posts: 1453
Joined: Tue Dec 21, 2010 6:18 pm

Re: Infinite mass moving platform

Postby Cannos » Tue Sep 20, 2016 1:14 pm

I need an infinite mass platform to guarantee it will be at the exact location specified. So the platform shouldn't have any forces applied to it by dynamic bodies it is pushing, nor should it have any limitations to it's movement imposed by joint min/max limits. So it sounds like the 2.0 version with joints probably won't work for this case.

I played around a bit with infinite mass kinematic bodies in the 3.x samples but also couldn't get the behavior I was expecting. I'll keep looking at that and post results.
Cannos
 
Posts: 129
Joined: Thu Mar 04, 2010 5:41 pm

Re: Infinite mass moving platform

Postby Julio Jerez » Tue Sep 20, 2016 1:35 pm

if you play 3.xx, check out the player controller. It is made of kinematic bodies.
In Newton, bodies with infinite mass are not considered kinematic.
you can move them around but that is not advised since they will generate infinite collision impulse.

for that 3.0 has the kinematic body which are bodies that can have mass and velocity by the have not update position and velocity update, you need to move then manually
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Infinite mass moving platform

Postby Cannos » Tue Sep 20, 2016 2:09 pm

I just tried out the player controller example in the latest code and it looks like it has the behavior I want. Basically a body that can be moved manually, can push dynamic bodies, and will not be pushed back. Thanks, I will look into it further.
Cannos
 
Posts: 129
Joined: Thu Mar 04, 2010 5:41 pm

Re: Infinite mass moving platform

Postby JoeJ » Tue Sep 20, 2016 2:12 pm

reply to late, but anyways...

Cannos wrote:platform to guarantee it will be at the exact location specified. So the platform shouldn't have any forces applied to it by dynamic bodies it is pushing, nor should it have any limitations to it's movement


This is exactly what kinematic bodies are doing, keep in mind:
You set mass only to avoid infinite impulses on other bodies.
You set velovity only to affect other bodies in contact.

Neither of both settings have any effect one motion of the kinetic body itself, you have full control of it's position.
E.g. if you set velocity, a dynamic body on top will move like on a conveyor belt, but the kinetic body does not move anywhere.
User avatar
JoeJ
 
Posts: 1453
Joined: Tue Dec 21, 2010 6:18 pm

Re: Infinite mass moving platform

Postby Cannos » Tue Sep 20, 2016 2:22 pm

Great, yeah that sounds like what I need. When I was trying kinematic bodies with mass in the 3.xx examples they weren't behaving right, so I must have had something set up wrong.
Last edited by Cannos on Tue Sep 20, 2016 7:08 pm, edited 1 time in total.
Cannos
 
Posts: 129
Joined: Thu Mar 04, 2010 5:41 pm

Re: Infinite mass moving platform

Postby Cannos » Tue Sep 20, 2016 6:03 pm

Okay looks like one problem I had is that I forgot to call NewtonBodySetCollidable(kinematicBody, true). Once I put that in, the kinematic body started pushing the dynamic ones around.

So it is now pushing dynamic bodies, but I'm seeing a fair amount of penetration, even with a very large kinematic body mass. Dynamic bodies are mass=1, I've tried masses up to 10000 for the kinematic body. I am setting both the position and velocity of the kinematic body.

Any ideas on how to decrease the penetration?
Cannos
 
Posts: 129
Joined: Thu Mar 04, 2010 5:41 pm

Re: Infinite mass moving platform

Postby JoeJ » Wed Sep 21, 2016 1:32 am

My guess is that you calculate velocity wrong, and because of this collisions are not resolved by collision responce, but by error correction.
With error correction i mean Newtons behaviour to seperate intersecting bodies just slowly at constant speed.
This could be explain it, experiment with large velocity constants to see what effect they have to proof given velocity is working at all.

If you don't think that's the reason post code and a video.
A little bit of interpenetration is normal. I use kinetic platforms to test balancing ragdoll (which is worst case because multi 20 bodies system resting an a single platform), and there i get penetration of about 1 cm.
User avatar
JoeJ
 
Posts: 1453
Joined: Tue Dec 21, 2010 6:18 pm

Re: Infinite mass moving platform

Postby Julio Jerez » Wed Sep 21, 2016 11:29 am

setting a mass of so high render the thing useless.
you need to set the velocity and angular velocity currently, there is a function that you can use to integrate the body.
can you make a video so that I can see what is it that you are try to do?
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Infinite mass moving platform

Postby Cannos » Wed Sep 21, 2016 7:07 pm

Here's a video of what I'm trying:
https://www.dropbox.com/s/dnd4nii3jwfe20y/kinematictest.mp4?dl=0

This is a modification of the BasicRestitution sample. I just make a large kinematic box (the green one) and move it upward, then snap it back to the bottom and move it upward again in a cycle. You can see that the bottom sphere sinks into the kinematic box.

Here's the code for the modified BasicRestitution.cpp. The new part I added was the MovingPlatformEntity. Perhaps you can spot any mistakes I'm making:

Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/

#include <toolbox_stdafx.h>
#include "SkyBox.h"
#include "DemoEntityManager.h"
#include "DemoCamera.h"
#include "PhysicsUtils.h"
#include "DemoMesh.h"
#include "OpenGlUtil.h"



static void UserContactRestitution (const NewtonJoint* contactJoint, dFloat timestep, int threadIndex)
{
   dFloat Ixx;
   dFloat Iyy;
   dFloat Izz;
   dFloat mass;
   NewtonBody* body;
   NewtonBody* body0;
   NewtonBody* body1;

   // call  the basic call back
   GenericContactProcess (contactJoint, timestep, threadIndex);

   body0 = NewtonJointGetBody0(contactJoint);
   body1 = NewtonJointGetBody1(contactJoint);

   body = body0;
   NewtonBodyGetMass (body, &mass, &Ixx, &Iyy, &Izz);
   if (mass == 0.0f) {
      body = body1;
   }

   NewtonCollision* const collision = NewtonBodyGetCollision(body);
   void* userData = NewtonCollisionGetUserData (collision);
   dFloat restitution = *((dFloat*)&userData);
   for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
      NewtonMaterial* const material = NewtonContactGetMaterial (contact);
      NewtonMaterialSetContactElasticity (material, restitution);
   }
}

const float cMaxTime = 2.0f;
const dVector cStartPos(0.0f, -1.0f, 0.0f);
const dVector cEndPos(0.0f, 5.0f, 0.0f);

class MovingPlatformEntity : public DemoEntity
{
    public:
    MovingPlatformEntity(DemoEntityManager* const scene, int materialID) :
        DemoEntity(dGetIdentityMatrix(), NULL),
        m_boxBody(NULL),
        elapsed(0.0f)
    {
        scene->Append(this);

        NewtonWorld* const world = scene->GetNewton();

        dMatrix offsetMatrix(dGetIdentityMatrix());
        dVector boxSize(20.0f, 2.0f, 20.0f, 0.0f);
        NewtonCollision* const boxCollision = CreateConvexCollision(world, offsetMatrix, boxSize, _BOX_PRIMITIVE, 0);

        DemoMesh* const boxMesh = new DemoMesh("box", boxCollision, "smilli.tga", "smilli.tga", "smilli.tga");
        DemoSubMesh& subMesh = boxMesh->GetFirst()->GetInfo();
        dVector color = dVector(0.0f, 0.5f, 0.0f, 0.5f);
        subMesh.m_specular = color;
        subMesh.m_diffuse = color;
        subMesh.m_ambient = color;
        boxMesh->OptimizeForRender();
        SetMesh(boxMesh, offsetMatrix);

        dMatrix matrix(dGetIdentityMatrix());
        matrix.m_posit.m_x = cStartPos.m_x;
        matrix.m_posit.m_y = cStartPos.m_y;
        matrix.m_posit.m_z = cStartPos.m_z;

        float mass = 100.0f;
        NewtonBody* const rigidBody = NewtonCreateKinematicBody(world, boxCollision, &matrix[0][0]);
        NewtonBodySetMassProperties(rigidBody, mass, boxCollision);
        NewtonBodySetUserData(rigidBody, this);
        NewtonBodySetMaterialGroupID(rigidBody, materialID);
        NewtonBodySetDestructorCallback(rigidBody, PhysicsBodyDestructor);
        NewtonBodySetTransformCallback(rigidBody, DemoEntity::TransformCallback);
        NewtonBodySetCollidable(rigidBody, true);
        //NewtonBodySetForceAndTorqueCallback(rigidBody, PhysicsApplyGravityForce);

        NewtonDestroyCollision(boxCollision);

        m_boxBody = rigidBody;
        elapsed = 0.0f;
    }

    virtual void SimulationPreListener(DemoEntityManager* const scene, DemoEntityManager::dListNode* const mynode, dFloat timestep)
    {
        if (m_boxBody)
        {
            elapsed += timestep;
            if (elapsed > cMaxTime)
                elapsed = 0.0f;

            // Current position
            dMatrix currentMtx;
            NewtonBodyGetMatrix(m_boxBody, &currentMtx[0][0]);

            // Calculate desired position
            float t = elapsed / cMaxTime;
            dVector desiredPos;
            desiredPos.m_x = cStartPos.m_x * (1.0f - t) + cEndPos.m_x * t;
            desiredPos.m_y = cStartPos.m_y * (1.0f - t) + cEndPos.m_y * t;
            desiredPos.m_z = cStartPos.m_z * (1.0f - t) + cEndPos.m_z * t;

            // Set new position
            dMatrix mtx(dGetIdentityMatrix());
            mtx.m_posit.m_x = desiredPos.m_x;
            mtx.m_posit.m_y = desiredPos.m_y;
            mtx.m_posit.m_z = desiredPos.m_z;
            NewtonBodySetMatrix(m_boxBody, &mtx[0][0]);

            // Calculate velocity
            dVector vel = desiredPos - currentMtx.m_posit;
            vel.Scale(1.0f / timestep);

            // Set velocity / angular velocity
            NewtonBodySetVelocity(m_boxBody, &vel[0]);
            dVector angVel(0.0f, 0.0f, 0.0f);
            NewtonBodySetOmega(m_boxBody, &angVel[0]);
        }
    }

    NewtonBody* m_boxBody;
    float elapsed;
};


void Restitution (DemoEntityManager* const scene)
{
   scene->CreateSkyBox();

   // customize the scene after loading
   // set a user friction variable in the body for variable friction demos
   // later this will be done using LUA script
   NewtonWorld* const world = scene->GetNewton();
   dMatrix offsetMatrix (dGetIdentityMatrix());

   int defaultMaterialID = NewtonMaterialGetDefaultGroupID (world);
   NewtonMaterialSetCollisionCallback (world, defaultMaterialID, defaultMaterialID, NULL, UserContactRestitution);


   CreateLevelMesh (scene, "flatPlane.ngd", 1);

   dVector location (0.0f, 0.0f, 0.0f, 0.0f);

   // create some spheres
   dVector sphSize (2.0f, 2.0f, 2.0f, 0.0f);
   NewtonCollision* const sphereCollision = CreateConvexCollision (world, offsetMatrix, sphSize, _SPHERE_PRIMITIVE, 0);
   DemoMesh* const sphereMesh = new DemoMesh("sphere", sphereCollision, "smilli.tga", "smilli.tga", "smilli.tga");

   // create some boxes too
   dVector boxSize (2.0f, 2.0f, 2.0f, 0.0f);
   NewtonCollision* const boxCollision = CreateConvexCollision (world, offsetMatrix, boxSize, _BOX_PRIMITIVE, 0);
   DemoMesh* const boxMesh = new DemoMesh("box", boxCollision, "smilli.tga", "smilli.tga", "smilli.tga");

   //int zCount = 10;
   int zCount = 1;
   dFloat spacing = 4.0f;
   dMatrix matrix (dGetIdentityMatrix());
   dVector origin (matrix.m_posit);
   origin.m_x -= 0.0f;

   // create a simple scene
   for (int i = 0; i < zCount; i ++) {
      dFloat restitution = i * 0.1f + 0.083f;
      NewtonBody* body;
      NewtonCollision* collision;

      dFloat z;
      dFloat x;
      dFloat mass;

      x = origin.m_x;
      z = origin.m_z + (i - zCount / 2) * spacing;

      mass = 1.0f;
      matrix.m_posit = FindFloor (world, dVector (x, 100.0f, z), 200.0f);
      matrix.m_posit.m_w = 1.0f;

      matrix.m_posit.m_y += 6.0f;
      body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
      NewtonBodySetLinearDamping (body, 0.0f);
      collision = NewtonBodyGetCollision(body);
      
      NewtonCollisionSetUserData (collision, *((void**)&restitution));

      matrix.m_posit.m_y += 6.0f;
      //body = CreateSimpleSolid (scene, boxMesh, mass, matrix, boxCollision, defaultMaterialID);
      body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
      NewtonBodySetLinearDamping (body, 0.0f);
      collision = NewtonBodyGetCollision(body);
      NewtonCollisionSetUserData (collision, *((void**)&restitution));

      matrix.m_posit.m_y += 6.0f;
      body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
      NewtonBodySetLinearDamping (body, 0.0f);
      collision = NewtonBodyGetCollision(body);
      NewtonCollisionSetUserData (collision, *((void**)&restitution));

      matrix.m_posit.m_y += 6.0f;
      body = CreateSimpleSolid (scene, boxMesh, mass, matrix, boxCollision, defaultMaterialID);
      //body = CreateSimpleSolid (scene, sphereMesh, mass, matrix, sphereCollision, defaultMaterialID);
      NewtonBodySetLinearDamping (body, 0.0f);
      collision = NewtonBodyGetCollision(body);
      NewtonCollisionSetUserData (collision, *((void**)&restitution));
   }

   boxMesh->Release();
   sphereMesh->Release();
   NewtonDestroyCollision(boxCollision);
   NewtonDestroyCollision(sphereCollision);


   dMatrix camMatrix (dGetIdentityMatrix());
   dQuaternion rot (camMatrix);
   origin = dVector (-25.0f, 5.0f, 0.0f, 0.0f);
   scene->SetCameraMatrix(rot, origin);

    new MovingPlatformEntity(scene, defaultMaterialID);

}


Thanks for the help!
Cannos
 
Posts: 129
Joined: Thu Mar 04, 2010 5:41 pm

Re: Infinite mass moving platform

Postby LordHexahedron » Thu Sep 22, 2016 1:02 am

I would probably make it a static mesh and move it manually per what's described here:

http://newtondynamics.com/wiki/index.ph ... TriMesh%3F

Sometimes you may wish to move portions of static game world for creating elevators, trains and other special animations.


that sounds a lot like what you want, since it's static other dynamic bodies do not affect it.
That's at least my understanding of the API, I could be entirely wrong but it's worth a shot as it seems relatively trivial to implement.
LordHexahedron
 
Posts: 11
Joined: Sat Sep 03, 2016 10:05 pm

Re: Infinite mass moving platform

Postby JoeJ » Thu Sep 22, 2016 2:31 am

Hehe, fallen into Julios math lib trap :)

You have:
// Calculate velocity
dVector vel = desiredPos - currentMtx.m_posit;
vel.Scale(1.0f / timestep); // <- does nothing

but you need to assign the value returned fram the scale:

vel = vel.Scale(1.0f / timestep);

... same thing happens to me again and again :)
"Scale" is indeed misleading, "Scaled" might be better.
User avatar
JoeJ
 
Posts: 1453
Joined: Tue Dec 21, 2010 6:18 pm

Re: Infinite mass moving platform

Postby Cannos » Thu Sep 22, 2016 12:28 pm

Right you are, fixing the scale assignment looks like it worked. Thanks!

I should have known something strange was happening when I raised the scale arbitrarily and didn't see anything change. Better than when I was using the operator* on the vector to try to scale and instead got a cross product through! :)
Cannos
 
Posts: 129
Joined: Thu Mar 04, 2010 5:41 pm

Re: Infinite mass moving platform

Postby Julio Jerez » Fri Sep 23, 2016 10:11 am

glad you have going,
Cannos wrote:Better than when I was using the operator* on the vector to try to scale and instead got a cross product through! :)

btw the operation * and % has been replaced with CrossProduct and DotProduct functions name.
the old function are still there but the engine do no uses then anywhere.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 13 guests

cron