us.ihmc.scs2.definition.robot.sdf.SDFTools Maven / Gradle / Ivy
package us.ihmc.scs2.definition.robot.sdf;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import us.ihmc.euclid.Axis3D;
import us.ihmc.euclid.matrix.Matrix3D;
import us.ihmc.euclid.tools.EuclidCoreIOTools;
import us.ihmc.euclid.transform.RigidBodyTransform;
import us.ihmc.euclid.tuple3D.Vector3D;
import us.ihmc.euclid.tuple3D.interfaces.Vector3DReadOnly;
import us.ihmc.euclid.yawPitchRoll.YawPitchRoll;
import us.ihmc.log.LogTools;
import us.ihmc.scs2.definition.AffineTransformDefinition;
import us.ihmc.scs2.definition.YawPitchRollTransformDefinition;
import us.ihmc.scs2.definition.collision.CollisionShapeDefinition;
import us.ihmc.scs2.definition.geometry.Box3DDefinition;
import us.ihmc.scs2.definition.geometry.Cylinder3DDefinition;
import us.ihmc.scs2.definition.geometry.GeometryDefinition;
import us.ihmc.scs2.definition.geometry.ModelFileGeometryDefinition;
import us.ihmc.scs2.definition.geometry.Sphere3DDefinition;
import us.ihmc.scs2.definition.robot.CameraSensorDefinition;
import us.ihmc.scs2.definition.robot.FixedJointDefinition;
import us.ihmc.scs2.definition.robot.IMUSensorDefinition;
import us.ihmc.scs2.definition.robot.JointDefinition;
import us.ihmc.scs2.definition.robot.LidarSensorDefinition;
import us.ihmc.scs2.definition.robot.OneDoFJointDefinition;
import us.ihmc.scs2.definition.robot.PlanarJointDefinition;
import us.ihmc.scs2.definition.robot.PrismaticJointDefinition;
import us.ihmc.scs2.definition.robot.RevoluteJointDefinition;
import us.ihmc.scs2.definition.robot.RigidBodyDefinition;
import us.ihmc.scs2.definition.robot.RobotDefinition;
import us.ihmc.scs2.definition.robot.SensorDefinition;
import us.ihmc.scs2.definition.robot.SixDoFJointDefinition;
import us.ihmc.scs2.definition.robot.sdf.items.SDFCollision;
import us.ihmc.scs2.definition.robot.sdf.items.SDFGeometry;
import us.ihmc.scs2.definition.robot.sdf.items.SDFInertia;
import us.ihmc.scs2.definition.robot.sdf.items.SDFJoint;
import us.ihmc.scs2.definition.robot.sdf.items.SDFJoint.SDFAxis;
import us.ihmc.scs2.definition.robot.sdf.items.SDFJoint.SDFAxis.SDFDynamics;
import us.ihmc.scs2.definition.robot.sdf.items.SDFJoint.SDFAxis.SDFLimit;
import us.ihmc.scs2.definition.robot.sdf.items.SDFLink;
import us.ihmc.scs2.definition.robot.sdf.items.SDFLink.SDFInertial;
import us.ihmc.scs2.definition.robot.sdf.items.SDFModel;
import us.ihmc.scs2.definition.robot.sdf.items.SDFRoot;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFCamera;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFIMU;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFIMU.SDFIMUNoise;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFIMU.SDFIMUNoise.SDFNoiseParameters;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFRay;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFRay.SDFNoise;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFRay.SDFRange;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFRay.SDFScan.SDFHorizontalScan;
import us.ihmc.scs2.definition.robot.sdf.items.SDFSensor.SDFRay.SDFScan.SDFVerticalScan;
import us.ihmc.scs2.definition.robot.sdf.items.SDFURIHolder;
import us.ihmc.scs2.definition.robot.sdf.items.SDFVisual;
import us.ihmc.scs2.definition.robot.sdf.items.SDFVisual.SDFMaterial;
import us.ihmc.scs2.definition.visual.ColorDefinition;
import us.ihmc.scs2.definition.visual.ColorDefinitions;
import us.ihmc.scs2.definition.visual.MaterialDefinition;
import us.ihmc.scs2.definition.visual.VisualDefinition;
public class SDFTools
{
public static final String SDF_DEFAULT_KEYWORD = "__default__";
private static final double DEFAULT_MASS = 0.0;
private static final double DEFAULT_IXX = 0.0;
private static final double DEFAULT_IYY = 0.0;
private static final double DEFAULT_IZZ = 0.0;
private static final double DEFAULT_IXY = 0.0;
private static final double DEFAULT_IXZ = 0.0;
private static final double DEFAULT_IYZ = 0.0;
private static final Vector3DReadOnly DEFAULT_AXIS = new Vector3D(1.0, 0.0, 0.0);
private static final double DEFAULT_LOWER_LIMIT = Double.NEGATIVE_INFINITY;
private static final double DEFAULT_UPPER_LIMIT = Double.POSITIVE_INFINITY;
private static final double DEFAULT_EFFORT_LIMIT = Double.POSITIVE_INFINITY;
private static final double DEFAULT_VELOCITY_LIMIT = Double.POSITIVE_INFINITY;
public static SDFRoot loadSDFRoot(File sdfFile) throws JAXBException
{
return loadSDFRoot(sdfFile, Collections.emptyList());
}
public static SDFRoot loadSDFRoot(File sdfFile, Collection resourceDirectories) throws JAXBException
{
Set allResourceDirectories = new HashSet<>(resourceDirectories);
File parentFile = sdfFile.getParentFile();
if (parentFile != null)
{
allResourceDirectories.add(parentFile.getAbsolutePath() + File.separator);
Stream.of(parentFile.listFiles(File::isDirectory)).map(file -> file.getAbsolutePath() + File.separator).forEach(allResourceDirectories::add);
}
JAXBContext context = JAXBContext.newInstance(SDFRoot.class);
Unmarshaller um = context.createUnmarshaller();
SDFRoot sdfRoot = (SDFRoot) um.unmarshal(sdfFile);
ensureListsNotNull(sdfRoot);
resolvePaths(sdfRoot, allResourceDirectories);
return sdfRoot;
}
public static SDFRoot loadSDFRoot(InputStream inputStream, Collection resourceDirectories, ClassLoader resourceClassLoader) throws JAXBException
{
Set allResourceDirectories = new HashSet<>(resourceDirectories);
JAXBContext context = JAXBContext.newInstance(SDFRoot.class);
Unmarshaller um = context.createUnmarshaller();
SDFRoot sdfRoot = (SDFRoot) um.unmarshal(inputStream);
ensureListsNotNull(sdfRoot);
resolvePaths(sdfRoot, allResourceDirectories, resourceClassLoader);
return sdfRoot;
}
/**
* Otherwise, iteration later on will result in NullPointerException if there are none of something.
*/
public static void ensureListsNotNull(SDFRoot sdfRoot)
{
if (sdfRoot.getModels() == null)
sdfRoot.setModels(new ArrayList<>());
for (SDFModel model : sdfRoot.getModels())
{
if (model.getLinks() == null)
model.setLinks(new ArrayList<>());
if (model.getJoints() == null)
model.setJoints(new ArrayList<>());
}
}
public static void resolvePaths(SDFRoot sdfRoot, Collection resourceDirectories)
{
resolvePaths(sdfRoot, resourceDirectories, null);
}
public static void resolvePaths(SDFRoot sdfRoot, Collection resourceDirectories, ClassLoader resourceClassLoader)
{
if (resourceClassLoader == null)
resourceClassLoader = SDFTools.class.getClassLoader();
List uriHolders = sdfRoot.getURIHolders();
for (SDFURIHolder sdfURIHolder : uriHolders)
{
sdfURIHolder.setUri(tryToConvertToPath(sdfURIHolder.getUri(), resourceDirectories, resourceClassLoader));
}
}
/**
* Attempts to locate the file corresponding to the given {@code filename} considering the paths of
* the resource directories and the class loader.
*
* When the file is located, a {@code fullname} is computed and returned such that the file can be
* later retrieved by using {@code resourceClassLoader.getResource(fullname)} or
* {@code new File(fullname)}.
*
*
* @param filename the name of the file to computed the fullname of.
* @param resourceDirectories the directories the file could be located in.
* @param resourceClassLoader the class loader is used to retrieve the resources. If the resources
* are located in the class path, e.g. in the resources folder,
* simply use {@code CallerClass.getClassLoader()}. If the resources are
* located outside the scope of the class path, see
* {@link URLClassLoader} that allows to point to a directory among
* other options.
* @return the fullname which can be used to open the file using
* {@code resourceClassLoader.getResource(fullname)} or {@code new File(fullname)}.
*/
public static String tryToConvertToPath(String filename, Collection resourceDirectories, ClassLoader resourceClassLoader)
{
try
{
URI uri = new URI(filename);
String authority = uri.getAuthority() == null ? "" : uri.getAuthority();
{ // Try to load without using the resource directories
String fullname = authority + uri.getPath();
// Path relative to class root
if (resourceClassLoader.getResource(fullname) != null)
{
return fullname;
}
// Absolute path
if (new File(fullname).exists())
{
return fullname;
}
}
for (String resourceDirectory : resourceDirectories)
{
String fullname = resourceDirectory + authority + uri.getPath();
// Path relative to class root
if (resourceClassLoader.getResource(fullname) != null)
{
return fullname;
}
// Absolute path
if (new File(fullname).exists())
{
return fullname;
}
fullname = resourceDirectory + File.separator + authority + uri.getPath();
// Path relative to class root
if (resourceClassLoader.getResource(fullname) != null)
{
return fullname;
}
// Absolute path
if (new File(fullname).exists())
{
return fullname;
}
}
// Let's look in the parent directories of the resources if we can find a match to authority
String resourceContainingAuthority = null;
for (String resourceDirectory : resourceDirectories)
{
if (resourceDirectory.contains(authority))
{
resourceContainingAuthority = resourceDirectory;
break;
}
}
if (resourceContainingAuthority != null)
{
int lastIndexOf = resourceContainingAuthority.lastIndexOf(authority, resourceContainingAuthority.length());
String newResource = resourceContainingAuthority.substring(0, lastIndexOf);
if (!resourceDirectories.contains(newResource))
{
resourceDirectories.add(newResource);
return tryToConvertToPath(filename, resourceDirectories, resourceClassLoader);
}
}
}
catch (URISyntaxException e)
{
System.err.println(SDFTools.class.getSimpleName() + ": Malformed resource path in SDF file for path: " + filename);
}
System.err.println(SDFTools.class.getSimpleName() + ": Unable to resolve the path: " + filename);
return null;
}
public static RobotDefinition toFloatingRobotDefinition(SDFRoot sdfRoot, String modelName)
{
return toFloatingRobotDefinition(sdfRoot.getModels().stream().filter(model -> model.getName().equals(modelName)).findFirst().get());
}
public static RobotDefinition toFloatingRobotDefinition(SDFModel sdfModel)
{
return toRobotDefinition(new SixDoFJointDefinition(), sdfModel);
}
public static RobotDefinition toRobotDefinition(JointDefinition rootJointDefinition, SDFRoot sdfRoot, String modelName)
{
return toRobotDefinition(rootJointDefinition, sdfRoot.getModels().stream().filter(model -> model.getName().equals(modelName)).findFirst().get());
}
public static RobotDefinition toRobotDefinition(JointDefinition rootJointDefinition, SDFModel sdfModel)
{
List sdfLinks = sdfModel.getLinks();
List sdfJoints = sdfModel.getJoints();
List rigidBodyDefinitions = sdfLinks.stream().map(SDFTools::toRigidBodyDefinition).collect(Collectors.toList());
List jointDefinitions;
if (sdfJoints == null)
jointDefinitions = Collections.emptyList();
else
jointDefinitions = sdfJoints.stream().map(SDFTools::toJointDefinition).collect(Collectors.toList());
RigidBodyDefinition startBodyDefinition = connectKinematics(rigidBodyDefinitions, jointDefinitions, sdfJoints, sdfLinks);
if (rootJointDefinition.getName() == null)
rootJointDefinition.setName(startBodyDefinition.getName());
rootJointDefinition.setSuccessor(startBodyDefinition);
RigidBodyDefinition rootBodyDefinition = new RigidBodyDefinition("rootBody");
rootBodyDefinition.addChildJoint(rootJointDefinition);
addSensors(sdfLinks, rigidBodyDefinitions);
correctTransforms(sdfJoints, sdfLinks, jointDefinitions);
RobotDefinition robotDefinition = new RobotDefinition(sdfModel.getName());
robotDefinition.setRootBodyDefinition(rootBodyDefinition);
return robotDefinition;
}
public static RigidBodyDefinition connectKinematics(List rigidBodyDefinitions,
List jointDefinitions,
List sdfJoints,
List sdfLinks)
{
if (sdfJoints == null)
return rigidBodyDefinitions.get(0);
Map rigidBodyDefinitionMap = rigidBodyDefinitions.stream()
.collect(Collectors.toMap(RigidBodyDefinition::getName,
Function.identity()));
Map jointDefinitionMap = jointDefinitions.stream().collect(Collectors.toMap(JointDefinition::getName, Function.identity()));
for (SDFJoint sdfJoint : sdfJoints)
{
String parent = sdfJoint.getParent();
String child = sdfJoint.getChild();
RigidBodyDefinition parentRigidBodyDefinition = rigidBodyDefinitionMap.get(parent);
RigidBodyDefinition childRigidBodyDefinition = rigidBodyDefinitionMap.get(child);
JointDefinition jointDefinition = jointDefinitionMap.get(sdfJoint.getName());
jointDefinition.setSuccessor(childRigidBodyDefinition);
parentRigidBodyDefinition.addChildJoint(jointDefinition);
}
RigidBodyDefinition rootBody = rigidBodyDefinitions.get(0);
if (!jointDefinitions.isEmpty())
{
rootBody = jointDefinitions.get(0).getPredecessor();
while (rootBody.getParentJoint() != null)
rootBody = rootBody.getParentJoint().getPredecessor();
}
return rootBody;
}
public static void addSensors(List sdfLinks, List rigidBodyDefinitions)
{
Map rigidBodyDefinitionMap = rigidBodyDefinitions.stream()
.collect(Collectors.toMap(RigidBodyDefinition::getName,
Function.identity()));
for (SDFLink sdfLink : sdfLinks)
{
if (sdfLink.getSensors() == null)
continue;
RigidBodyDefinition rigidBodyDefinition = rigidBodyDefinitionMap.get(sdfLink.getName());
JointDefinition parentJoint = rigidBodyDefinition.getParentJoint();
for (SDFSensor sdfSensor : sdfLink.getSensors())
{
List sensorDefinitions = toSensorDefinition(sdfSensor);
if (sensorDefinitions != null)
sensorDefinitions.forEach(parentJoint::addSensorDefinition);
}
}
}
public static void correctTransforms(List sdfJoints, List sdfLinks, List jointDefinitions)
{
Map sdfLinkMap = sdfLinks.stream().collect(Collectors.toMap(SDFLink::getName, Function.identity()));
Map jointDefinitionMap = jointDefinitions.stream().collect(Collectors.toMap(JointDefinition::getName, Function.identity()));
for (SDFJoint sdfJoint : sdfJoints)
{
String jointName = sdfJoint.getName();
JointDefinition jointDefinition = jointDefinitionMap.get(jointName);
RigidBodyDefinition childDefinition = jointDefinition.getSuccessor();
String parentLinkName = sdfJoint.getParent();
String childLinkName = sdfJoint.getChild();
SDFLink parentSDFLink = sdfLinkMap.get(parentLinkName);
SDFLink childSDFLink = sdfLinkMap.get(childLinkName);
RigidBodyTransform parentLinkPose = parsePose(parentSDFLink.getPose());
RigidBodyTransform childLinkPose = parsePose(childSDFLink.getPose());
// Correct joint transform
YawPitchRollTransformDefinition transformToParentJoint = jointDefinition.getTransformToParent();
transformToParentJoint.setAndInvert(parentLinkPose);
transformToParentJoint.multiply(childLinkPose);
transformToParentJoint.getRotation().setToZero();
parentLinkPose.transform(transformToParentJoint.getTranslation());
// Correct link inertia pose
YawPitchRollTransformDefinition inertiaPose = childDefinition.getInertiaPose();
inertiaPose.prependOrientation(childLinkPose.getRotation());
inertiaPose.transform(childDefinition.getMomentOfInertia());
inertiaPose.getRotation().setToZero();
// Correct visual transform
for (VisualDefinition visualDescription : childDefinition.getVisualDefinitions())
{
AffineTransformDefinition visualPose = visualDescription.getOriginPose();
visualPose.prependOrientation(childLinkPose.getRotation());
}
// Correct collision transform
for (CollisionShapeDefinition collisionShapeDefinition : childDefinition.getCollisionShapeDefinitions())
{
YawPitchRollTransformDefinition originPose = collisionShapeDefinition.getOriginPose();
originPose.prependOrientation(childLinkPose.getRotation());
}
for (SensorDefinition sensorDefinition : jointDefinition.getSensorDefinitions())
{
sensorDefinition.getTransformToJoint().prependOrientation(childLinkPose.getRotation());
}
}
}
public static RigidBodyDefinition toRigidBodyDefinition(SDFLink sdfLink)
{
RigidBodyDefinition definition = new RigidBodyDefinition(sdfLink.getName());
SDFInertial sdfInertial = sdfLink.getInertial();
if (sdfInertial == null)
{
definition.setMass(parseDouble(null, DEFAULT_MASS));
definition.getMomentOfInertia().set(parseMomentOfInertia(null));
definition.getInertiaPose().set(parsePose(null));
}
else
{
definition.setMass(parseDouble(sdfInertial.getMass(), DEFAULT_MASS));
definition.getMomentOfInertia().set(parseMomentOfInertia(sdfInertial.getInertia()));
definition.getInertiaPose().set(parsePose(sdfInertial.getPose()));
}
if (sdfLink.getVisuals() != null)
sdfLink.getVisuals().stream().map(SDFTools::toVisualDefinition).forEach(definition::addVisualDefinition);
if (sdfLink.getCollisions() != null)
sdfLink.getCollisions().stream().map(SDFTools::toCollisionShapeDefinition).forEach(definition::addCollisionShapeDefinition);
return definition;
}
public static JointDefinition toJointDefinition(SDFJoint sdfJoint)
{
switch (sdfJoint.getType())
{
case "continuous":
return toRevoluteJointDefinition(sdfJoint, true);
case "revolute":
return toRevoluteJointDefinition(sdfJoint, false);
case "prismatic":
return toPrismaticJointDefinition(sdfJoint);
case "fixed":
return toFixedJoint(sdfJoint);
case "floating":
return toSixDoFJointDefinition(sdfJoint);
case "planar":
return toPlanarJointDefinition(sdfJoint);
default:
throw new RuntimeException("Unexpected value for the joint type: " + sdfJoint.getType());
}
}
public static RevoluteJointDefinition toRevoluteJointDefinition(SDFJoint sdfJoint, boolean ignorePositionLimits)
{
RevoluteJointDefinition definition = new RevoluteJointDefinition(sdfJoint.getName());
definition.getTransformToParent().set(parsePose(sdfJoint.getPose()));
definition.getAxis().set(parseAxis(sdfJoint.getAxis()));
parseLimit(sdfJoint.getAxis().getLimit(), definition, ignorePositionLimits);
parseDynamics(sdfJoint.getAxis().getDynamics(), definition);
return definition;
}
public static PrismaticJointDefinition toPrismaticJointDefinition(SDFJoint sdfJoint)
{
PrismaticJointDefinition definition = new PrismaticJointDefinition(sdfJoint.getName());
definition.getTransformToParent().set(parsePose(sdfJoint.getPose()));
definition.getAxis().set(parseAxis(sdfJoint.getAxis()));
parseLimit(sdfJoint.getAxis().getLimit(), definition, false);
parseDynamics(sdfJoint.getAxis().getDynamics(), definition);
return definition;
}
public static FixedJointDefinition toFixedJoint(SDFJoint sdfJoint)
{
FixedJointDefinition definition = new FixedJointDefinition(sdfJoint.getName());
RigidBodyTransform parseRigidBodyTransform = parsePose(sdfJoint.getPose());
definition.getTransformToParent().set(parseRigidBodyTransform);
return definition;
}
public static SixDoFJointDefinition toSixDoFJointDefinition(SDFJoint sdfJoint)
{
SixDoFJointDefinition definition = new SixDoFJointDefinition(sdfJoint.getName());
definition.getTransformToParent().set(parsePose(sdfJoint.getPose()));
return definition;
}
public static PlanarJointDefinition toPlanarJointDefinition(SDFJoint sdfJoint)
{
PlanarJointDefinition definition = new PlanarJointDefinition(sdfJoint.getName());
definition.getTransformToParent().set(parsePose(sdfJoint.getPose()));
Vector3D surfaceNormal = parseAxis(sdfJoint.getAxis());
if (!surfaceNormal.geometricallyEquals(Axis3D.Y, 1.0e-5))
throw new UnsupportedOperationException("Planar joint are supported only with a surface normal equal to: "
+ EuclidCoreIOTools.getTuple3DString(Axis3D.Y) + ", received:" + surfaceNormal);
return definition;
}
public static List toSensorDefinition(SDFSensor sdfSensor)
{
List definitions = new ArrayList<>();
switch (sdfSensor.getType())
{
case "camera":
case "multicamera":
case "depth":
definitions.addAll(toCameraSensorDefinition(sdfSensor.getCamera()));
break;
case "imu":
definitions.add(toIMUSensorDefinition(sdfSensor.getImu()));
break;
case "gpu_ray":
case "ray":
definitions.add(toLidarSensorDefinition(sdfSensor.getRay()));
break;
default:
LogTools.error("Unsupport sensor type: " + sdfSensor.getType());
return null;
}
int updatePeriod = sdfSensor.getUpdateRate() == null ? -1 : (int) (1000.0 / parseDouble(sdfSensor.getUpdateRate(), 1000.0));
for (SensorDefinition definition : definitions)
{
if (definition.getName() != null && !definition.getName().isEmpty() && !definition.getName().equals(SDF_DEFAULT_KEYWORD))
definition.setName(sdfSensor.getName() + "_" + definition.getName());
else
definition.setName(sdfSensor.getName());
definition.getTransformToJoint().preMultiply(parsePose(sdfSensor.getPose()));
definition.setUpdatePeriod(updatePeriod);
}
return definitions;
}
public static List toCameraSensorDefinition(List sdfCameras)
{
return sdfCameras.stream().map(SDFTools::toCameraSensorDefinition).collect(Collectors.toList());
}
public static CameraSensorDefinition toCameraSensorDefinition(SDFCamera sdfCamera)
{
CameraSensorDefinition definition = new CameraSensorDefinition();
definition.setName(sdfCamera.getName());
definition.getTransformToJoint().set(parsePose(sdfCamera.getPose()));
definition.setFieldOfView(parseDouble(sdfCamera.getHorizontalFov(), Double.NaN));
definition.setClipNear(parseDouble(sdfCamera.getClip().getNear(), Double.NaN));
definition.setClipFar(parseDouble(sdfCamera.getClip().getFar(), Double.NaN));
definition.setImageWidth(parseInteger(sdfCamera.getImage().getWidth(), -1));
definition.setImageHeight(parseInteger(sdfCamera.getImage().getHeight(), -1));
return definition;
}
public static LidarSensorDefinition toLidarSensorDefinition(SDFRay sdfRay)
{
LidarSensorDefinition definition = new LidarSensorDefinition();
SDFRange sdfRange = sdfRay.getRange();
double sdfRangeMax = parseDouble(sdfRange.getMax(), Double.NaN);
double sdfRangeMin = parseDouble(sdfRange.getMin(), Double.NaN);
double sdfRangeResolution = parseDouble(sdfRange.getResolution(), Double.NaN);
SDFHorizontalScan sdfHorizontalScan = sdfRay.getScan().getHorizontal();
SDFVerticalScan sdfVerticalScan = sdfRay.getScan().getVertical();
double maxSweepAngle = parseDouble(sdfHorizontalScan.getMaxAngle(), 0.0);
double minSweepAngle = parseDouble(sdfHorizontalScan.getMinAngle(), 0.0);
double maxHeightAngle = sdfVerticalScan == null ? 0.0 : parseDouble(sdfVerticalScan.getMaxAngle(), 0.0);
double minHeightAngle = sdfVerticalScan == null ? 0.0 : parseDouble(sdfVerticalScan.getMinAngle(), 0.0);
int samples = parseInteger(sdfHorizontalScan.getSamples(), -1) / 3 * 3;
int scanHeight = sdfVerticalScan == null ? 1 : parseInteger(sdfVerticalScan.getSamples(), 1);
SDFNoise sdfNoise = sdfRay.getNoise();
if (sdfNoise != null)
{
if ("gaussian".equals(sdfNoise.getType()))
{
definition.setGaussianNoiseMean(parseDouble(sdfNoise.getMean(), 0.0));
definition.setGaussianNoiseStandardDeviation(parseDouble(sdfNoise.getStddev(), 0.0));
}
else
{
LogTools.error("Unknown noise model: {}.", sdfNoise.getType());
}
}
definition.getTransformToJoint().set(parsePose(sdfRay.getPose()));
definition.setPointsPerSweep(samples);
definition.setSweepYawLimits(minSweepAngle, maxSweepAngle);
definition.setHeightPitchLimits(minHeightAngle, maxHeightAngle);
definition.setRangeLimits(sdfRangeMin, sdfRangeMax);
definition.setRangeResolution(sdfRangeResolution);
definition.setScanHeight(scanHeight);
return definition;
}
public static IMUSensorDefinition toIMUSensorDefinition(SDFIMU sdfIMU)
{
IMUSensorDefinition definition = new IMUSensorDefinition();
SDFIMUNoise sdfNoise = sdfIMU.getNoise();
if (sdfNoise != null)
{
if ("gaussian".equals(sdfNoise.getType()))
{
SDFNoiseParameters accelerationNoise = sdfNoise.getAccel();
SDFNoiseParameters angularVelocityNoise = sdfNoise.getRate();
definition.setAccelerationNoiseParameters(parseDouble(accelerationNoise.getMean(), 0.0), parseDouble(accelerationNoise.getStddev(), 0.0));
definition.setAccelerationBiasParameters(parseDouble(accelerationNoise.getBias_mean(), 0.0), parseDouble(accelerationNoise.getBias_stddev(), 0.0));
definition.setAngularVelocityNoiseParameters(parseDouble(angularVelocityNoise.getMean(), 0.0), parseDouble(angularVelocityNoise.getStddev(), 0.0));
definition.setAngularVelocityBiasParameters(parseDouble(angularVelocityNoise.getBias_mean(), 0.0),
parseDouble(angularVelocityNoise.getBias_stddev(), 0.0));
}
else
{
LogTools.error("Unknown IMU noise model: {}.", sdfNoise.getType());
}
}
return definition;
}
public static VisualDefinition toVisualDefinition(SDFVisual sdfVisual)
{
if (sdfVisual == null)
return null;
VisualDefinition visualDefinition = new VisualDefinition();
visualDefinition.setName(sdfVisual.getName());
visualDefinition.setOriginPose(parsePose(sdfVisual.getPose()));
visualDefinition.setMaterialDefinition(toMaterialDefinition(sdfVisual.getMaterial()));
visualDefinition.setGeometryDefinition(toGeometryDefinition(sdfVisual.getGeometry()));
return visualDefinition;
}
public static CollisionShapeDefinition toCollisionShapeDefinition(SDFCollision sdfCollision)
{
if (sdfCollision == null)
return null;
CollisionShapeDefinition collisionShapeDefinition = new CollisionShapeDefinition();
collisionShapeDefinition.setName(sdfCollision.getName());
collisionShapeDefinition.setOriginPose(parsePose(sdfCollision.getPose()));
collisionShapeDefinition.setGeometryDefinition(toGeometryDefinition(sdfCollision.getGeometry()));
return collisionShapeDefinition;
}
public static GeometryDefinition toGeometryDefinition(SDFGeometry sdfGeometry)
{
return toGeometryDefinition(sdfGeometry, Collections.emptyList());
}
public static GeometryDefinition toGeometryDefinition(SDFGeometry sdfGeometry, List resourceDirectories)
{
if (sdfGeometry.getBox() != null)
{
Box3DDefinition boxGeometryDefinition = new Box3DDefinition();
boxGeometryDefinition.setSize(parseVector3D(sdfGeometry.getBox().getSize(), null));
return boxGeometryDefinition;
}
if (sdfGeometry.getCylinder() != null)
{
Cylinder3DDefinition cylinderGeometryDefinition = new Cylinder3DDefinition();
cylinderGeometryDefinition.setRadius(parseDouble(sdfGeometry.getCylinder().getRadius(), 0.0));
cylinderGeometryDefinition.setLength(parseDouble(sdfGeometry.getCylinder().getLength(), 0.0));
return cylinderGeometryDefinition;
}
if (sdfGeometry.getSphere() != null)
{
Sphere3DDefinition sphereGeometryDefinition = new Sphere3DDefinition();
sphereGeometryDefinition.setRadius(parseDouble(sdfGeometry.getSphere().getRadius(), 0.0));
return sphereGeometryDefinition;
}
if (sdfGeometry.getMesh() != null)
{
ModelFileGeometryDefinition modelFileGeometryDefinition = new ModelFileGeometryDefinition();
modelFileGeometryDefinition.setResourceDirectories(resourceDirectories);
modelFileGeometryDefinition.setFileName(sdfGeometry.getMesh().getUri());
modelFileGeometryDefinition.setScale(parseVector3D(sdfGeometry.getMesh().getScale(), new Vector3D(1, 1, 1)));
return modelFileGeometryDefinition;
}
throw new IllegalArgumentException("The given SDF Geometry is empty.");
}
public static MaterialDefinition toMaterialDefinition(SDFMaterial sdfMaterial)
{
if (sdfMaterial == null)
return null;
MaterialDefinition materialDefinition = new MaterialDefinition();
materialDefinition.setShininess(parseDouble(sdfMaterial.getLighting(), Double.NaN));
materialDefinition.setAmbientColor(toColorDefinition(sdfMaterial.getAmbient()));
materialDefinition.setDiffuseColor(toColorDefinition(sdfMaterial.getDiffuse()));
materialDefinition.setSpecularColor(toColorDefinition(sdfMaterial.getSpecular()));
materialDefinition.setEmissiveColor(toColorDefinition(sdfMaterial.getEmissive()));
// TODO handle the script
return materialDefinition;
}
public static ColorDefinition toColorDefinition(String sdfColor)
{
if (sdfColor == null)
return null;
double[] colorArray = parseArray(sdfColor, null);
if (colorArray == null)
return null;
else if (colorArray.length < 4)
return ColorDefinitions.rgb(colorArray);
else
return ColorDefinitions.rgba(colorArray);
}
public static RigidBodyTransform parsePose(String pose)
{
RigidBodyTransform rigidBodyTransform = new RigidBodyTransform();
if (pose != null)
{
String[] split = pose.strip().split("\\s+");
Vector3D position = new Vector3D(Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2]));
YawPitchRoll orientation = new YawPitchRoll(Double.parseDouble(split[5]), Double.parseDouble(split[4]), Double.parseDouble(split[3]));
rigidBodyTransform.set(orientation, position);
}
return rigidBodyTransform;
}
public static Matrix3D parseMomentOfInertia(SDFInertia inertia)
{
if (inertia == null)
inertia = new SDFInertia();
Matrix3D momentOfInertia = new Matrix3D();
double ixx = parseDouble(inertia.getIxx(), DEFAULT_IXX);
double iyy = parseDouble(inertia.getIyy(), DEFAULT_IYY);
double izz = parseDouble(inertia.getIzz(), DEFAULT_IZZ);
double ixy = parseDouble(inertia.getIxy(), DEFAULT_IXY);
double ixz = parseDouble(inertia.getIxz(), DEFAULT_IXZ);
double iyz = parseDouble(inertia.getIyz(), DEFAULT_IYZ);
momentOfInertia.setM00(ixx);
momentOfInertia.setM11(iyy);
momentOfInertia.setM22(izz);
momentOfInertia.setM01(ixy);
momentOfInertia.setM02(ixz);
momentOfInertia.setM12(iyz);
momentOfInertia.setM10(ixy);
momentOfInertia.setM20(ixz);
momentOfInertia.setM21(iyz);
return momentOfInertia;
}
public static void parseLimit(SDFLimit sdfLimit, OneDoFJointDefinition jointDefinitionToParseLimitInto, boolean ignorePositionLimits)
{
jointDefinitionToParseLimitInto.setPositionLimits(DEFAULT_LOWER_LIMIT, DEFAULT_UPPER_LIMIT);
jointDefinitionToParseLimitInto.setEffortLimits(DEFAULT_EFFORT_LIMIT);
jointDefinitionToParseLimitInto.setVelocityLimits(DEFAULT_VELOCITY_LIMIT);
if (sdfLimit != null)
{
if (!ignorePositionLimits)
{
double positionLowerLimit = parseDouble(sdfLimit.getLower(), DEFAULT_LOWER_LIMIT);
double positionUpperLimit = parseDouble(sdfLimit.getUpper(), DEFAULT_UPPER_LIMIT);
if (positionLowerLimit < positionUpperLimit)
jointDefinitionToParseLimitInto.setPositionLimits(positionLowerLimit, positionUpperLimit);
}
double effortLimit = parseDouble(sdfLimit.getEffort(), DEFAULT_EFFORT_LIMIT);
if (Double.isFinite(effortLimit) && effortLimit >= 0)
jointDefinitionToParseLimitInto.setEffortLimits(effortLimit);
double velocityLimit = parseDouble(sdfLimit.getVelocity(), DEFAULT_VELOCITY_LIMIT);
if (Double.isFinite(velocityLimit) && velocityLimit >= 0)
jointDefinitionToParseLimitInto.setVelocityLimits(velocityLimit);
}
}
public static void parseDynamics(SDFDynamics sdfDynamics, OneDoFJointDefinition jointDefinitionToParseDynamicsInto)
{
double damping = 0.0;
double stiction = 0.0;
if (sdfDynamics != null)
{
damping = parseDouble(sdfDynamics.getDamping(), 0.0);
stiction = parseDouble(sdfDynamics.getFriction(), 0.0);
}
jointDefinitionToParseDynamicsInto.setDamping(damping);
jointDefinitionToParseDynamicsInto.setStiction(stiction);
}
public static Vector3D parseAxis(SDFAxis axis)
{
if (axis == null)
return new Vector3D(DEFAULT_AXIS);
Vector3D parsedAxis = parseVector3D(axis.getXYZ(), new Vector3D(DEFAULT_AXIS));
parsedAxis.normalize();
return parsedAxis;
}
public static double parseDouble(String value, double defaultValue)
{
if (value == null)
return defaultValue;
return Double.parseDouble(value);
}
public static int parseInteger(String value, int defaultValue)
{
if (value == null)
return defaultValue;
return Integer.parseInt(value);
}
public static Vector3D parseVector3D(String value, Vector3D defaultValue)
{
if (value == null)
return defaultValue;
String[] split = value.strip().split("\\s+");
Vector3D vector = new Vector3D();
vector.setX(Double.parseDouble(split[0]));
vector.setY(Double.parseDouble(split[1]));
vector.setZ(Double.parseDouble(split[2]));
return vector;
}
public static double[] parseArray(String value, double[] defaultValue)
{
if (value == null)
return defaultValue;
String[] split = value.strip().split("\\s+");
double[] array = new double[split.length];
for (int i = 0; i < split.length; i++)
array[i] = Double.parseDouble(split[i]);
return array;
}
}