Skip to content

Commit f006217

Browse files
authored
Fix behavior footstep plan action bug and document graphic classes. (#638)
1 parent dc0ca74 commit f006217

File tree

6 files changed

+115
-50
lines changed

6 files changed

+115
-50
lines changed

ihmc-communication/src/main/java/us/ihmc/communication/crdt/CRDTBidirectionalRigidBodyTransform.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ public RigidBodyTransform getValueUnsafe()
3535
return getValueInternal();
3636
}
3737

38+
/** Prefer this method in the case you need to call it every tick, as it no-ops in the case the value is the same. */
39+
public void setValue(RigidBodyTransformReadOnly value, double epsilon)
40+
{
41+
// rotation and translation must be checked separately to handle pose-transform comparison case
42+
// translation must use epsilonEquals because it can be vector vs. point
43+
if (!(getValueInternal().getRotation().geometricallyEquals(value.getRotation(), epsilon)
44+
&& getValueInternal().getTranslation().epsilonEquals(value.getTranslation(), epsilon)))
45+
{
46+
getValueAndModify().set(value);
47+
}
48+
}
49+
3850
public void toMessage(Pose3D poseMessage)
3951
{
4052
poseMessage.set(getValueReadOnly());

ihmc-high-level-behaviors/src/libgdx/java/us/ihmc/rdx/ui/behavior/actions/RDXFootstepPlanAction.java

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import us.ihmc.rdx.ui.behavior.sequence.RDXActionNode;
3838
import us.ihmc.rdx.ui.behavior.tools.RDXCRDTTools;
3939
import us.ihmc.rdx.ui.gizmo.RDXSelectablePose3DGizmo;
40-
import us.ihmc.rdx.ui.graphics.RDXFootstepGraphic;
4140
import us.ihmc.rdx.ui.graphics.RDXFootstepPlanGraphic;
4241
import us.ihmc.rdx.ui.widgets.ImGuiFootstepsWidget;
4342
import us.ihmc.rdx.vr.RDXVRContext;
@@ -73,8 +72,7 @@ public class RDXFootstepPlanAction extends RDXActionNode<FootstepPlanActionState
7372
private final RDXMutableArrowModel goalArrowGraphic = new RDXMutableArrowModel();
7473
private final RDXSelectablePose3DGizmo goalStancePointGizmo = new RDXSelectablePose3DGizmo();
7574
private final RDXSelectablePose3DGizmo goalFocalPointGizmo = new RDXSelectablePose3DGizmo();
76-
private final SideDependentList<RDXFootstepGraphic> goalFeetGraphics = new SideDependentList<>();
77-
private final SideDependentList<RDXSelectablePose3DGizmo> goalFeetGizmos = new SideDependentList<>();
75+
private final SideDependentList<RDXFootstepPlanActionGoalFootstep> goalFeet = new SideDependentList<>();
7876
private final RDX3DPanelTooltip tooltip;
7977
private final ImGuiFootstepsWidget footstepsWidget = new ImGuiFootstepsWidget();
8078
private final RDXFootstepPlanGraphic previewFootstepPlan;
@@ -165,16 +163,7 @@ public RDXFootstepPlanAction(long id,
165163
goalFocalPointGizmo.getPoseGizmo().getCenterSphereToTorusRatio().set(0.5f);
166164

167165
for (RobotSide side : RobotSide.values)
168-
{
169-
RDXSelectablePose3DGizmo footGizmo = new RDXSelectablePose3DGizmo(ReferenceFrame.getWorldFrame(), state.getGoalFootstepToGoalTransform(side));
170-
footGizmo.create(baseUI.getPrimary3DPanel());
171-
footGizmo.getPoseGizmo().getCenterSphereToTorusRatio().set(0.3f);
172-
goalFeetGizmos.put(side, footGizmo);
173-
174-
RDXFootstepGraphic goalFootGraphic = new RDXFootstepGraphic(robotModel.getContactPointParameters().getControllerFootGroundContactPoints(), side);
175-
goalFootGraphic.create();
176-
goalFeetGraphics.put(side, goalFootGraphic);
177-
}
166+
goalFeet.put(side, new RDXFootstepPlanActionGoalFootstep(baseUI, side, definition, state, robotModel));
178167

179168
previewFootstepPlan = new RDXFootstepPlanGraphic(robotModel.getContactPointParameters().getControllerFootGroundContactPoints());
180169

@@ -240,14 +229,13 @@ public void update()
240229
goalFocalPointGizmo.getPoseGizmo().setParentFrame(parentFrame);
241230

242231
for (RobotSide side : RobotSide.values)
243-
goalFeetGizmos.get(side).getPoseGizmo().setParentFrame(state.getGoalFrame().getReferenceFrame());
232+
goalFeet.get(side).setParentFrame();
244233

245234
RDXCRDTTools.syncGizmoWithBidirectionalField(goalStancePointGizmo.getPoseGizmo(), definition.getGoalStancePoint(), definition);
246235
RDXCRDTTools.syncGizmoWithBidirectionalField(goalFocalPointGizmo.getPoseGizmo(), definition.getGoalFocalPoint(), definition);
247236

248237
for (RobotSide side : RobotSide.values)
249-
if (goalFeetGizmos.get(side).getPoseGizmo().getGizmoModifiedByUser().poll())
250-
definition.modify();
238+
goalFeet.get(side).handleGizmoModifiedByUser();
251239

252240
if (definition.isModified())
253241
for (RobotSide side : RobotSide.values)
@@ -272,10 +260,7 @@ public void update()
272260
});
273261

