All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.ihmc.scs2.simulation.bullet.physicsEngine.BulletFlyingBallSimulationTest Maven / Gradle / Ivy

The newest version!
package us.ihmc.scs2.simulation.bullet.physicsEngine;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.commons.lang3.mutable.MutableObject;
import org.junit.jupiter.api.Test;

import us.ihmc.euclid.referenceFrame.interfaces.FrameVector3DReadOnly;
import us.ihmc.euclid.tools.EuclidCoreTestTools;
import us.ihmc.euclid.tuple3D.Point3D;
import us.ihmc.euclid.tuple3D.Vector3D;
import us.ihmc.scs2.definition.collision.CollisionShapeDefinition;
import us.ihmc.scs2.definition.geometry.Sphere3DDefinition;
import us.ihmc.scs2.definition.robot.MomentOfInertiaDefinition;
import us.ihmc.scs2.definition.robot.RigidBodyDefinition;
import us.ihmc.scs2.definition.robot.RobotDefinition;
import us.ihmc.scs2.definition.robot.SixDoFJointDefinition;
import us.ihmc.scs2.definition.state.SixDoFJointState;
import us.ihmc.scs2.definition.visual.ColorDefinitions;
import us.ihmc.scs2.definition.visual.MaterialDefinition;
import us.ihmc.scs2.definition.visual.VisualDefinition;
import us.ihmc.scs2.sessionVisualizer.jfx.SessionVisualizer;
import us.ihmc.scs2.sessionVisualizer.jfx.SessionVisualizerControls;
import us.ihmc.scs2.simulation.SimulationEnergyStatistics;
import us.ihmc.scs2.simulation.SimulationSession;
import us.ihmc.scs2.simulation.TimeConsumer;
import us.ihmc.scs2.simulation.bullet.physicsEngine.parameters.BulletMultiBodyJointParameters;
import us.ihmc.scs2.simulation.bullet.physicsEngine.parameters.BulletMultiBodyParameters;
import us.ihmc.scs2.simulation.physicsEngine.PhysicsEngineFactory;
import us.ihmc.scs2.simulation.robot.multiBodySystem.SimFloatingRootJoint;
import us.ihmc.yoVariables.euclid.YoPoint3D;
import us.ihmc.yoVariables.variable.YoDouble;

/**
 * Tests the ballistics equation:
 *
 * H(time) = -1/2 * g * t2 + V(initial) * t + H(initial)
 *
 * and asserts that the Orbital Energy remains constant.
 */
public class BulletFlyingBallSimulationTest
{
   private static final double EPSILON = 0.01;
   private static final boolean BULLET_PHYSICS_ENGINE = true;
   private static final boolean VISUALIZE = false;
   private static final int numberOfSimulationTicks = 1000;
   private YoPoint3D expectedPosition;
   private SimFloatingRootJoint floatingRootJoint;
   private YoDouble orbitalEnergyVariable;

