| name | coordinate-conversion |
| description | Convert between SDF (right-hand) and Unity (left-hand) coordinate systems. Use when: implementing pose transforms, converting sensor data between coordinate frames, debugging position/rotation mismatches. |
Coordinate System Conversion Reference
Quick reference for converting between SDF and Unity coordinate systems in CLOiSim.
When to Use
- Converting positions, rotations, or scales between SDF and Unity
- Debugging pose mismatches after import
- Implementing sensor data output in the correct frame
- Converting joint axes or velocities
Coordinate Systems
SDF (right-hand): X-forward, Y-left, Z-up
Unity (left-hand): X-right, Y-up, Z-forward
Conversion Formulas
SDF → Unity (SDF2Unity)
Unity.X = -SDF.Y
Unity.Y = SDF.Z
Unity.Z = SDF.X
Position:
Vector3 pos = SDF2Unity.Position(in double x, in double y, in double z);
Vector3 pos = sdfVector3d.ToUnity();
Vector3 pos = protobufVector3d.ToUnity();
Rotation (quaternion):
Quaternion rot = SDF2Unity.Rotation(in double w, in double x, in double y, in double z);
Quaternion rot = sdfQuaterniond.ToUnity();
Pose (position + rotation):
var (position, rotation) = sdfPose3d.ToUnity();
Scale:
Vector3 scale = SDF2Unity.Scalar(in double x, in double y, in double z);
Vector3 scale = SDF2Unity.Scale(sdfVector3d);
Curve orientation (for roads/splines):
float angleDeg = SDF2Unity.CurveOrientation(in float radians);
float angleRad = SDF2Unity.CurveOrientationAngle(in float radians);
Unity → SDF (Unity2SDF)
SDF.X = Unity.Z
SDF.Y = -Unity.X
SDF.Z = Unity.Y
Position:
SDFormat.Math.Vector3d sdfPos = Unity2SDF.Position(in Vector3 value);
Rotation:
SDFormat.Math.Quaterniond sdfRot = Unity2SDF.Rotation(in Quaternion value);
Pose:
SDFormat.Math.Pose3d sdfPose = Unity2SDF.Pose(in Vector3 pos, in Quaternion rot);
Direction reversal (for road/curve orientation):
Vector3 reversed = Unity2SDF.Direction.Reverse(in Vector3 value);
float curveDir = Unity2SDF.Direction.Curve(in float value);
Joint prismatic direction:
float val = Unity2SDF.Direction.Joint.Prismatic(in float value, in Vector3 rotation);
Common Patterns
In Sensor Devices
Sensor data output typically needs Unity→SDF conversion before publishing:
var sdfPosition = Unity2SDF.Position(transform.position);
_msg.Position.Set(sdfPosition.X, sdfPosition.Y, sdfPosition.Z);
In SDF Import
During import, always use ToUnity() extension methods:
var (localPosition, localRotation) = sdfElement.RawPose.ToUnity();
newObject.transform.localPosition = localPosition;
newObject.transform.localRotation = localRotation;
In Joint Axes
Joint axis directions are converted during import:
var jointAxis = joint.Axis.Xyz.ToUnity().normalized;
var springRef = SDF2Unity.CurveOrientation((float)joint.Axis.SpringReference);
Color Conversion
Color unityColor = sdfColor.ToUnity();
Color fromString = "0.5 0.5 0.5 1.0".ToColor();
2D Conversions
Vector2 size = SDF2Unity.Size(sdfVector2d);
Vector2 point = SDF2Unity.Point(sdfVector2d);
Critical Rules
- Never manually swap axes — always use
SDF2Unity / Unity2SDF methods
- Extension methods are available on
SDFormat.Math.Vector3d, Quaterniond, Pose3d, and cloisim.msgs.Vector3d
- Scale conversion preserves signs for mesh scaling but uses absolute values for collider sizing
- Protobuf message
.Set() extensions handle conversion internally — check whether they expect Unity-space or SDF-space input before calling
- Partial classes:
SDF2Unity is split across SDF2Unity.cs, SDF2Unity.Material.cs, SDF2Unity.Mesh.cs, SDF2Unity.Model.cs