274262
for (RobotSide side : RobotSide.values)
275-
{
276-
goalFeetGizmos.get(side).getPoseGizmo().update();
277-
goalFeetGraphics.get(side).setPose(goalFeetGizmos.get(side).getPoseGizmo().getPose());
278-
}
263+
goalFeet.get(side).updatePoses();
279264

280265
if (state.getIsNextForExecution())
281266
{
@@ -344,9 +329,7 @@ public void calculate3DViewPick(ImGui3DViewInput input)
344329
goalStancePointGizmo.calculate3DViewPick(input);
345330
goalFocalPointGizmo.calculate3DViewPick(input);
346331
for (RobotSide side : RobotSide.values)
347-
{
348-
goalFeetGizmos.get(side).calculate3DViewPick(input);
349-
}
332+
goalFeet.get(side).calculate3DViewPick(input);
350333
}
351334
}
352335
}
@@ -369,9 +352,7 @@ public void process3DViewInput(ImGui3DViewInput input)
369352
goalFocalPointGizmo.process3DViewInput(input, false);
370353
tooltip.setInput(input);
371354
for (RobotSide side : RobotSide.values)
372-
{
373-
goalFeetGizmos.get(side).process3DViewInput(input, false);
374-
}
355+
goalFeet.get(side).process3DViewInput(input);
375356
}
376357
}
377358
}
@@ -433,7 +414,7 @@ protected void renderImGuiWidgetsInternal()
433414
ImGui.checkbox(labels.get("Focal Point"), goalFocalPointGizmo.getSelected());
434415
for (RobotSide side : RobotSide.values)
435416
{
436-
ImGui.checkbox(labels.get(side.getPascalCaseName() + " Foot to Goal"), goalFeetGizmos.get(side).getSelected());
417+
ImGui.checkbox(labels.get(side.getPascalCaseName() + " Foot to Goal"), goalFeet.get(side).getGizmo().getSelected());
437418
if (side == RobotSide.LEFT)
438419
ImGui.sameLine();
439420
}
@@ -466,7 +447,7 @@ public void deselectGizmos()
466447
goalStancePointGizmo.setSelected(false);
467448
goalFocalPointGizmo.setSelected(false);
468449
for (RobotSide side : RobotSide.values)
469-
goalFeetGizmos.get(side).setSelected(false);
450+
goalFeet.get(side).getGizmo().setSelected(false);
470451
editManuallyPlacedSteps.set(false);
471452
}
472453

@@ -486,7 +467,7 @@ public void getRenderables(Array<Renderable> renderables, Pool<Renderable> pool)
486467
{
487468
if (state.areFramesInWorld())
488469
{
489-
if (definition.getIsManuallyPlaced() && (state.getIsNextForExecution() || getSelected()))
470+
if (definition.getIsManuallyPlaced())
490471
{
491472
for (RDXFootstepPlanActionFootstep footstep : manuallyPlacedFootsteps)
492473
{
@@ -500,19 +481,10 @@ public void getRenderables(Array<Renderable> renderables, Pool<Renderable> pool)
500481
goalStancePointGizmo.getVirtualRenderables(renderables, pool);
501482
goalFocalPointGizmo.getVirtualRenderables(renderables, pool);
502483
for (RobotSide side : RobotSide.values)
503-
{
504-
goalFeetGizmos.get(side).getVirtualRenderables(renderables, pool);
505-
}
506-
for (RobotSide side : RobotSide.values)
507-
{
508-
goalFeetGraphics.get(side).setHighlighted(footstepsWidget.getIsHovered().get(side));
509-
goalFeetGraphics.get(side).getRenderables(renderables, pool);
510-
}
484+
goalFeet.get(side).getRenderables(renderables, pool, footstepsWidget.getIsHovered().get(side));
511485

512486
if (state.getIsNextForExecution())
513-
{
514487
previewFootstepPlan.getRenderables(renderables, pool);
515-
}
516488
}
517489
}
518490
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package us.ihmc.rdx.ui.behavior.actions;
2+
3+
import com.badlogic.gdx.graphics.g3d.Renderable;
4+
import com.badlogic.gdx.utils.Array;
5+
import com.badlogic.gdx.utils.Pool;
6+
import us.ihmc.avatar.drcRobot.DRCRobotModel;
7+
import us.ihmc.behaviors.sequence.actions.FootstepPlanActionDefinition;
8+
import us.ihmc.behaviors.sequence.actions.FootstepPlanActionState;
9+
import us.ihmc.euclid.referenceFrame.ReferenceFrame;
10+
import us.ihmc.rdx.input.ImGui3DViewInput;
11+
import us.ihmc.rdx.ui.RDXBaseUI;
12+
import us.ihmc.rdx.ui.gizmo.RDXSelectablePose3DGizmo;
13+
import us.ihmc.rdx.ui.graphics.RDXFootstepGraphic;
14+
import us.ihmc.robotics.robotSide.RobotSide;
15+
16+
/** UI for the behavior footstep plan action's modifiable goal footstep, used by the footstep planner. */
17+
public class RDXFootstepPlanActionGoalFootstep
18+
{
19+
private final FootstepPlanActionDefinition definition;
20+
private final FootstepPlanActionState state;
21+
22+
private final RDXSelectablePose3DGizmo gizmo;
23+
private final RDXFootstepGraphic graphic;
24+
25+
public RDXFootstepPlanActionGoalFootstep(RDXBaseUI baseUI,
26+
RobotSide side,
27+
FootstepPlanActionDefinition definition,
28+
FootstepPlanActionState state,
29+
DRCRobotModel robotModel)
30+
{
31+
this.definition = definition;
32+
this.state = state;
33+
34+
gizmo = new RDXSelectablePose3DGizmo(ReferenceFrame.getWorldFrame(), state.getGoalFootstepToGoalTransform(side));
35+
gizmo.create(baseUI.getPrimary3DPanel());
36+
gizmo.getPoseGizmo().getCenterSphereToTorusRatio().set(0.3f);
37+
38+
graphic = new RDXFootstepGraphic(robotModel.getContactPointParameters().getControllerFootGroundContactPoints(), side);
39+
graphic.create();
40+
}
41+
42+
public void setParentFrame()
43+
{
44+
gizmo.getPoseGizmo().setParentFrame(state.getGoalFrame().getReferenceFrame());
45+
}
46+
47+
public void handleGizmoModifiedByUser()
48+
{
49+
if (gizmo.getPoseGizmo().getGizmoModifiedByUser().poll())
50+
definition.modify();
51+
}
52+
53+
public void updatePoses()
54+
{
55+
gizmo.getPoseGizmo().update();
56+
graphic.setPose(gizmo.getPoseGizmo().getPose());
57+
}
58+
59+
public void calculate3DViewPick(ImGui3DViewInput input)
60+
{
61+
gizmo.calculate3DViewPick(input);
62+
}
63+
64+
public void process3DViewInput(ImGui3DViewInput input)
65+
{
66+
gizmo.process3DViewInput(input, false);
67+
}
68+
69+
public void getRenderables(Array<Renderable> renderables, Pool<Renderable> pool, boolean isHighlighted)
70+
{
71+
gizmo.getVirtualRenderables(renderables, pool);
72+
graphic.setHighlighted(isHighlighted);
73+
graphic.getRenderables(renderables, pool);
74+
}
75+
76+
public RDXSelectablePose3DGizmo getGizmo()
77+
{
78+
return gizmo;
79+
}
80+
}

ihmc-high-level-behaviors/src/libgdx/java/us/ihmc/rdx/ui/graphics/RDXFootstepGraphic.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@
2929
import us.ihmc.scs2.definition.visual.ColorDefinition;
3030

3131
import java.util.ArrayList;
32-
import java.util.concurrent.atomic.AtomicInteger;
3332

33+
/**
34+
* A multiline, colored outline graphic of the foot, typically the 100% support polygon.
35+
*/
3436
public class RDXFootstepGraphic implements RenderableProvider
3537
{
3638
public static final Color LEFT_FOOT_RED_COLOR = new Color(0.5f, 0.0f, 0.0f, 1.0f);
3739
public static final Color RIGHT_FOOT_GREEN_COLOR = new Color(0.0f, 0.5f, 0.0f, 1.0f);
3840
public static final SideDependentList<Color> FOOT_COLORS = new SideDependentList<>(LEFT_FOOT_RED_COLOR, RIGHT_FOOT_GREEN_COLOR);
39-
private static final AtomicInteger INDEX = new AtomicInteger();
4041

4142
private final Color color;
4243
private final Color highlightColor;

ihmc-high-level-behaviors/src/libgdx/java/us/ihmc/rdx/ui/graphics/RDXFootstepPlanGraphic.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import us.ihmc.footstepPlanning.PlannedFootstep;
2626
import us.ihmc.log.LogTools;
2727
import us.ihmc.rdx.RDX3DSituatedText;
28-
import us.ihmc.rdx.mesh.RDXIDMappedColorFunction;
2928
import us.ihmc.rdx.mesh.RDXMultiColorMeshBuilder;
3029
import us.ihmc.rdx.tools.LibGDXTools;
3130
import us.ihmc.rdx.tools.RDXModelBuilder;
@@ -38,24 +37,25 @@
3837
import java.util.EnumMap;
3938
import java.util.List;
4039
import java.util.concurrent.atomic.AtomicReference;
41-
import java.util.function.Function;
4240

41+
/**
42+
* A graphic representing one or more sequential footsteps.
43+
* They are colored outlines of the maximum base of support, with a solid fill, and text number on each step.
44+
* Optionally, more text can be added to give a name to the footstep plan.
45+
*
46+
* TODO: Make this class hold a list of RDXFootstepGraphic instead, moving the extra elements here to that class.
47+
*/
4348
public class RDXFootstepPlanGraphic implements RenderableProvider
4449
{
4550
private final ModelBuilder modelBuilder = new ModelBuilder();
46-
RDXMultiColorMeshBuilder meshBuilder = new RDXMultiColorMeshBuilder();
47-
// visualization options
48-
private final Function<Integer, Color> colorFunction = new RDXIDMappedColorFunction();
51+
private final RDXMultiColorMeshBuilder meshBuilder = new RDXMultiColorMeshBuilder();
4952
private final SideDependentList<Color> footstepColors = new SideDependentList<>();
50-
5153
{
5254
footstepColors.set(RobotSide.LEFT, new Color(RDXFootstepGraphic.LEFT_FOOT_RED_COLOR));
5355
footstepColors.set(RobotSide.RIGHT, new Color(RDXFootstepGraphic.RIGHT_FOOT_GREEN_COLOR));
5456
}
55-
5657
private final SideDependentList<ConvexPolygon2D> defaultContactPoints = new SideDependentList<>();
5758
private volatile Runnable buildMeshAndCreateModelInstance = null;
58-
5959
private ModelInstance modelInstance;
6060
private Model lastModel;
6161

ihmc-high-level-behaviors/src/main/java/us/ihmc/behaviors/sequence/actions/FootstepPlanActionExecutor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public void update()
135135
snappedGoalStancePose.getRotation().set(stanceOrientation);
136136
snappedGoalStancePose.changeFrame(state.getParentFrame());
137137

138-
state.getGoalToParentTransform().getValue().set(snappedGoalStancePose);
138+
state.getGoalToParentTransform().setValue(snappedGoalStancePose, 1e-5);
139139
state.getGoalFrame().getReferenceFrame().update();
140140

141141
for (RobotSide side : RobotSide.values)

0 commit comments

Comments
 (0)