Simulation Construction Set

Simulation Construction Set

  • IHMC Home
  • All IHMC Docs
  • About IHMC

›Ground Contact Modeling

Getting Started

  • Quick Start
  • Requirements
  • Using IHMC Open Robotics Software .jar releases with Maven/Gradle
  • Building .jars
  • Depending Directly on the Source

Using the SCS GUI

  • Running a simulation
  • Changing the Camera Settings
  • SCS Variables
  • Graphing Variables
  • Simulation Replay
  • Data Buffer
  • Exporting Data
  • Export Snapshots and Video of the 3D View

Creating a New Simulation

  • Summary
  • Create a New Project
  • SimplePendulumSimulation.java
  • SimplePendulumRobot.java
  • Run the simulation

Adding Control to a Simulation

  • Summary
  • Adding control to a simulation
  • Run the simulation

Creating Links

  • Summary
  • Creating Links
  • Run the Simulation

Creating Robot with Multiple Joints

  • Summary
  • Create a New Package
  • Mobile Simulation
  • Initial Variables in MobileRobot Class
  • MobileRobot Class Description

Ground Contact Modeling

  • Summary
  • Create a New Package
  • Create a New Class FallingBrickSimulation
  • Create a New Class FallingBrickRobot
  • Create a New Class WavyGroundProfile
  • Description and Analysis

Implementing Closed-Chain Mechanisms Using External Force Points

  • Summary
  • Implementing Closed-Chain Mechanisms
  • FlyballGovernorSimulation Class
  • FlyballGovernorRobot Class
  • FlyballGovernorSimpleClosedLoopConstraintController Class
  • FlyballGovernorCommonControlParameters Class
  • Description and Analysis

Description and Analysis

