BowlerKernel
MobileBasePhysicsManager.java
Go to the documentation of this file.
1 package com.neuronrobotics.bowlerstudio.physics;
2 
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.stream.Collectors;
8 
9 import javax.vecmath.Quat4f;
10 import javax.vecmath.Vector3f;
11 
12 import com.bulletphysics.dynamics.RigidBody;
13 import com.bulletphysics.dynamics.constraintsolver.HingeConstraint;
14 import com.bulletphysics.linearmath.Transform;
15 import com.neuronrobotics.bowlerstudio.creature.MobileBaseCadManager;
16 import com.neuronrobotics.sdk.addons.kinematics.AbstractLink;
17 import com.neuronrobotics.sdk.addons.kinematics.DHLink;
18 import com.neuronrobotics.sdk.addons.kinematics.DHParameterKinematics;
19 import com.neuronrobotics.sdk.addons.kinematics.ILinkListener;
20 import com.neuronrobotics.sdk.addons.kinematics.LinkConfiguration;
21 import com.neuronrobotics.sdk.addons.kinematics.MobileBase;
22 import com.neuronrobotics.sdk.addons.kinematics.imu.IMU;
23 import com.neuronrobotics.sdk.addons.kinematics.imu.IMUUpdate;
24 import com.neuronrobotics.sdk.addons.kinematics.math.RotationNR;
25 import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR;
26 import com.neuronrobotics.sdk.common.IClosedLoopController;
27 import com.neuronrobotics.sdk.pid.PIDLimitEvent;
28 import com.neuronrobotics.sdk.util.ThreadUtil;
29 
30 import Jama.Matrix;
31 
32 import eu.mihosoft.vrl.v3d.CSG;
33 //import eu.mihosoft.vrl.v3d.ext.quickhull3d.HullUtil;
34 //import eu.mihosoft.vvecmath.Vector3d;
35 import javafx.application.Platform;
36 import javafx.scene.paint.Color;
37 import javafx.scene.transform.Affine;
38 
40 
41  public static final float PhysicsGravityScalar = 6;
42  private HashMap<LinkConfiguration, ArrayList<CSG>> simplecad;
43  private float lift = 0;
44  private ArrayList<ILinkListener> linkListeners = new ArrayList<>();
45  public static final float LIFT_EPS = (float) Math.toRadians(0.1);
46 
47  private IPhysicsUpdate getUpdater(RigidBody body, IMU base) {
48  return new IPhysicsUpdate() {
49  Vector3f oldavelocity = new Vector3f(0f, 0f, 0f);
50  Vector3f oldvelocity = new Vector3f(0f, 0f, 0f);
51  Vector3f gravity = new Vector3f();
52  private Quat4f orentation = new Quat4f();
53  Transform gravTrans = new Transform();
54  Transform orentTrans = new Transform();
55  Vector3f avelocity = new Vector3f();
56  Vector3f velocity = new Vector3f();
57 
58  @Override
59  public void update(float timeStep) {
60 
61  body.getAngularVelocity(avelocity);
62  body.getLinearVelocity(velocity);
63 
64  body.getGravity(gravity);
65  body.getOrientation(orentation);
66 
67  TransformFactory.nrToBullet(new TransformNR(gravity.x, gravity.y, gravity.z, new RotationNR()),
68  gravTrans);
70  new TransformNR(0, 0, 0, orentation.w, orentation.x, orentation.y, orentation.z), orentTrans);
71  orentTrans.inverse();
72  orentTrans.mul(gravTrans);
73 
74  // A=DeltaV / DeltaT
75  Double rotxAcceleration = (double) ((oldavelocity.x - avelocity.x) / timeStep);
76  Double rotyAcceleration = (double) ((oldavelocity.y - avelocity.y) / timeStep);
77  Double rotzAcceleration = (double) ((oldavelocity.z - avelocity.z) / timeStep);
78  Double xAcceleration = (double) (((oldvelocity.x - velocity.x) / timeStep) / PhysicsGravityScalar)
79  + (orentTrans.origin.x / PhysicsGravityScalar);
80  Double yAcceleration = (double) (((oldvelocity.y - velocity.y) / timeStep) / PhysicsGravityScalar)
81  + (orentTrans.origin.y / PhysicsGravityScalar);
82  Double zAcceleration = (double) (((oldvelocity.z - velocity.z) / timeStep) / PhysicsGravityScalar)
83  + (orentTrans.origin.z / PhysicsGravityScalar);
84  // tell the virtual IMU the system updated
85  base.setVirtualState(new IMUUpdate(xAcceleration, yAcceleration, zAcceleration, rotxAcceleration,
86  rotyAcceleration, rotzAcceleration));
87  // update the old variables
88  oldavelocity.set(avelocity);
89  oldvelocity.set(velocity);
90 
91  }
92  };
93  }
94 
95  public MobileBasePhysicsManager(MobileBase base, ArrayList<CSG> baseCad,
96  HashMap<LinkConfiguration, ArrayList<CSG>> simplecad) {
97  this(base, baseCad, simplecad, PhysicsEngine.get());
98  }
99 
100  public MobileBasePhysicsManager(MobileBase base, ArrayList<CSG> baseCad,
101  HashMap<LinkConfiguration, ArrayList<CSG>> simplecad, PhysicsCore core) {
102  this.simplecad = simplecad;
103  double minz = 0;
104  double Maxz = 0;
105  for (DHParameterKinematics dh : base.getAllDHChains()) {
106  if (dh.getCurrentTaskSpaceTransform().getZ() < minz) {
107  minz = dh.getCurrentTaskSpaceTransform().getZ();
108  }
109  }
110  for (CSG c : baseCad) {
111  if (c.getMinZ() < minz) {
112  minz = c.getMinZ();
113  }
114  if (c.getMaxZ() > Maxz) {
115  Maxz = c.getMaxZ();
116  }
117  }
118  // System.out.println("Minimum z = "+minz);
119  Transform start = new Transform();
121  // TransformNR globe= base.getFiducialToGlobalTransform();
122 
124  start.origin.z = (float) (start.origin.z - minz + lift);
125  Platform.runLater(new Runnable() {
126  @Override
127  public void run() {
128  TransformFactory.bulletToAffine(baseCad.get(0).getManipulator(), start);
129  }
130  });
131  CSG collisionBod;
132 // ArrayList<Vector3d> points = new ArrayList<Vector3d>();
133 // try {
134 // for (DHParameterKinematics leg : base.getAllDHChains()) {
135 // TransformNR limbRoot = leg.getRobotToFiducialTransform();
136 // points.add(Vector3d.xyz(limbRoot.getX(), limbRoot.getY(), limbRoot.getZ()));
137 // points.add(Vector3d.xyz(limbRoot.getX(), limbRoot.getY(), Maxz));
138 // }
139 //
140 // collisionBod = HullUtil.hull(points);
141 // } catch (Exception ex) {
142  collisionBod = CSG.hullAll(MobileBaseCadManager.getBaseCad(base));
143 // }
144 
145  CSGPhysicsManager baseManager = new CSGPhysicsManager((List<CSG>) Arrays.asList(collisionBod), start,
146  base.getMassKg(), false, core);
147  baseManager.setBaseCSG(baseCad);
148 
149  RigidBody body = baseManager.getFallRigidBody();
150  baseManager.setUpdateManager(getUpdater(body, base.getImu()));
151  body.setWorldTransform(start);
152  core.getDynamicsWorld().setGravity(new Vector3f(0, 0, (float) -98 * PhysicsGravityScalar));
153  core.add(baseManager);
154  for (int j = 0; j < base.getAllDHChains().size(); j++) {
155  DHParameterKinematics dh = base.getAllDHChains().get(j);
157  RigidBody lastLink = body;
158  Matrix previousStep = null;
159  // ensure the dh-cache chain is computed and recent
161  ArrayList<TransformNR> cachedStart = dh.getDhChain().getCachedChain();
162  List<TransformNR> cached = cachedStart.stream().collect(Collectors.toList());
163  for (int i = 0; i < dh.getNumberOfLinks() && i < cached.size(); i++) {
164  // Hardware to engineering units configuration
166  // DH parameters
167  DHLink l = dh.getDhChain().getLinks().get(i);
168  ArrayList<CSG> thisLinkCad = simplecad.get(conf);
169  if (thisLinkCad != null && thisLinkCad.size() > 0) {
170 
171  // use the DH parameters to calculate the offset of the link
172  // at 0 degrees
173  Matrix step;
174  if (conf.isPrismatic()) {
175  step = l.DhStepInversePrismatic(0);
176  } else {
177  step = l.DhStepInverseRotory(Math.toRadians(0));
178  }
179  // correct jog for singularity.
180 
181  // Engineering units to kinematics link (limits and hardware
182  // type abstraction)
183  AbstractLink abstractLink = dh.getAbstractLink(i);
184 
185  // Transform used by the UI to render the location of the
186  // object
187  Affine manipulator = new Affine();// make a new affine for the physics engine to service. the
188  // manipulaters in the CSG will not conflict for resources here
189  // The DH chain calculated the starting location of the link
190  // in its current configuration
191  TransformNR localLink;
192  if (i > 0)
193  localLink = cached.get(i - 1);
194  else
195  localLink = limbRoot.copy();
196  // Lift it in the air so nothing is below the ground to
197  // start.
198  localLink.translateZ(lift);
199  // Bullet engine transform object
200  Transform linkLoc = new Transform();
201  TransformFactory.nrToBullet(localLink, linkLoc);
202  linkLoc.origin.z = (float) (linkLoc.origin.z - minz + lift);
203 
204  // Set the manipulator to the location from the kinematics,
205  // needs to be in UI thread to touch manipulator
206  Platform.runLater(new Runnable() {
207  @Override
208  public void run() {
209  TransformFactory.nrToAffine(localLink, manipulator);
210  }
211  });
212  ThreadUtil.wait(16);
213 
214  double mass = conf.getMassKg();
215  ArrayList<CSG> outCad = new ArrayList<>();
216  ArrayList<CSG> collisions = new ArrayList<>();
217  for (int x = 0; x < thisLinkCad.size(); x++) {
218  Color color = thisLinkCad.get(x).getColor();
219  CSG cad = thisLinkCad.get(x);
221  // tmp=tmp.difference(tmp.toXMax())
222  outCad.add(cad.transformed(TransformFactory.nrToCSG(new TransformNR(step).inverse())));
223  outCad.get(x).setManipulator(manipulator);
224  outCad.get(x).setColor(color);
225 
226  collisions.add(tmp.transformed(TransformFactory.nrToCSG(new TransformNR(step).inverse())));
227  collisions.get(x).setManipulator(manipulator);
228  collisions.get(x).setColor(color);
229 
230  }
231 
232  // Build a hinge based on the link and mass
233  // was outCad
234  HingeCSGPhysicsManager hingePhysicsManager = new HingeCSGPhysicsManager(collisions, linkLoc, mass,
235  core);
236  hingePhysicsManager.setBaseCSG(outCad);
238 
239  RigidBody linkSection = hingePhysicsManager.getFallRigidBody();
240 
241  hingePhysicsManager.setUpdateManager(getUpdater(linkSection, abstractLink.getImu()));
242  // // Setup some damping on the m_bodies
243  // linkSection.setDamping(0.5f, 08.5f);
244  // linkSection.setDeactivationTime(0.8f);
245  // linkSection.setSleepingThresholds(1.6f, 2.5f);
246  linkSection.setActivationState(
247  com.bulletphysics.collision.dispatch.CollisionObject.DISABLE_DEACTIVATION);
248 
249  // linkSection.set
250 
251  HingeConstraint joint6DOF;
252  Transform localA = new Transform();
253  Transform localB = new Transform();
254  localA.setIdentity();
255  localB.setIdentity();
256 
257  // set up the center of mass offset from the centroid of the
258  // links
259  if (i == 0) {
260 
262  } else {
263  TransformFactory.nrToBullet(new TransformNR(previousStep.inverse()), localA);
264  }
265  // set the link constraint based on DH parameters
266  TransformFactory.nrToBullet(new TransformNR(), localB);
267  previousStep = step;
268  // build the hinge constraint
269  joint6DOF = new HingeConstraint(lastLink, linkSection, localA, localB);
270  joint6DOF.setLimit(-(float) Math.toRadians(abstractLink.getMinEngineeringUnits()),
271  -(float) Math.toRadians(abstractLink.getMaxEngineeringUnits()));
272 
273  lastLink = linkSection;
274 
275  hingePhysicsManager.setConstraint(joint6DOF);
276 
277  if (!conf.isPassive()) {
278  ILinkListener ll = new ILinkListener() {
279  @Override
280  public void onLinkPositionUpdate(AbstractLink source, double engineeringUnitsValue) {
281  // System.out.println("
282  // value="+engineeringUnitsValue);
283  hingePhysicsManager.setTarget(Math.toRadians(-engineeringUnitsValue));
284 
285  // joint6DOF.setLimit( (float)
286  // (Math.toRadians(-engineeringUnitsValue )-
287  // LIFT_EPS),
288  // (float) (Math.toRadians(-engineeringUnitsValue )+
289  // LIFT_EPS));
290  }
291 
292  @Override
293  public void onLinkLimit(AbstractLink source, PIDLimitEvent event) {
294  // println event
295  }
296  };
297  hingePhysicsManager.setController(new IClosedLoopController() {
298 
299  @Override
300  public double compute(double currentState, double target, double seconds) {
301  double error = target - currentState;
302  return (error / seconds) * (seconds * 10);
303  }
304  });
305  abstractLink.addLinkListener(ll);
306  linkListeners.add(ll);
307  }
308 
309  abstractLink.getCurrentPosition();
310  core.add(hingePhysicsManager);
311  linkSection.setWorldTransform(linkLoc);
312  }
313  }
314  }
315  }
316 
317  public void clear() {
318  if(simplecad!=null) {
319  simplecad.clear();
320  }
321  linkListeners.clear();
322  }
323 }
MobileBasePhysicsManager(MobileBase base, ArrayList< CSG > baseCad, HashMap< LinkConfiguration, ArrayList< CSG >> simplecad)
MobileBasePhysicsManager(MobileBase base, ArrayList< CSG > baseCad, HashMap< LinkConfiguration, ArrayList< CSG >> simplecad, PhysicsCore core)
static eu.mihosoft.vrl.v3d.Transform nrToCSG(TransformNR nr)
static void bulletToAffine(Affine affine, com.bulletphysics.linearmath.Transform bullet)
static void nrToBullet(TransformNR nr, com.bulletphysics.linearmath.Transform bullet)
ArrayList< TransformNR > getCachedChain()
Definition: DHChain.java:273
ArrayList< DHParameterKinematics > getAllDHChains()
void setVirtualState(IMUUpdate virtualState)
Definition: IMU.java:41
CSG transformed(Transform transform)
Definition: CSG.java:1676
CSG setManipulator(Affine manipulator)
Definition: CSG.java:235
static CSG hullAll(CSG... csgs)
Definition: CSG.java:880
CSG setColor(Color color)
Definition: CSG.java:207