Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
2ad93b2
Fixed filename loading issues on the MCAPLogFileReader
PotatoPeeler3000 Jul 6, 2026
75c2f5a
Fix naming convention issues when trying to open an MCAP log
PotatoPeeler3000 Jul 6, 2026
38e41f5
Fixes a few bugs with the joint data not updating because of the stan…
PotatoPeeler3000 Jul 7, 2026
d65f9de
Tests and MCAPOdometryManager for reading in all the messages from an…
PotatoPeeler3000 Jul 7, 2026
9cc145c
Merge branch 'develop' into feature/loading-mcap
PotatoPeeler3000 Jul 9, 2026
f504a07
Add support for static fields with enums, message types that are part…
PotatoPeeler3000 Jul 9, 2026
bb64ac4
Update LZ4Frame encoding and decoming to use native libraries.
PotatoPeeler3000 Jul 12, 2026
a682fb0
Updated tests to reflect the newest LZ4 library included. Added comme…
PotatoPeeler3000 Jul 12, 2026
7542b84
Got the ROS2SchemaParser working with a robot log, better check for e…
PotatoPeeler3000 Jul 12, 2026
c8165e7
Replaced Java Concurrency code with this section from Java Concurrenc…
PotatoPeeler3000 Jul 12, 2026
7051ad8
Changed to use jros2 where I can for the ROS2SchemaParser
PotatoPeeler3000 Jul 13, 2026
41ddf71
Default to use BuiltinTools from jros2 to do some of the behavior
PotatoPeeler3000 Jul 13, 2026
9dcd530
Added support for protobuf for mcap files. Added many tests to cover …
PotatoPeeler3000 Jul 20, 2026
8e1c7e5
Merge branch 'develop' into feature/loading-mcap
PotatoPeeler3000 Jul 25, 2026
2bc8d8e
Keep generate formatting available
PotatoPeeler3000 Jul 25, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.net.URISyntaxException;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
Expand Down Expand Up @@ -262,6 +263,31 @@ public static String tryToConvertToPath(String filename, Collection<String> reso
return tryToConvertToPath(filename, resourceDirectories, resourceClassLoader);
}
}

// Last resort: the on-disk resource layout may not mirror the package structure declared in the URI
// (e.g. a flattened asset bundle). Progressively strip leading path segments and look for the
// remaining suffix under each resource directory, preferring the longest (most specific) match.
String[] pathSegments = Arrays.stream(uri.getPath().split("/")).filter(segment -> !segment.isEmpty()).toArray(String[]::new);

for (int start = 0; start < pathSegments.length; start++)
{
String suffix = String.join(File.separator, Arrays.copyOfRange(pathSegments, start, pathSegments.length));

for (String resourceDirectory : resourceDirectories)
{
String fullname = resourceDirectory + File.separator + suffix;
// Path relative to class root
if (resourceClassLoader.getResource(fullname) != null)
{
return fullname;
}
// Absolute path
if (new File(fullname).exists())
{
return fullname;
}
}
}
}
catch (URISyntaxException e)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package us.ihmc.scs2.definition.robot.sdf;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