1. Add the constructor to the FallingBrickRobot class

  public FallingBrickRobot()
     {
        super("FallingBrick");
         
        this.setGravity(0.0, 0.0, -G);
        // create the brick as a floating joint
        floatingJoint = new FloatingJoint("base", new Vector3d(0.0, 0.0, 0.0), this);
        Link link1 = base("base", YoAppearance.Red());
        floatingJoint.setLink(link1);
        this.addRootJoint(floatingJoint);
        // add ground contact points to the brick
        GroundContactPoint gc1 = new GroundContactPoint("gc1", new Vector3d(BASE_L / 2.0, BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc1);
        GroundContactPoint gc2 = new GroundContactPoint("gc2", new Vector3d(BASE_L / 2.0, -BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc2);
        GroundContactPoint gc3 = new GroundContactPoint("gc3", new Vector3d(-BASE_L / 2.0, BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc3);
        GroundContactPoint gc4 = new GroundContactPoint("gc4", new Vector3d(-BASE_L / 2.0, -BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc4);
        GroundContactPoint gc5 = new GroundContactPoint("gc5", new Vector3d(BASE_L / 2.0, BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc5);
        GroundContactPoint gc6 = new GroundContactPoint("gc6", new Vector3d(BASE_L / 2.0, -BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc6);
        GroundContactPoint gc7 = new GroundContactPoint("gc7", new Vector3d(-BASE_L / 2.0, BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc7);
        GroundContactPoint gc8 = new GroundContactPoint("gc8", new Vector3d(-BASE_L / 2.0, -BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc8);
        GroundContactPoint gc9 = new GroundContactPoint("gc9", new Vector3d(0.0, 0.0, BASE_H / 2.0 + BASE_H), this);
        floatingJoint.addGroundContactPoint(gc9);
        GroundContactPoint gc10 = new GroundContactPoint("gc10", new Vector3d(0.0, 0.0, -BASE_H / 2.0 - BASE_H), this);
        floatingJoint.addGroundContactPoint(gc10);
        this.setController(this); // tells the simulator to call the local doControl() method
        // instantiate ground contact model
        GroundContactModel groundModel = new LinearGroundContactModel(this, 1422, 150.6, 50.0, 1000.0,
                                                                      this.getRobotsYoVariableRegistry());
        // GroundContactModel groundModel = new CollisionGroundContactModel(this, 0.5, 0.7);
        GroundProfile3D profile = new WavyGroundProfile();
        groundModel.setGroundProfile3D(profile);
        this.setGroundContactModel(groundModel);
        initRobot();
        initControl();
     }
     /**
      * This method returns a brick link instance.
      */
     private Link base(String name, AppearanceDefinition appearance)
     {
        Link ret = new Link(name);
        ret.setMass(M1);
        ret.setMomentOfInertia(Ixx1, Iyy1, Izz1);
        ret.setComOffset(0.0, 0.0, 0.0);
        LinkGraphicsDescription linkGraphics = new LinkGraphicsDescription();
        linkGraphics.translate(0.0, 0.0, -B1);
        // linkGraphics.addCube((float)BASE_L, (float)BASE_W, (float)BASE_H, appearance);
        // linkGraphics.addCone((float)BASE_L,(float)BASE_W);
        linkGraphics.addPyramidCube(BASE_L, BASE_W, BASE_H, BASE_H, appearance);
        ret.setLinkGraphics(linkGraphics);
        return ret;
     }
     
     
     public YoVariableRegistry getYoVariableRegistry()
     {
        return registry;
     }
      
     public void initialize()
     {     
     }
     public String getDescription()
     {
        return getName();
     }
  }

Find the following 4 lines in FallingBrickRobot where the ground contact is defined:

GroundContactModel groundModel = new LinearGroundContactModel(this, 1422, 150.6, 50.0, 1000.0, this.getRobotsYoVariableRegistry());
GroundProfile3D profile = new WavyGroundProfile();
groundModel.setGroundProfile3D(profile);
this.setGroundContactModel(groundModel);

Lets look at it one line at a time.
Notice that the groundModel is an instance of the class LinearGroundContactModel and the GroundProfile is an instance of the class WavyGroundProfile().

2. Next add the method initRobot method in the FallingBrickRobot class

This method simply sets the bricks position, velocity, and acceleration initially.

     public void initRobot()
     {
        q_qlength = new DoubleYoVariable("q_qlength", registry);
        theta_x = new DoubleYoVariable("theta_x", registry);
        t.set(0.0);
        q_x = (DoubleYoVariable)this.getVariable("q_x");
        q_y = (DoubleYoVariable)this.getVariable("q_y");
        q_z = (DoubleYoVariable)this.getVariable("q_z");
        qd_x = (DoubleYoVariable)this.getVariable("qd_x");
        qd_y = (DoubleYoVariable)this.getVariable("qd_y");
        qd_z = (DoubleYoVariable)this.getVariable("qd_z");
        qdd_x = (DoubleYoVariable)this.getVariable("qdd_x");
        qdd_y = (DoubleYoVariable)this.getVariable("qdd_y");
        qdd_z = (DoubleYoVariable)this.getVariable("qdd_z");
        q_qs = (DoubleYoVariable)this.getVariable("q_qs");
        q_qx = (DoubleYoVariable)this.getVariable("q_qx");
        q_qy = (DoubleYoVariable)this.getVariable("q_qy");
        q_qz = (DoubleYoVariable)this.getVariable("q_qz");
        qd_wx = (DoubleYoVariable)this.getVariable("qd_wx");
        qd_wy = (DoubleYoVariable)this.getVariable("qd_wy");
        qd_wz = (DoubleYoVariable)this.getVariable("qd_wz");
        qdd_wx = (DoubleYoVariable)this.getVariable("qdd_wx");
        qdd_wy = (DoubleYoVariable)this.getVariable("qdd_wy");
        qdd_wz = (DoubleYoVariable)this.getVariable("qdd_wz");
        q_x.set(0.0);
        q_y.set(0.0);
        q_z.set(0.6);
        qd_x.set(0.0);
        qd_y.set(0.0);
        qd_z.set(0.0);
        q_qs.set(0.707);
        q_qx.set(0.3);
        q_qy.set(0.4);
        q_qz.set(0.5);
        qd_wx.set(0.0001);
        qd_wy.set(1.0);
        qd_wz.set(0.5001);
     }

3. Next add the initControl method to the FallingBrickRobot class

This method simply initializes the robots controller.

 public void initControl()
     {
        qdd2_wx = new DoubleYoVariable("qdd2_wx", registry);
        qdd2_wy = new DoubleYoVariable("qdd2_wy", registry);
        qdd2_wz = new DoubleYoVariable("qdd2_wz", registry);
        energy = new DoubleYoVariable("energy", registry);
     }
     
     public void doControl()
          {
             energy.set(  M1 * G * q_z.getDoubleValue() 
                          + 0.5 * M1 * qd_x.getDoubleValue() * qd_x.getDoubleValue() 
                          + 0.5 * M1 * qd_y.getDoubleValue() * qd_y.getDoubleValue() 
                          + 0.5 * M1 * qd_z.getDoubleValue() * qd_z.getDoubleValue()
                          + 0.5 * Ixx1 * qd_wx.getDoubleValue() * qd_wx.getDoubleValue() 
                          + 0.5 * Iyy1 * qd_wy.getDoubleValue() * qd_wy.getDoubleValue()
                          + 0.5 * Izz1 * qd_wz.getDoubleValue() * qd_wz.getDoubleValue());
                          
             qdd2_wx.set((Iyy1 - Izz1) / Ixx1 * qd_wy.getDoubleValue() * qd_wz.getDoubleValue());
             qdd2_wy.set((Izz1 - Ixx1) / Iyy1 * qd_wz.getDoubleValue() * qd_wx.getDoubleValue());
             qdd2_wz.set((Ixx1 - Iyy1) / Izz1 * qd_wx.getDoubleValue() * qd_wy.getDoubleValue());
          }

4. Add methods to WavyGroundProfile class

Add the following methods to your WavyGroundProfile class:

      public double heightAt(double x, double y, double z)
      {
         if ((x > xMin) && (x < xMax) && (y > yMin) && (y < yMax))
            return 1.0 * Math.exp(-Math.abs(2.0 * x)) * Math.exp(-Math.abs(2.0 * y)) * Math.sin(2.0 * Math.PI * 0.7 * x);
         else
            return 0.0;
      }
      public void surfaceNormalAt(double x, double y, double z, Vector3d normal)
      {
         normal.x = 0.0;
         normal.y = 0.0;
         normal.z = 1.0;
      }
      public void closestIntersectionTo(double x, double y, double z, Point3d point)
      {
         point.x = x;
         point.y = y;
         point.z = heightAt(x, y, z);
      }
      public void closestIntersectionAndNormalAt(double x, double y, double z, Point3d point, Vector3d normal)
      {
         closestIntersectionTo(x, y, z, point);
         surfaceNormalAt(x, y, z, normal);
      }
      public boolean checkIfInside(double x, double y, double z, Point3d intersectionToPack, Vector3d normalToPack)
      {
         closestIntersectionTo(x, y, z, intersectionToPack);
         surfaceNormalAt(x, y, z, normalToPack);
          
         return (z < intersectionToPack.getZ());
      }
       
      public boolean isClose(double x, double y, double z)
      {
         return boundingBox.isInside(x, y, z);
      }
      public BoundingBox3d getBoundingBox()
      {
         return boundingBox;
      }

Since WavyGroundProfile implements the interface GroundProfile, it defines the methods:
heightAt, isClose, surfaceNormalAt, closestIntersectionTo, closestIntersectionAndNormalAt, getXmin, getXmax, getYmin, getYmax, getXTiles, and getYTiles.

The point where the height of the ground is defined is in heightAt:
return 1.0 * Math.exp(-Math.abs(2.0x)) * Math.exp(-Math.abs(2.0y)) * Math.sin(2.0Math.PI0.7x);*

5. Change the profile of the terrain

Do this by changing the function heightAt. Run the simulation and see how the profile of the ground changed.

To read more about how to use and setup GroundProfile check out the Ground Profile Interface API page.

6. Examine the file LinearGroundContactModel.java

Since LinearGroundContactModel implements the interface GroundContactModel, it defines the method doGroundContact, where the ground contact forces are computed.

7. Study the doGroundContact and resolveContactForceZUp methods

These can be found in the file LinearStickSlipGroundContactModel.java

Notice that the ground is modeled as a linear spring-damper in the x and y directions and a non-linear spring and a linear damper in the z direction. Using a non-linear (hardening) spring in the z direction is a standard way to prevent ground chatter or bounce while still simulating a stiff ground. This GroundContactModel is a simple one and does not take into consideration the surface normal of the ground, or ground slipping. For this example simulation, that is ok, but in many instances, these effects are important. If so, then you should use one of the other ground contact models in the com.yobotics.simulationconstructionset.utils package, or create your own.

8. Experiment with different values of ground spring and damping constants

Note that as you lower the stiffnesses, greater penetration into the ground will occur. As you lower the damping constants, vibrations occur longer. However, if you increase the stiffness or damping constants too much, instabilities can occur due to numerical instabilities.

9. As a general rule of thumb

Ground stiffness and damping are tuned experimentally until an acceptable ground penetration and bounce is achieved. Try tuning the ground parameters for different ground penetration and bounce.

Various GroundProfiles and GroundContactModels are provided in the com.yobotics.simulationconstructionset.util.ground directory. You should examine the source code of these files (found in SimulationConstructionSet\src) in order to determine the model and profile best for your simulation, and to understand how to create your own custom ground contact model.

Full Code for Classes

FallingBrickSimulation

package us.ihmc.exampleSimulations.fallingBrick  ;
import us.ihmc.graphicsDescription.appearance.YoAppearance;
import us.ihmc.simulationconstructionset.SimulationConstructionSet;
import us.ihmc.simulationconstructionset.SimulationConstructionSetParameters;
import us.ihmc.simulationconstructionset.examples.FallingBrickRobot;
public class FallingBrickSimulation
{
    private enum GROUND_APPEARANCE
    {
        EARTH, STONE, ALUMINUM
    }
    SimulationConstructionSet sim;
    public FallingBrickSimulation()
    {
        GROUND_APPEARANCE appearance = GROUND_APPEARANCE.EARTH;
        FallingBrickRobot fallingBrick = new FallingBrickRobot();
        sim = new SimulationConstructionSet(fallingBrick, new SimulationConstructionSetParameters(16342));
        sim.setDT(0.001, 20);
        sim.setCameraPosition(-1.5, -2.5, 0.5);
        sim.setCameraFix(0.0, 0.0, 0.4);
        sim.setCameraTracking(false, true, true, false);
        sim.setCameraDolly(false, true, true, false);
        // Set up some graphs:
        sim.setupGraph("q_z");
        sim.setupEntryBox("qd_x");
        sim.setupEntryBox("qd_y");
        sim.setupEntryBox("qd_z");
        sim.setupEntryBox("qd_wx");
        sim.setupEntryBox("qd_wy");
        sim.setupEntryBox("qd_wz");
        switch (appearance)
        {
            case EARTH:
                sim.setGroundAppearance(YoAppearance.EarthTexture());
                break;
            case STONE:
                sim.setGroundAppearance(YoAppearance.StoneTexture());
                break;
            case ALUMINUM:
                sim.setGroundAppearance(YoAppearance.AluminumMaterial());
                break;
        }
        Thread myThread = new Thread(sim);
        myThread.start();
    }
    public static void main(String[] args)
    {
        new FallingBrickSimulation();
    }
}

FallingBrickRobot

package us.ihmc.exampleSimulations.fallingBrick;
import javax.vecmath.Vector3d;
import us.ihmc.jMonkeyEngineToolkit.GroundProfile3D;
import us.ihmc.robotics.robotDescription.LinkGraphicsDescription;
import us.ihmc.graphicsDescription.appearance.AppearanceDefinition;
import us.ihmc.graphicsDescription.appearance.YoAppearance;
import us.ihmc.robotics.dataStructures.variable.DoubleYoVariable;
import us.ihmc.simulationconstructionset.FloatingJoint;
import us.ihmc.simulationconstructionset.GroundContactModel;
import us.ihmc.simulationconstructionset.GroundContactPoint;
import us.ihmc.simulationconstructionset.Joint;
import us.ihmc.simulationconstructionset.Link;
import us.ihmc.simulationconstructionset.Robot;
import us.ihmc.robotics.dataStructures.registry.YoVariableRegistry;
import us.ihmc.robotics.robotController.RobotController;
import us.ihmc.simulationconstructionset.util.LinearGroundContactModel;
import us.ihmc.simulationconstructionset.util.ground.WavyGroundProfile;
public class FallingBrickRobot extends Robot implements RobotController
{
    private static final long serialVersionUID = 773713164696806099L;

    private static final double BASE_H = 0.1, BASE_W = 0.2, BASE_L = 0.3;
    private static final double B1 = BASE_H / 2.0;
    private static final double M1 = 1.7;
    private static final double Ixx1 = 0.1, Iyy1 = 0.5, Izz1 = 0.9;
    private static final double G = 9.81;
    private final YoVariableRegistry registry = new YoVariableRegistry("FallingBrickController");
    // position, velocity, and acceleration variables
    DoubleYoVariable q_x, q_y, q_z, qd_x, qd_y, qd_z, qdd_x, qdd_y, qdd_z;
    DoubleYoVariable q_qs, q_qx, q_qy, q_qz, qd_wx, qd_wy, qd_wz, qdd_wx, qdd_wy, qdd_wz;
    DoubleYoVariable energy, q_qlength, theta_x;
    DoubleYoVariable qdd2_wx, qdd2_wy, qdd2_wz;
    Joint floatingJoint;

    public FallingBrickRobot()
    {
        super("FallingBrick");

        this.setGravity(0.0, 0.0, -G);
        // create the brick as a floating joint
        floatingJoint = new FloatingJoint("base", new Vector3d(0.0, 0.0, 0.0), this);
        Link link1 = base("base", YoAppearance.Red());
        floatingJoint.setLink(link1);
        this.addRootJoint(floatingJoint);
        // add ground contact points to the brick
        GroundContactPoint gc1 = new GroundContactPoint("gc1", new Vector3d(BASE_L / 2.0, BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc1);
        GroundContactPoint gc2 = new GroundContactPoint("gc2", new Vector3d(BASE_L / 2.0, -BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc2);
        GroundContactPoint gc3 = new GroundContactPoint("gc3", new Vector3d(-BASE_L / 2.0, BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc3);
        GroundContactPoint gc4 = new GroundContactPoint("gc4", new Vector3d(-BASE_L / 2.0, -BASE_W / 2.0, BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc4);
        GroundContactPoint gc5 = new GroundContactPoint("gc5", new Vector3d(BASE_L / 2.0, BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc5);
        GroundContactPoint gc6 = new GroundContactPoint("gc6", new Vector3d(BASE_L / 2.0, -BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc6);
        GroundContactPoint gc7 = new GroundContactPoint("gc7", new Vector3d(-BASE_L / 2.0, BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc7);
        GroundContactPoint gc8 = new GroundContactPoint("gc8", new Vector3d(-BASE_L / 2.0, -BASE_W / 2.0, -BASE_H / 2.0), this);
        floatingJoint.addGroundContactPoint(gc8);
        GroundContactPoint gc9 = new GroundContactPoint("gc9", new Vector3d(0.0, 0.0, BASE_H / 2.0 + BASE_H), this);
        floatingJoint.addGroundContactPoint(gc9);
        GroundContactPoint gc10 = new GroundContactPoint("gc10", new Vector3d(0.0, 0.0, -BASE_H / 2.0 - BASE_H), this);
        floatingJoint.addGroundContactPoint(gc10);
        this.setController(this); // tells the simulator to call the local doControl() method
        // instantiate ground contact model
        GroundContactModel groundModel = new LinearGroundContactModel(this, 1422, 150.6, 50.0, 1000.0,
                this.getRobotsYoVariableRegistry());
        // GroundContactModel groundModel = new CollisionGroundContactModel(this, 0.5, 0.7);
        GroundProfile3D profile = new WavyGroundProfile();
        groundModel.setGroundProfile3D(profile);
        this.setGroundContactModel(groundModel);
        initRobot();
        initControl();
    }
    /**
     * This method returns a brick link instance.
     */
    private Link base(String name, AppearanceDefinition appearance)
    {
        Link ret = new Link(name);
        ret.setMass(M1);
        ret.setMomentOfInertia(Ixx1, Iyy1, Izz1);
        ret.setComOffset(0.0, 0.0, 0.0);
        LinkGraphicsDescription linkGraphics = new LinkGraphicsDescription();
        linkGraphics.translate(0.0, 0.0, -B1);
        // linkGraphics.addCube((float)BASE_L, (float)BASE_W, (float)BASE_H, appearance);
        // linkGraphics.addCone((float)BASE_L,(float)BASE_W);
        linkGraphics.addPyramidCube(BASE_L, BASE_W, BASE_H, BASE_H, appearance);
        ret.setLinkGraphics(linkGraphics);
        return ret;
    }

    /**
     * This method sets the initial positions, velocities, and accelerations of the brick
     */
    public void initRobot()
    {
        q_qlength = new DoubleYoVariable("q_qlength", registry);
        theta_x = new DoubleYoVariable("theta_x", registry);
        t.set(0.0);
        q_x = (DoubleYoVariable)this.getVariable("q_x");
        q_y = (DoubleYoVariable)this.getVariable("q_y");
        q_z = (DoubleYoVariable)this.getVariable("q_z");
        qd_x = (DoubleYoVariable)this.getVariable("qd_x");
        qd_y = (DoubleYoVariable)this.getVariable("qd_y");
        qd_z = (DoubleYoVariable)this.getVariable("qd_z");
        qdd_x = (DoubleYoVariable)this.getVariable("qdd_x");
        qdd_y = (DoubleYoVariable)this.getVariable("qdd_y");
        qdd_z = (DoubleYoVariable)this.getVariable("qdd_z");
        q_qs = (DoubleYoVariable)this.getVariable("q_qs");
        q_qx = (DoubleYoVariable)this.getVariable("q_qx");
        q_qy = (DoubleYoVariable)this.getVariable("q_qy");
        q_qz = (DoubleYoVariable)this.getVariable("q_qz");
        qd_wx = (DoubleYoVariable)this.getVariable("qd_wx");
        qd_wy = (DoubleYoVariable)this.getVariable("qd_wy");
        qd_wz = (DoubleYoVariable)this.getVariable("qd_wz");
        qdd_wx = (DoubleYoVariable)this.getVariable("qdd_wx");
        qdd_wy = (DoubleYoVariable)this.getVariable("qdd_wy");
        qdd_wz = (DoubleYoVariable)this.getVariable("qdd_wz");
        q_x.set(0.0);
        q_y.set(0.0);
        q_z.set(0.6);
        qd_x.set(0.0);
        qd_y.set(0.0);
        qd_z.set(0.0);
        q_qs.set(0.707);
        q_qx.set(0.3);
        q_qy.set(0.4);
        q_qz.set(0.5);
        qd_wx.set(0.0001);
        qd_wy.set(1.0);
        qd_wz.set(0.5001);
    }
    public void initControl()
    {
        qdd2_wx = new DoubleYoVariable("qdd2_wx", registry);
        qdd2_wy = new DoubleYoVariable("qdd2_wy", registry);
        qdd2_wz = new DoubleYoVariable("qdd2_wz", registry);
        energy = new DoubleYoVariable("energy", registry);
    }
    public void doControl()
    {
        energy.set(  M1 * G * q_z.getDoubleValue()
                + 0.5 * M1 * qd_x.getDoubleValue() * qd_x.getDoubleValue()
                + 0.5 * M1 * qd_y.getDoubleValue() * qd_y.getDoubleValue()
                + 0.5 * M1 * qd_z.getDoubleValue() * qd_z.getDoubleValue()
                + 0.5 * Ixx1 * qd_wx.getDoubleValue() * qd_wx.getDoubleValue()
                + 0.5 * Iyy1 * qd_wy.getDoubleValue() * qd_wy.getDoubleValue()
                + 0.5 * Izz1 * qd_wz.getDoubleValue() * qd_wz.getDoubleValue());

        qdd2_wx.set((Iyy1 - Izz1) / Ixx1 * qd_wy.getDoubleValue() * qd_wz.getDoubleValue());
        qdd2_wy.set((Izz1 - Ixx1) / Iyy1 * qd_wz.getDoubleValue() * qd_wx.getDoubleValue());
        qdd2_wz.set((Ixx1 - Iyy1) / Izz1 * qd_wx.getDoubleValue() * qd_wy.getDoubleValue());
    }
    public YoVariableRegistry getYoVariableRegistry()
    {
        return registry;
    }

    public void initialize()
    {
    }
    public String getDescription()
    {
        return getName();
    }
}

WavyGroundProfile

package us.ihmc.exampleSimulations.fallingBrick;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import us.ihmc.jMonkeyEngineToolkit.GroundProfile3D;
import us.ihmc.jMonkeyEngineToolkit.HeightMapWithNormals;
import us.ihmc.robotics.geometry.BoundingBox3d;

public class WavyGroundProfile implements GroundProfile3D, HeightMapWithNormals
{
    private double xMin = -2.0, xMax = 2.0, yMin = -2.0, yMax = 2.0, zMin = -10.0, zMax = 10.0;

    private BoundingBox3d boundingBox = new BoundingBox3d(new Point3d(xMin, yMin, zMin), new Point3d(xMax, yMax, zMax));
    public WavyGroundProfile()
    {
    }
    public double heightAndNormalAt(double x, double y, double z, Vector3d normalToPack)
    {
        double heightAt = heightAt(x, y, z);
        surfaceNormalAt(x, y, heightAt, normalToPack);
        return heightAt;
    }

    public double heightAt(double x, double y, double z)
    {
        if ((x > xMin) && (x < xMax) && (y > yMin) && (y < yMax))
            return 1.0 * Math.exp(-Math.abs(2.0 * x)) * Math.exp(-Math.abs(2.0 * y)) * Math.sin(2.0 * Math.PI * 0.7 * x);
        else
            return 0.0;
    }
    public void surfaceNormalAt(double x, double y, double z, Vector3d normal)
    {
        normal.x = 0.0;
        normal.y = 0.0;
        normal.z = 1.0;
    }
    public void closestIntersectionTo(double x, double y, double z, Point3d point)
    {
        point.x = x;
        point.y = y;
        point.z = heightAt(x, y, z);
    }
    public void closestIntersectionAndNormalAt(double x, double y, double z, Point3d point, Vector3d normal)
    {
        closestIntersectionTo(x, y, z, point);
        surfaceNormalAt(x, y, z, normal);
    }
    public boolean checkIfInside(double x, double y, double z, Point3d intersectionToPack, Vector3d normalToPack)
    {
        closestIntersectionTo(x, y, z, intersectionToPack);
        surfaceNormalAt(x, y, z, normalToPack);

        return (z < intersectionToPack.getZ());
    }

    public boolean isClose(double x, double y, double z)
    {
        return boundingBox.isInside(x, y, z);
    }
    public BoundingBox3d getBoundingBox()
    {
        return boundingBox;
    }
    public HeightMapWithNormals getHeightMapIfAvailable()
    {
        return this;
    }
}

← Create a New Class WavyGroundProfileSummary →
Simulation Construction Set
Docs
Quick StartSoftware Documentation
Community
GitHubFacebookTwitterYouTube
Copyright © 2018 IHMC Robotics