99import us .ihmc .euclid .referenceFrame .interfaces .FixedFramePoint3DBasics ;
1010import us .ihmc .euclid .referenceFrame .interfaces .FixedFrameVector3DBasics ;
1111import us .ihmc .euclid .referenceFrame .interfaces .FramePoint2DBasics ;
12+ import us .ihmc .euclid .referenceFrame .interfaces .FramePoint2DReadOnly ;
1213import us .ihmc .euclid .referenceFrame .interfaces .FramePoint3DReadOnly ;
1314import us .ihmc .euclid .referenceFrame .interfaces .FrameVector3DReadOnly ;
1415import us .ihmc .euclid .referenceFrame .interfaces .FrameVertex2DSupplier ;
3940import us .ihmc .yoVariables .providers .BooleanProvider ;
4041import us .ihmc .yoVariables .providers .DoubleProvider ;
4142import us .ihmc .yoVariables .registry .YoRegistry ;
43+ import us .ihmc .yoVariables .variable .YoBoolean ;
4244
4345class SingleFootEstimator implements SCS2YoGraphicHolder
4446{
@@ -57,13 +59,17 @@ class SingleFootEstimator implements SCS2YoGraphicHolder
5759 private final YoFrameVector3D footFusedLinearVelocityInWorld ;
5860 private final YoFrameVector3D footFusedAngularVelocityInWorld ;
5961
62+ private final YoBoolean footIsMoving ;
63+
6064 private final YoFrameVector3D copVelocityInWorld ;
6165 private final AlphaFilteredYoFrameVector3D footToRootJointPosition ;
6266 private final YoFramePoint3D footPositionInWorld ;
6367 /** Debug variable */
6468 private final YoFramePoint3D rootJointPositionPerFoot ;
6569
66- private final YoFramePoint3D copPositionInWorld ;
70+ private final YoFramePoint3D copIKPositionInWorld ;
71+ private final YoFramePoint3D copIMUPositionInWorld ;
72+ private final YoFramePoint3D copFusedPositionInWorld ;
6773 private final YoFramePoint2D previousCoPInFootFrame ;
6874
6975 private final AlphaFilteredYoFramePoint2D copFilteredInFootFrame ;
@@ -124,6 +130,8 @@ public SingleFootEstimator(FloatingJointBasics rootJoint,
124130 copRawInFootFrame = new YoFramePoint2D (namePrefix + "CoPRawInFootFrame" , soleFrame , registry );
125131 previousCoPInFootFrame = new YoFramePoint2D (namePrefix + "PreviousCoPInFootFrame" , soleFrame , registry );
126132
133+ footIsMoving = new YoBoolean (namePrefix + "IsMoving" , registry );
134+
127135 footIKLinearVelocityInWorld = new YoFrameVector3D (namePrefix + "IKLinearVelocityInWorld" , worldFrame , registry );
128136 footIKAngularVelocityInWorld = new YoFrameVector3D (namePrefix + "IKAngularVelocityInWorld" , worldFrame , registry );
129137 footIMULinearVelocityInWorld = new YoFrameVector3D (namePrefix + "IMULinearVelocityInWorld" , worldFrame , registry );
@@ -134,7 +142,9 @@ public SingleFootEstimator(FloatingJointBasics rootJoint,
134142 DoubleProvider alphaCop = () -> AlphaFilterTools .computeAlphaGivenBreakFrequencyProperly (copFilterBreakFrequency .getValue (), estimatorDT );
135143 copFilteredInFootFrame = new AlphaFilteredYoFramePoint2D (namePrefix + "CoPFilteredInFootFrame" , "" , registry , alphaCop , copRawInFootFrame );
136144 copFilteredInFootFrame .update (0.0 , 0.0 );
137- copPositionInWorld = new YoFramePoint3D (namePrefix + "CoPPositionInWorld" , worldFrame , registry );
145+ copIKPositionInWorld = new YoFramePoint3D (namePrefix + "CoPIKPositionInWorld" , worldFrame , registry );
146+ copIMUPositionInWorld = new YoFramePoint3D (namePrefix + "CoPIMUPositionInWorld" , worldFrame , registry );
147+ copFusedPositionInWorld = new YoFramePoint3D (namePrefix + "CoPFusedPositionInWorld" , worldFrame , registry );
138148 copVelocityInWorld = new YoFrameVector3D (namePrefix + "CoPVelocityInWorld" , worldFrame , registry );
139149 }
140150
@@ -144,7 +154,7 @@ public void createVisualization(YoGraphicsListRegistry yoGraphicsListRegistry)
144154 return ;
145155
146156 String sidePrefix = foot .getName ();
147- YoGraphicPosition copInWorld = new YoGraphicPosition (sidePrefix + "StateEstimatorCoP" , copPositionInWorld , 0.005 , YoAppearance .DeepPink ());
157+ YoGraphicPosition copInWorld = new YoGraphicPosition (sidePrefix + "StateEstimatorCoP" , copFusedPositionInWorld , 0.005 , YoAppearance .DeepPink ());
148158 YoArtifactPosition artifact = copInWorld .createArtifact ();
149159 artifact .setVisible (false );
150160 yoGraphicsListRegistry .registerArtifact ("StateEstimator" , artifact );
@@ -153,7 +163,7 @@ public void createVisualization(YoGraphicsListRegistry yoGraphicsListRegistry)
153163 @ Override
154164 public YoGraphicDefinition getSCS2YoGraphics ()
155165 {
156- return YoGraphicDefinitionFactory .newYoGraphicPoint2D (foot .getName () + "StateEstimatorCoP" , copPositionInWorld ,
166+ return YoGraphicDefinitionFactory .newYoGraphicPoint2D (foot .getName () + "StateEstimatorCoP" , copFusedPositionInWorld ,
157167 0.01 ,
158168 ColorDefinitions .DeepPink (),
159169 DefaultPoint2DGraphic .CIRCLE );
@@ -192,6 +202,12 @@ public void updateKinematics(TwistReadOnly rootBodyTwist)
192202 tempFrameVector .changeFrame (worldFrame );
193203
194204 footToRootJointPosition .update (tempFrameVector );
205+
206+ // FIXME remove magic parameters
207+ if (USE_IMU_DATA )
208+ footIsMoving .set (getFootLinearVelocityInWorld ().norm () > 0.5 || getFootAngularVelocityInWorld ().norm () > 1.0 );
209+ else
210+ footIsMoving .set (false );
195211 }
196212
197213 /**
@@ -202,7 +218,7 @@ public void updateKinematics(TwistReadOnly rootBodyTwist)
202218 public void updateCoPAndFootSettingZ (boolean trustCoPAsNonSlippingContactPoint , boolean useControllerDesiredCoP , double zPosition )
203219 {
204220 updateCoPPosition (trustCoPAsNonSlippingContactPoint , useControllerDesiredCoP );
205- copPositionInWorld .setZ (zPosition );
221+ copFusedPositionInWorld .setZ (zPosition );
206222 correctFootPositionsUsingCoP (trustCoPAsNonSlippingContactPoint );
207223 }
208224
@@ -257,14 +273,14 @@ public void correctFootPositionFromRootJoint(boolean isTrusted, boolean trustCoP
257273
258274 if (!isTrusted )
259275 {
260- copPositionInWorld .set (footPositionInWorld );
276+ copFusedPositionInWorld .set (footPositionInWorld );
261277 copRawInFootFrame .setToZero ();
262278 copFilteredInFootFrame .setToZero ();
263279 }
264280 else if (trustCoPAsNonSlippingContactPoint )
265281 {
266282 tempFrameVector .sub (footPositionInWorld , tempPoint ); // Delta from previous to new foot position
267- copPositionInWorld .add (tempFrameVector ); // New CoP position
283+ copFusedPositionInWorld .add (tempFrameVector ); // New CoP position
268284 }
269285 }
270286
@@ -288,6 +304,11 @@ public FrameVector3DReadOnly getFootAngularVelocityInWorld()
288304 return footFusedAngularVelocityInWorld ;
289305 }
290306
307+ public boolean isFootMoving ()
308+ {
309+ return footIsMoving .getBooleanValue ();
310+ }
311+
291312 private final FramePoint2D tempCoP2d = new FramePoint2D ();
292313 private final FrameVector3D tempCoPOffset = new FrameVector3D ();
293314
@@ -340,23 +361,35 @@ private void updateCoPPosition(boolean trustCoPAsNonSlippingContactPoint, boolea
340361 copRawInFootFrame .set (tempCoP2d );
341362 copFilteredInFootFrame .update ();
342363
364+ // Update the CoP value from kinematics. This treats it as non-stationary.
365+ copIKPositionInWorld .setMatchingFrame (soleFrame , copFilteredInFootFrame .getX (), copFilteredInFootFrame .getY (), 0.0 );
366+
343367 // Update the change in the CoP from the previous tick.
344368 tempCoPOffset .setIncludingFrame (soleFrame ,
345369 copFilteredInFootFrame .getX () - previousCoPInFootFrame .getX (),
346370 copFilteredInFootFrame .getY () - previousCoPInFootFrame .getY (),
347371 0.0 );
348372 tempCoPOffset .changeFrame (worldFrame );
349373 // Apply this same change to the CoP in world.
350- copPositionInWorld .add (tempCoPOffset );
374+ copFusedPositionInWorld .add (tempCoPOffset );
351375 }
352376 else
353377 {
354378 tempCoP2d .setToZero (soleFrame );
355- copRawInFootFrame .setToZero ();
356- copFilteredInFootFrame .setToZero ();
357- copPositionInWorld .setFromReferenceFrame (soleFrame );
379+ // Update the CoP value to match the center of the foot.
380+ copIKPositionInWorld .setFromReferenceFrame (soleFrame );
358381 }
359382
383+ if (USE_IMU_DATA )
384+ {
385+ // Integrate the fused position using the velocity, which is from the kinematics and the IMU.
386+ computeLinearVelocityAtPointInWorld (copFusedPositionInWorld , tempFrameVector );
387+ copIMUPositionInWorld .scaleAdd (footAlphaLeakIMUOnly .getValue () * estimatorDT , tempFrameVector , copFusedPositionInWorld );
388+
389+ // Fuse the kinematic data with the IMU data
390+ double alpha = AlphaFilterTools .computeAlphaGivenBreakFrequencyProperly (imuAgainstKinematicsForPositionBreakFrequency .getValue (), estimatorDT );
391+ copFusedPositionInWorld .interpolate (copIKPositionInWorld , copIMUPositionInWorld , alpha );
392+ }
360393 }
361394
362395 private void correctFootPositionsUsingCoP (boolean trustCoPAsNonSlippingContactPoint )
@@ -368,7 +401,7 @@ private void correctFootPositionsUsingCoP(boolean trustCoPAsNonSlippingContactPo
368401 tempCoPOffset .setIncludingFrame (copFilteredInFootFrame , 0.0 );
369402 tempCoPOffset .changeFrame (worldFrame );
370403 // Update where the foot must be, according to this CoP location
371- footPositionInWorld .sub (copPositionInWorld , tempCoPOffset );
404+ footPositionInWorld .sub (copFusedPositionInWorld , tempCoPOffset );
372405 }
373406
374407 private final FrameVector3D linearAcceleration = new FrameVector3D ();
@@ -445,10 +478,15 @@ private void computeFootTwistInWorld(TwistReadOnly rootBodyTwist)
445478 }
446479
447480 private void computeCoPLinearVelocityInWorld (FixedFrameVector3DBasics footLinearVelocityToPack )
481+ {
482+ computeLinearVelocityAtPointInWorld (copFusedPositionInWorld , footLinearVelocityToPack );
483+ }
484+
485+ private void computeLinearVelocityAtPointInWorld (FramePoint3DReadOnly point , FixedFrameVector3DBasics footLinearVelocityToPack )
448486 {
449487 footTwistInWorld .getLinearPart ().set (footFusedLinearVelocityInWorld );
450488 footTwistInWorld .getAngularPart ().set (footFusedAngularVelocityInWorld );
451489
452- footTwistInWorld .getLinearVelocityAt (copPositionInWorld , footLinearVelocityToPack );
490+ footTwistInWorld .getLinearVelocityAt (point , footLinearVelocityToPack );
453491 }
454492}
0 commit comments