/**
* Covers {@link SDFTools#tryToConvertToPath}'s last-resort fallback: every earlier strategy in that method assumes
* the on-disk resource layout mirrors the {@code package://} URI's own path structure (e.g. a resource directory
* containing a matching {@code robot_description/robots/.../assets/...} tree). The fallback drops that assumption -
* it strips leading path segments off the URI one at a time and looks for the shrinking suffix directly under each
* resource directory - so a mesh still resolves even when the on-disk bundle has been flattened relative to the
* package path declared in the URDF (as happens with some downloaded log bundles).
* <p>
* Both tests use JUnit's {@code @TempDir} to fabricate a throwaway directory + a 1-byte placeholder file at test
* time (not checked into source, deleted automatically afterward) - nothing here depends on any real robot's mesh
* files or on-disk layout.
* </p>
*/
public class SDFToolsTest
{
/**
* {@code tempDir} holds only {@code assets/merged/test.stl} - no {@code robot_description/robots/version/urdf/}
* tree at all - while the requested URI is the full {@code package://robot_description/robots/version/urdf/
* assets/merged/test.stl}. Every earlier resolution strategy in {@code tryToConvertToPath} would fail to find
* this (the on-disk layout doesn't match the URI's path), so a successful result here specifically exercises the
* suffix-stripping fallback - and its "prefer the longest/most-specific matching suffix" behavior, since
* {@code assets/merged/test.stl} is the first (most specific) suffix that happens to exist under {@code tempDir}.
*/
@Test
public void testTryToConvertToPathWithFlattenedResourceLayout(@TempDir File tempDir) throws IOException
{
// Simulates an on-disk resource bundle that has been flattened relative to the ROS package structure
// declared by the package:// URI, e.g. a downloaded log bundle with "assets/merged/*.stl" directly
// alongside the URDF, instead of the full "robot_description/robots/version/urdf/assets/merged/" tree.
File assetsDir = new File(tempDir, "assets/merged");
assertEquals(true, assetsDir.mkdirs());
File meshFile = new File(assetsDir, "test.stl");
Files.write(meshFile.toPath(), new byte[] {0});

String filename = "package://robot_description/robots/version/urdf/assets/merged/test.stl";
List<String> resourceDirectories = new ArrayList<>(Collections.singletonList(tempDir.getAbsolutePath()));

String result = SDFTools.tryToConvertToPath(filename, resourceDirectories, getClass().getClassLoader());

assertEquals(meshFile.getAbsolutePath(), result);
}

/**
* {@code tempDir} is empty this time - no file exists under any suffix of the requested URI, at any strip
* length, down to just the bare filename. The fallback (and every strategy before it) must give up gracefully
* and return {@code null} rather than throwing, so callers can report "mesh not found" instead of crashing.
*/
@Test
public void testTryToConvertToPathReturnsNullWhenUnresolvable(@TempDir File tempDir)
{
String filename = "package://robot_description/robots/version/urdf/assets/merged/does_not_exist.stl";
List<String> resourceDirectories = new ArrayList<>(Collections.singletonList(tempDir.getAbsolutePath()));

String result = SDFTools.tryToConvertToPath(filename, resourceDirectories, getClass().getClassLoader());

assertNull(result);
}
}
13 changes: 12 additions & 1 deletion scs2-session-logger/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,20 @@ mainDependencies {
api("us.ihmc:scs2-simulation:source") // TODO Need to fix this, it needs the Robot.

api("us.ihmc:ihmc-robot-data-logger:0.39.1")
api("com.github.luben:zstd-jni:1.5.5-10")
api("us.ihmc:jros2-parser:1.4.0")
api("org.antlr:antlr4-runtime:4.13.1")
api("com.github.vatbub:mslinks:1.0.6.2")
api("com.google.protobuf:protobuf-java:4.34.2")
// Not using org.bytedeco:lz4-platform: it pulls in javacpp-platform, whose fixed javacpp:1.5.8
// classifier list (incl. android-arm/x86, linux-armhf, linux/windows-x86 32-bit) gets bumped to

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added lz4 strictly for mcap decoding

// 1.5.11 by other native deps in this build (cuda/ffmpeg/openblas/opencv from ihmc-robot-data-logger),
// and those obsolete 32-bit/Android classifiers were dropped at 1.5.11, breaking resolution.
// Depending on the plain lz4 module plus only the native classifiers we actually avoid that.
api("org.bytedeco:lz4:1.9.4-1.5.8")
api("org.bytedeco:lz4:1.9.4-1.5.8:linux-x86_64")
api("org.bytedeco:lz4:1.9.4-1.5.8:macosx-x86_64")
api("org.bytedeco:lz4:1.9.4-1.5.8:macosx-arm64")
api("org.bytedeco:lz4:1.9.4-1.5.8:windows-x86_64")
}

testDependencies {
Expand Down
Loading
Loading