   public SimulationSession createSession()
   {
      Point3D initialPosition = new Point3D(0.0, 0.0, 0.0);
      Vector3D initialVelocity = new Vector3D(0.0, 0.0, 0.0);

      double dt = 0.01;

      double ballRadius = 0.2;
      double ballMass = 2.0;
      String name = "sphere";

      RobotDefinition sphereRobot = new RobotDefinition(name);
      RigidBodyDefinition rootBody = new RigidBodyDefinition(name + "RootBody");
      SixDoFJointDefinition rootJoint = new SixDoFJointDefinition(name);
      rootBody.addChildJoint(rootJoint);

      RigidBodyDefinition rigidBody = new RigidBodyDefinition(name + "RigidBody");
      rigidBody.setMass(ballMass);
      rigidBody.setMomentOfInertia(new MomentOfInertiaDefinition(0.1, 0.1, 0.1));
      rigidBody.addVisualDefinition(new VisualDefinition(new Sphere3DDefinition(0.05),
                                                         new MaterialDefinition(null, ColorDefinitions.Brown(), ColorDefinitions.LightGray(), null, 10)));
      rootJoint.setSuccessor(rigidBody);

      sphereRobot.setRootBodyDefinition(rootBody);
      sphereRobot.getRigidBodyDefinition(name + "RigidBody").addCollisionShapeDefinition(new CollisionShapeDefinition(new Sphere3DDefinition(ballRadius)));

      SixDoFJointState sphereInitialState = new SixDoFJointState();
      sphereInitialState.setConfiguration(null, initialPosition);
      sphereInitialState.setVelocity(null, initialVelocity);
      sphereRobot.getRootJointDefinitions().get(0).setInitialJointState(sphereInitialState);

      SimulationSession simulationSession = null;
      if (BULLET_PHYSICS_ENGINE)
      {
         BulletMultiBodyParameters bulletMultiBodyParameters = BulletMultiBodyParameters.defaultBulletMultiBodyParameters();
         bulletMultiBodyParameters.setLinearDamping(0);
         bulletMultiBodyParameters.setMaxCoordinateVelocity(10000000);
         bulletMultiBodyParameters.setUseRK4Integration(true);
         BulletMultiBodyJointParameters bulletMultiBodyJointParameter = BulletMultiBodyJointParameters.defaultBulletMultiBodyJointParameters();
         simulationSession = new SimulationSession(BulletPhysicsEngineFactory.newBulletPhysicsEngineFactory(bulletMultiBodyParameters,
                                                                                                            bulletMultiBodyJointParameter));
      }
      else
      {
         simulationSession = new SimulationSession(PhysicsEngineFactory.newImpulseBasedPhysicsEngineFactory());
      }

      simulationSession.addRobot(sphereRobot);
      simulationSession.setSessionDTSeconds(dt);
      simulationSession.initializeBufferSize(2 * numberOfSimulationTicks);
      SimulationEnergyStatistics.setupSimulationEnergyStatistics(simulationSession);

      expectedPosition = new YoPoint3D("expectedSpherePosition", simulationSession.getRootRegistry());
      FrameVector3DReadOnly gravity = simulationSession.getGravity();

      floatingRootJoint = (SimFloatingRootJoint) simulationSession.getPhysicsEngine().getRobots().get(0).getJoint(name);

      orbitalEnergyVariable = (YoDouble) simulationSession.getRootRegistry().findVariable(name + "OrbitalEnergy");

      simulationSession.addAfterPhysicsCallback(time -> expectedPosition.set(heightAfterSeconds(initialPosition, initialVelocity, time, gravity.getZ())));
      return simulationSession;
   }

   @Test
   public void testFlyingBall() throws Throwable
   {
      SimulationSession simulationSession = createSession();

      simulationSession.addAfterPhysicsCallback(new TimeConsumer()
      {
         double initialOrbitalEnergy = 0;

         @Override
         public void accept(double time)
         {
            EuclidCoreTestTools.assertEquals(expectedPosition, floatingRootJoint.getJointPose().getPosition(), EPSILON);

            //orbital energy should remain constant
            if (initialOrbitalEnergy == 0)
               initialOrbitalEnergy = orbitalEnergyVariable.getValue();
            assertEquals(initialOrbitalEnergy, orbitalEnergyVariable.getValue(), 0.1, "Orbital Energy failed at time = " + time);
         }
      });

      MutableObject caughtException = new MutableObject<>(null);
      simulationSession.addRunThrowableListener(t -> caughtException.setValue(t));

      SessionVisualizerControls visualizerControls = null;
      if (VISUALIZE)
      {
         visualizerControls = SessionVisualizer.startSessionVisualizer(simulationSession);
         visualizerControls.waitUntilVisualizerFullyUp();
      }

      try
      {
         simulationSession.getSimulationSessionControls().simulateNow(numberOfSimulationTicks);
         if (caughtException.getValue() != null)
            throw caughtException.getValue();
      }
      finally
      {
         if (VISUALIZE)
         {
            visualizerControls.waitUntilVisualizerDown();
         }
      }

      simulationSession.shutdownSession();
   }

   private static Vector3D heightAfterSeconds(Point3D initialPosition, Vector3D initialVelocity, double seconds, double gravity)
   {
      //H(time) = -1/2 * g * t^2 + V(initial) * t + H(initial)
      Vector3D height = new Vector3D();

      height.setX(initialVelocity.getX() * seconds + initialPosition.getX());
      height.setY(initialVelocity.getY() * seconds + initialPosition.getY());
      height.setZ(0.5 * gravity * seconds * seconds + initialVelocity.getZ() * seconds + initialPosition.getZ());

      return height;
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy