Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draw log data to SVG for papers #376

Merged
merged 56 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e188ec8
Add SCS 2 log data processor and generate SVG file of CoM trajectory.
calvertdw Sep 26, 2024
8f3903f
Plot the CoM trajectory and get it loading in Inkscape.
calvertdw Sep 27, 2024
448b7c9
Flip Y, plot footsteps.
calvertdw Sep 27, 2024
4795de9
Use better method for detecting footsteps and separate SVG from data …
calvertdw Sep 27, 2024
72efaf7
Add a UI to manage logs.
calvertdw Sep 30, 2024
927c63e
Making progress on log scrubber.
calvertdw Sep 30, 2024
b56bb3c
Iterate on log data processing.
calvertdw Oct 1, 2024
0d0c24d
Clean up code to add more stuff.
calvertdw Oct 2, 2024
d5d9f84
Add working counter mismatch & number of walks.
calvertdw Oct 2, 2024
07b2f1d
Rename foot state class.
calvertdw Oct 2, 2024
4b9a3ac
Separating walks.
calvertdw Oct 2, 2024
e892574
Load stats after writing them.
calvertdw Oct 2, 2024
a239614
Fix stop processing.
calvertdw Oct 2, 2024
7ebaf44
Add process all button.
calvertdw Oct 2, 2024
d92fc09
Print and layout.
calvertdw Oct 4, 2024
fc01d71
Fix up SVG rendering.
calvertdw Oct 4, 2024
de43689
Improve plot visuals and plot ICP
calvertdw Oct 4, 2024
64fb417
Add arm joint positions.
calvertdw Oct 7, 2024
2e476dd
Adding joint tracker.
calvertdw Oct 7, 2024
35d0d0b
Sort log directories.
calvertdw Oct 7, 2024
0dc4ca2
Add legend.
calvertdw Oct 7, 2024
da2dd2a
Extract overhead SVG plot.
calvertdw Oct 7, 2024
df137ea
Homogenize naming.
calvertdw Oct 7, 2024
cd06826
Add matplotlib4j
calvertdw Oct 7, 2024
b109c70
Add times, save CSV pelvis poses, fix process all bug.
calvertdw Oct 8, 2024
d99f0d5
Draw footstep indexes.
calvertdw Oct 9, 2024
a7505d3
Work on extracting pelvis progress w.r.t. door frame.
calvertdw Oct 9, 2024
6a00626
Finish up on door progress plots.
calvertdw Oct 9, 2024
6b4faf5
Gather hand frames.
calvertdw Oct 12, 2024
8701c1d
Record hand poses to CSV.
calvertdw Oct 13, 2024
7031cd2
Plot hand data.
calvertdw Oct 13, 2024
36a1696
Drawing behavior tree to SVG.
calvertdw Oct 13, 2024
380ce07
Drawing behavior trees to SVG.
calvertdw Oct 13, 2024
623ba77
Drawing action sequence SVG.
calvertdw Oct 14, 2024
1ae7621
Lay out the concurrency.
calvertdw Oct 14, 2024
c7e12d6
Cascade the sequence.
calvertdw Oct 14, 2024
9698a63
A few edits of SVG stuff.
calvertdw Oct 15, 2024
b036c32
Restructuring SVG to prepare to draw it differently.
calvertdw Oct 25, 2024
8a2eabf
Add node depth method.
calvertdw Oct 25, 2024
7f61da7
Add code before removing commented code.
calvertdw Oct 25, 2024
5c50b7f
Tool to get child index.
calvertdw Oct 25, 2024
db15dcb
Building figures that fit in paper.
calvertdw Oct 25, 2024
4822db1
Start adding timeline of concurrent actions.
calvertdw Oct 25, 2024
63ee0e0
Code for not drawing the boxes.
calvertdw Oct 25, 2024
2b8cf65
Calculate RMS for ICP X, Y error.
calvertdw Jan 14, 2025
3aaca66
Remove unused imports.
calvertdw Jan 15, 2025
1e618af
Prevent no hand error. Setting up for plotting step timings, ICP error.
calvertdw Jan 17, 2025
148b78c
Fix writing to CSV for new log.
calvertdw Jan 18, 2025
1e255d6
Write foot state changes to CSV.
calvertdw Jan 19, 2025
af77671
Plot step states.
calvertdw Jan 19, 2025
c124478
Aggregate foot swing durations.
calvertdw Jan 20, 2025
a76ca07
Plot swing durations over time.
calvertdw Jan 23, 2025
f324173
Plot double support durations.
calvertdw Jan 23, 2025
9356efd
Plotting swing & transfer desireds and combining them into one plot.
calvertdw Jan 23, 2025
b997e9c
Plot ICP error.
calvertdw Jan 24, 2025
0b92d13
Add documentation.
calvertdw Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ihmc-avatar-interfaces/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ mainDependencies {
api("com.martiansoftware:jsap:2.1")
api("org.apache.poi:poi:3.15") // I/O library for xls files.
api("com.hierynomus:sshj:0.32.0")
api("org.jfree:org.jfree.svg:5.0.6")
api("com.github.sh0nk:matplotlib4j:0.5.0")

api("us.ihmc:mecano-graphviz:17-0.18.1")
api("us.ihmc:scs2-bullet-simulation:17-0.28.3")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package us.ihmc.avatar.logProcessor;

import gnu.trove.list.array.TDoubleArrayList;
import us.ihmc.log.LogTools;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

/**
* Used as a scratchpad to calculate RMS error data for papers.
*/
public class LogCSVProcessor
{
private final String LOG_PATH = Paths.get(System.getProperty("log.path")).toString();

public LogCSVProcessor()
{
Path filePath = Paths.get(LOG_PATH);

List<String> fileContents;
try
{
fileContents = Files.readAllLines(filePath, StandardCharsets.UTF_8);
}
catch (IOException e)
{
throw new RuntimeException();
}

fileContents.remove(0); // Remove header

TDoubleArrayList controllerICPErrorXs = new TDoubleArrayList();
TDoubleArrayList controllerICPErrorYs = new TDoubleArrayList();

for (String line : fileContents)
{
String[] splitLine = line.split(",");
controllerICPErrorXs.add(Double.parseDouble(splitLine[0]));
controllerICPErrorYs.add(Double.parseDouble(splitLine[1]));
}

LogTools.info("RMS controllerICPErrorXs: {}", calculateRMS(controllerICPErrorXs));
LogTools.info("RMS controllerICPErrorYs: {}", calculateRMS(controllerICPErrorYs));
}

public double calculateRMS(TDoubleArrayList values)
{
double sum = 0.0;
for (int i = 0; i < values.size(); i++)
{
double value = values.get(i);
sum += value * value;
}
double averageSquare = sum / values.size();
return Math.sqrt(averageSquare);
}

public static void main(String[] args)
{
new LogCSVProcessor();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package us.ihmc.avatar.logProcessor;

import us.ihmc.yoVariables.variable.YoEnum;

/** Used to process YoEnum changes for data post-processing. */
public class SCS2LogEnum<E extends Enum<E>>
{
private final YoEnum<?> yoEnum;
private final Class<E> enumType;
private E lastValue = null;

public SCS2LogEnum(YoEnum<?> yoEnum, Class<E> enumType)
{
this.yoEnum = yoEnum;
this.enumType = enumType;
}

public E getValue()
{
for (E enumConstant : enumType.getEnumConstants())
{
if (yoEnum.getStringValue().equals(enumConstant.name()))
{
return enumConstant;
}
}

return null;
}

public boolean changed()
{
return lastValue != getValue();
}

public boolean changedFrom(E fromValue)
{
return lastValue == fromValue && getValue() != fromValue;
}

public boolean changedTo(E toValue)
{
return getValue() == toValue && lastValue != toValue;
}

public void postUpdate()
{
E currentValue = getValue();
lastValue = currentValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package us.ihmc.avatar.logProcessor;

import us.ihmc.commonWalkingControlModules.controlModules.foot.FootControlModule.ConstraintType;
import us.ihmc.commons.thread.TypedNotification;
import us.ihmc.euclid.tuple2D.Point2D;
import us.ihmc.log.LogTools;
import us.ihmc.robotics.robotSide.RobotSide;
import us.ihmc.yoVariables.registry.YoRegistry;
import us.ihmc.yoVariables.variable.YoVariable;

import java.util.ArrayList;

/** Data holder for YoVariable information relating to foot state for data post-processing. */
public class SCS2LogFootState
{
private final RobotSide side;
private final SCS2LogEnum<ConstraintType> yoFootState;
private boolean newStep = false;
private double fullSupportTime = Double.NaN;
private final YoVariable footPolygon_0_x;
private final YoVariable footPolygon_0_y;
private final YoVariable footPolygon_1_x;
private final YoVariable footPolygon_1_y;
private final YoVariable footPolygon_2_x;
private final YoVariable footPolygon_2_y;
private final YoVariable footPolygon_3_x;
private final YoVariable footPolygon_3_y;
private final ArrayList<SCS2LogFootstep> footsteps = new ArrayList<>();
private final TypedNotification<ConstraintType> stateChanged = new TypedNotification<>();
private final double comPlotProximityToFootsteps = 5.0;
private double timeStartedSwing = Double.NaN;
private final TypedNotification<Double> swingCompleted = new TypedNotification<>();

public SCS2LogFootState(RobotSide side, SCS2LogEnum<ConstraintType> yoFootState, YoRegistry rootRegistry)
{
this.side = side;
this.yoFootState = yoFootState;

String highLevelController = "root.main.DRCControllerThread.DRCMomentumBasedController.HumanoidHighLevelControllerManager.";
String footPolygonPrefix = highLevelController + "HighLevelHumanoidControllerToolbox.BipedSupportPolygons.";
footPolygon_0_x = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_0_x".formatted(side.getLowerCaseName()));
footPolygon_0_y = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_0_y".formatted(side.getLowerCaseName()));
footPolygon_1_x = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_1_x".formatted(side.getLowerCaseName()));
footPolygon_1_y = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_1_y".formatted(side.getLowerCaseName()));
footPolygon_2_x = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_2_x".formatted(side.getLowerCaseName()));
footPolygon_2_y = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_2_y".formatted(side.getLowerCaseName()));
footPolygon_3_x = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_3_x".formatted(side.getLowerCaseName()));
footPolygon_3_y = rootRegistry.findVariable(footPolygonPrefix + "%sFootPolygon_3_y".formatted(side.getLowerCaseName()));
}

public void afterRead(double currentTime)
{
if (yoFootState.changed())
{
stateChanged.set(yoFootState.getValue());
}
if (yoFootState.changedTo(ConstraintType.FULL))
{
newStep = true;
fullSupportTime = currentTime;
}
if (yoFootState.changedTo(ConstraintType.SWING))
{
timeStartedSwing = currentTime;
}
if (yoFootState.changedFrom(ConstraintType.SWING))
{
double swingDuration = currentTime - timeStartedSwing;
swingCompleted.set(swingDuration);
}
yoFootState.postUpdate();

if (newStep && currentTime - fullSupportTime > 0.1)
{
LogTools.info("%s step at %s".formatted(side.getPascalCaseName(), new Point2D(footPolygon_0_x.getValueAsDouble(), footPolygon_0_y.getValueAsDouble())));
footsteps.add(new SCS2LogFootstep(currentTime, side, new double[] {footPolygon_0_x.getValueAsDouble(),
footPolygon_1_x.getValueAsDouble(),
footPolygon_2_x.getValueAsDouble(),
footPolygon_3_x.getValueAsDouble(),
footPolygon_0_y.getValueAsDouble(),
footPolygon_1_y.getValueAsDouble(),
footPolygon_2_y.getValueAsDouble(),
footPolygon_3_y.getValueAsDouble()}));
newStep = false;
}
}

public RobotSide getSide()
{
return side;
}

public ArrayList<SCS2LogFootstep> getFootsteps()
{
return footsteps;
}

public TypedNotification<ConstraintType> getStateChanged()
{
return stateChanged;
}

public TypedNotification<Double> getSwingCompleted()
{
return swingCompleted;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package us.ihmc.avatar.logProcessor;

import us.ihmc.robotics.robotSide.RobotSide;

/** Holder for foostep data for post-processing. */
public class SCS2LogFootstep
{
private final double time;
private final RobotSide side;
private final double[] polygon;

public SCS2LogFootstep(double time, RobotSide side, double[] polygon)
{
this.time = time;
this.side = side;
this.polygon = polygon.clone();
}

public double getTime()
{
return time;
}

public RobotSide getSide()
{
return side;
}

public double[] getPolygon()
{
return polygon;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package us.ihmc.avatar.logProcessor;

import us.ihmc.yoVariables.variable.YoDouble;

/** Work in progress, will likely be needed for future manipulation publications. For log data post-processing. */
public class SCS2LogJointTracker
{
private final YoDouble jointPosition;

public SCS2LogJointTracker(YoDouble jointPosition)
{
this.jointPosition = jointPosition;
}

public void update()
{

}
}
Loading
Loading