diff --git a/unity/Runtime/Components/Bodies/MjBody.cs b/unity/Runtime/Components/Bodies/MjBody.cs index 8d6a8cd3..e29de5c0 100644 --- a/unity/Runtime/Components/Bodies/MjBody.cs +++ b/unity/Runtime/Components/Bodies/MjBody.cs @@ -20,17 +20,23 @@ namespace Mujoco { // The component represents the apex of hierarchy that defines a single rigid body. public class MjBody : MjBaseBody { + + [Tooltip("Gravity compensation force, specified as fraction of body weight.")] + public float GravityCompensation; + protected override void OnParseMjcf(XmlElement mjcf) { // Transform transform.localPosition = MjEngineTool.UnityVector3(mjcf.GetVector3Attribute("pos", defaultValue: Vector3.zero)); transform.localRotation = MjEngineTool.UnityQuaternion( mjcf.GetQuaternionAttribute("quat", defaultValue: MjEngineTool.MjQuaternionIdentity)); + GravityCompensation = mjcf.GetFloatAttribute("gravcomp", defaultValue: 0.0f); } protected override XmlElement OnGenerateMjcf(XmlDocument doc) { var mjcf = (XmlElement)doc.CreateElement("body"); MjEngineTool.PositionRotationToMjcf(mjcf, this); + mjcf.SetAttribute("gravcomp", MjEngineTool.MakeLocaleInvariant($"{GravityCompensation}")); return mjcf; } diff --git a/unity/Runtime/Components/MjGlobalSettings.cs b/unity/Runtime/Components/MjGlobalSettings.cs index ad8b7e0f..4510a140 100644 --- a/unity/Runtime/Components/MjGlobalSettings.cs +++ b/unity/Runtime/Components/MjGlobalSettings.cs @@ -29,7 +29,8 @@ namespace Mujoco { // exactly what the documentation specifies: http://mujoco.org/book/XMLreference.html#option . public enum IntegratorType { Euler, - RK4 + RK4, + @implicit } public enum CollisionCheckType { @@ -208,7 +209,7 @@ public struct MjOptionStruct { public static MjOptionStruct Default = new MjOptionStruct() { ImpRatio = 1.0f, Magnetic = Vector3.zero, - Wind = new Vector3(0.0f, -0.5f, 0.0f), + Wind = new Vector3(0.0f, 0.0f, 0.0f), Density = 0.0f, Viscosity = 0.0f, OverrideMargin = 0.0f, diff --git a/unity/Runtime/Importer/MjXmlModifiers.cs b/unity/Runtime/Importer/MjXmlModifiers.cs index 66460b59..d9d74040 100644 --- a/unity/Runtime/Importer/MjXmlModifiers.cs +++ b/unity/Runtime/Importer/MjXmlModifiers.cs @@ -28,12 +28,17 @@ namespace Mujoco { _root = root; } - public void ApplyModifiersToElement(XmlElement element) { + public void ApplyModifiersToElement(XmlElement element, string elementName=null) { + // Allow overriding the element name for defaults lookup, needed for tendon + if (elementName == null) { + elementName = element.Name; + } + // Combine all defaults into one. At this stage, we want to overwrite attributes defined by // the previous defaults. var aggregateDefaults = _root.CreateElement("aggregate"); // Root default leaf should be processed only once, and handled first (so it's overriden). - var rootDefaultLeaf = _root.SelectSingleNode($"/mujoco/default/{element.Name}") as XmlElement; + var rootDefaultLeaf = _root.SelectSingleNode($"/mujoco/default/{elementName}") as XmlElement; if (rootDefaultLeaf != null) { CopyAttributes(rootDefaultLeaf, aggregateDefaults); } @@ -43,7 +48,7 @@ namespace Mujoco { var defaultClassElement = _root.SelectSingleNode($"descendant::default[@class='{className}']") as XmlElement; // Ancestry iterates up in the tree, but we want to apply changes from remote to specific. - var ancestors = GetDefaultAncestry(defaultClassElement, element.Name).Reverse(); + var ancestors = GetDefaultAncestry(defaultClassElement, elementName).Reverse(); foreach (var defaultAncestor in ancestors) { CopyAttributesOverwriteExisting(defaultAncestor, aggregateDefaults); } diff --git a/unity/Runtime/Importer/MjcfImporter.cs b/unity/Runtime/Importer/MjcfImporter.cs index fe83df5f..6215e6e0 100644 --- a/unity/Runtime/Importer/MjcfImporter.cs +++ b/unity/Runtime/Importer/MjcfImporter.cs @@ -167,6 +167,7 @@ public class MjcfImporter { if (tendonNode != null) { var tendonsParentObject = CreateGameObjectInParent("tendons", rootObject); foreach (var child in tendonNode.OfType()) { + _modifiers.ApplyModifiersToElement(child, elementName: "tendon"); if (child.Name == "fixed") { CreateGameObjectWithUniqueName(tendonsParentObject, child); } else if (child.Name == "spatial") { @@ -238,7 +239,7 @@ public class MjcfImporter { } } - // Called by ParseBodyChildren for each XML node, overridable by inheriting claases. + // Called by ParseBodyChildren for each XML node, overridable by inheriting classes. private void ParseBodyChild(XmlElement child, GameObject parentObject) { switch (child.Name) { case "geom": {