3131
3232public class RDXMultiContactRegionGraphic implements RenderableProvider
3333{
34- private static final Color POLYGON_GRAPHIC_COLOR = Color .valueOf ("DEE933" );
34+ private static final Color NOMINAL_POLYGON_GRAPHIC_COLOR = Color .valueOf ("DEE933" );
35+ private static final Color LOW_STABILITY_POLYGON_GRAPHIC_COLOR = Color .valueOf ("EB3D40" );
3536 private static final double STABILITY_GRAPHIC_HEIGHT = 2.0 ;
3637
37- private final ConvexPolygon2D multiContactSupportRegion = new ConvexPolygon2D ();
38+ private final ConvexPolygon2D supportRegion = new ConvexPolygon2D ();
3839
3940 private final FramePoint3D comCurrent = new FramePoint3D ();
41+ private final FramePoint3D comDesired = new FramePoint3D ();
4042 private final FramePoint3D comXYAtFootHeight = new FramePoint3D ();
41- private final ConvexPolygon2D closestProximityEdge = new ConvexPolygon2D ();
43+ private final FramePoint3D desiredCoMXYAtFootHeight = new FramePoint3D ();
4244
4345 private int minimumEdgeIndex ;
4446 private double minimumEdgeDistance ;
4547
4648 private final ModelBuilder modelBuilder = new ModelBuilder ();
4749 private final RDXMultiColorMeshBuilder meshBuilder = new RDXMultiColorMeshBuilder ();
48- private final FullHumanoidRobotModel ghostFullRobotModel ;
4950 private final CenterOfMassReferenceFrame centerOfMassFrame ;
5051 private final MidFrameZUpFrame midFeetZUpFrame ;
5152 private final RigidBodyTransform transform = new RigidBodyTransform ();
@@ -55,68 +56,97 @@ public class RDXMultiContactRegionGraphic implements RenderableProvider
5556
5657 public RDXMultiContactRegionGraphic (FullHumanoidRobotModel ghostFullRobotModel )
5758 {
58- this .ghostFullRobotModel = ghostFullRobotModel ;
5959 this .centerOfMassFrame = new CenterOfMassReferenceFrame ("ghostCoMFrame" , ReferenceFrame .getWorldFrame (), ghostFullRobotModel .getRootBody ());
6060 this .midFeetZUpFrame = new MidFrameZUpFrame ("midFeedZUpWhost" ,
6161 ReferenceFrame .getWorldFrame (),
6262 ghostFullRobotModel .getSoleFrame (RobotSide .LEFT ),
6363 ghostFullRobotModel .getSoleFrame (RobotSide .RIGHT ));
6464 }
6565
66- public void update (KinematicsToolboxOutputStatus kinematicsToolboxOutputStatus )
66+ public void update (KinematicsToolboxOutputStatus kinematicsToolboxOutputStatus , FramePoint3D desiredCoMPosition )
6767 {
68- multiContactSupportRegion .clear ();
69- Object <Point3D > supportRegion = kinematicsToolboxOutputStatus .getSupportRegion ();
70-
71- for (int i = 0 ; i < supportRegion .size (); i ++)
72- {
73- multiContactSupportRegion .addVertex (supportRegion .get (i ));
74- }
75-
76- multiContactSupportRegion .update ();
77-
78- if (multiContactSupportRegion .getNumberOfVertices () < 3 )
79- {
80- modelInstance = null ;
81- lastModel = null ;
82- return ;
83- }
84-
8568 meshBuilder .clear ();
8669
70+ // Update frames and compute mid-feet height
8771 centerOfMassFrame .update ();
8872 midFeetZUpFrame .update ();
89- updateMinimumEdge ();
9073
9174 FramePoint3D midFoot = new FramePoint3D (midFeetZUpFrame );
9275 midFoot .changeFrame (ReferenceFrame .getWorldFrame ());
9376 double footZ = midFoot .getZ ();
9477
95- transform .setTranslationAndIdentityRotation (0.0 , 0.0 , footZ );
96-
97- for (int i = 0 ; i < multiContactSupportRegion .getNumberOfVertices (); i ++)
78+ // Update desired and achieved CoM graphic
9879 {
99- Point2DReadOnly v0 = multiContactSupportRegion .getVertex (i );
100- Point2DReadOnly v1 = multiContactSupportRegion .getNextVertex (i );
80+ comCurrent .setToZero (centerOfMassFrame );
81+ comCurrent .changeFrame (ReferenceFrame .getWorldFrame ());
82+
83+ meshBuilder .addSphere (0.03f , comCurrent , Color .BLACK );
84+
85+ comXYAtFootHeight .setIncludingFrame (comCurrent );
86+ comXYAtFootHeight .setZ (footZ );
87+ meshBuilder .addSphere (0.03f , comXYAtFootHeight , Color .BLACK );
88+
89+ FramePoint3D comXYElevated = new FramePoint3D (comXYAtFootHeight );
90+ comXYElevated .addZ (STABILITY_GRAPHIC_HEIGHT );
91+ meshBuilder .addLine (comXYAtFootHeight , comXYElevated , 0.005f , Color .BLACK );
92+
93+ if (desiredCoMPosition != null )
94+ {
95+ comDesired .setMatchingFrame (desiredCoMPosition );
96+ meshBuilder .addSphere (0.03f , comDesired , Color .GREEN );
97+
98+ desiredCoMXYAtFootHeight .setIncludingFrame (comDesired );
99+ desiredCoMXYAtFootHeight .setZ (footZ );
100+ meshBuilder .addSphere (0.03f , desiredCoMXYAtFootHeight , Color .GREEN );
101101
102- Color color = i == minimumEdgeIndex ? Color .RED : POLYGON_GRAPHIC_COLOR ;
103- meshBuilder .addLine (v0 .getX (), v0 .getY (), footZ , v1 .getX (), v1 .getY (), footZ , 0.01f , color );
102+ FramePoint3D desiredComXYElevated = new FramePoint3D (desiredCoMXYAtFootHeight );
103+ desiredComXYElevated .addZ (STABILITY_GRAPHIC_HEIGHT );
104+ meshBuilder .addLine (desiredCoMXYAtFootHeight , desiredComXYElevated , 0.005f , Color .GREEN );
105+ }
104106 }
105107
106- meshBuilder .addPolygon (transform , multiContactSupportRegion , POLYGON_GRAPHIC_COLOR );
108+ // Update region graphic
109+ Object <Point3D > ikSupportRegion = kinematicsToolboxOutputStatus .getSupportRegion ();
110+ if (ikSupportRegion .size () >= 3 )
111+ {
112+ this .supportRegion .clear ();
113+
114+ for (int i = 0 ; i < ikSupportRegion .size (); i ++)
115+ {
116+ this .supportRegion .addVertex (ikSupportRegion .get (i ));
117+ }
118+
119+ this .supportRegion .update ();
107120
108- comCurrent .setToZero (centerOfMassFrame );
109- comCurrent .changeFrame (ReferenceFrame .getWorldFrame ());
121+ if (this .supportRegion .getNumberOfVertices () < 3 )
122+ {
123+ modelInstance = null ;
124+ lastModel = null ;
125+ return ;
126+ }
110127
111- meshBuilder . addSphere ( 0.03f , comCurrent , Color . BLACK );
128+ updateMinimumEdge ( );
112129
113- comXYAtFootHeight .setIncludingFrame (comCurrent );
114- comXYAtFootHeight .setZ (footZ );
115- meshBuilder .addSphere (0.03f , comXYAtFootHeight , Color .BLACK );
130+ transform .setTranslationAndIdentityRotation (0.0 , 0.0 , footZ );
116131
117- FramePoint3D comXYElevated = new FramePoint3D (comXYAtFootHeight );
118- comXYElevated .addZ (STABILITY_GRAPHIC_HEIGHT );
119- meshBuilder .addLine (comXYAtFootHeight , comXYElevated , 0.005f , Color .BLACK );
132+ for (int i = 0 ; i < this .supportRegion .getNumberOfVertices (); i ++)
133+ {
134+ Point2DReadOnly v0 = this .supportRegion .getVertex (i );
135+ Point2DReadOnly v1 = this .supportRegion .getNextVertex (i );
136+
137+ Color color = i == minimumEdgeIndex ? Color .RED : NOMINAL_POLYGON_GRAPHIC_COLOR ;
138+ meshBuilder .addLine (v0 .getX (), v0 .getY (), footZ , v1 .getX (), v1 .getY (), footZ , 0.01f , color );
139+ }
140+
141+ double postureSensitivityThreshold = 0.045 ;
142+ double stabilityMarginThreshold = 0.12 ;
143+
144+ boolean isPostureHighlySensitive = kinematicsToolboxOutputStatus .getSupportRegionSensitivity () > postureSensitivityThreshold ;
145+ boolean hasLowStabilityMargin = minimumEdgeDistance < stabilityMarginThreshold ;
146+
147+ Color polygonGraphicColor = (isPostureHighlySensitive && hasLowStabilityMargin ) ? LOW_STABILITY_POLYGON_GRAPHIC_COLOR : NOMINAL_POLYGON_GRAPHIC_COLOR ;
148+ meshBuilder .addPolygon (transform , this .supportRegion , polygonGraphicColor );
149+ }
120150
121151 modelBuilder .begin ();
122152 Mesh mesh = meshBuilder .generateMesh ();
@@ -139,10 +169,10 @@ private void updateMinimumEdge()
139169 {
140170 minimumEdgeDistance = Double .POSITIVE_INFINITY ;
141171
142- for (int i = 0 ; i < multiContactSupportRegion .getNumberOfVertices (); i ++)
172+ for (int i = 0 ; i < supportRegion .getNumberOfVertices (); i ++)
143173 {
144- Point2DReadOnly v0 = multiContactSupportRegion .getVertex (i );
145- Point2DReadOnly v1 = multiContactSupportRegion .getNextVertex (i );
174+ Point2DReadOnly v0 = supportRegion .getVertex (i );
175+ Point2DReadOnly v1 = supportRegion .getNextVertex (i );
146176
147177 double margin = EuclidGeometryTools .distanceFromPoint2DToLine2D (comXYAtFootHeight .getX (), comXYAtFootHeight .getY (), v0 , v1 );
148178 if (margin < minimumEdgeDistance )
@@ -156,7 +186,7 @@ private void updateMinimumEdge()
156186 @ Override
157187 public void getRenderables (Array <Renderable > renderables , Pool <Renderable > pool )
158188 {
159- if (multiContactSupportRegion .isEmpty ())
189+ if (supportRegion .isEmpty ())
160190 {
161191 return ;
162192 }
0 commit comments