redid the global settings according to suggested guidelines

This commit is contained in:
Joan Llobera
2025-10-13 14:50:08 +02:00
parent cfd487c315
commit 655b961c89
+95 -53
View File
@@ -13,57 +13,59 @@
// limitations under the License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using UnityEngine;
using UnityEngine.Profiling;
namespace Mujoco {
namespace Mujoco
{
// The MuJoCo parser is case-sensitive. The case format of the entries in the enums below is
// exactly what the documentation specifies: http://mujoco.org/book/XMLreference.html#option .
public enum IntegratorType {
public enum IntegratorType
{
Euler,
RK4,
@implicit,
@implicitfast
}
public enum FrictionConeType {
public enum FrictionConeType
{
pyramidal,
elliptic
}
public enum JacobianType {
public enum JacobianType
{
dense,
sparse,
auto
}
public enum ConstraintSolverType {
public enum ConstraintSolverType
{
PGS,
CG,
Newton
}
public enum EnableDisableFlag {
public enum EnableDisableFlag
{
enable,
disable
}
[Serializable]
public struct MjcfOptionFlag {
public struct MjcfOptionFlag
{
public EnableDisableFlag Constraint;
public EnableDisableFlag Equality;
public EnableDisableFlag FrictionLoss;
public EnableDisableFlag Limit;
public EnableDisableFlag Contact;
public EnableDisableFlag Passive;
public EnableDisableFlag Spring;
public EnableDisableFlag Damper;
public EnableDisableFlag Gravity;
public EnableDisableFlag ClampCtrl;
public EnableDisableFlag WarmStart;
@@ -74,13 +76,15 @@ public struct MjcfOptionFlag {
public EnableDisableFlag Energy;
public EnableDisableFlag FwdInv;
public EnableDisableFlag MultiCCD;
public static MjcfOptionFlag Default = new MjcfOptionFlag() {
public static MjcfOptionFlag Default = new MjcfOptionFlag()
{
Constraint = EnableDisableFlag.enable,
Equality = EnableDisableFlag.enable,
FrictionLoss = EnableDisableFlag.enable,
Limit = EnableDisableFlag.enable,
Contact = EnableDisableFlag.enable,
Passive = EnableDisableFlag.enable,
Spring = EnableDisableFlag.enable,
Damper = EnableDisableFlag.enable,
Gravity = EnableDisableFlag.enable,
ClampCtrl = EnableDisableFlag.enable,
WarmStart = EnableDisableFlag.enable,
@@ -93,7 +97,8 @@ public struct MjcfOptionFlag {
MultiCCD = EnableDisableFlag.disable
};
public void FromMjcf(XmlElement mjcf) {
public void FromMjcf(XmlElement mjcf)
{
var localDefault = MjcfOptionFlag.Default;
Constraint = mjcf.GetEnumAttribute<EnableDisableFlag>("constraint", localDefault.Constraint);
Equality = mjcf.GetEnumAttribute<EnableDisableFlag>("equality", localDefault.Equality);
@@ -101,7 +106,8 @@ public struct MjcfOptionFlag {
localDefault.FrictionLoss);
Limit = mjcf.GetEnumAttribute<EnableDisableFlag>("limit", localDefault.Limit);
Contact = mjcf.GetEnumAttribute<EnableDisableFlag>("contact", localDefault.Contact);
Passive = mjcf.GetEnumAttribute<EnableDisableFlag>("passive", localDefault.Passive);
Spring = mjcf.GetEnumAttribute<EnableDisableFlag>("spring", localDefault.Spring);
Damper = mjcf.GetEnumAttribute<EnableDisableFlag>("damper", localDefault.Damper);
Gravity = mjcf.GetEnumAttribute<EnableDisableFlag>("gravity", localDefault.Gravity);
ClampCtrl = mjcf.GetEnumAttribute<EnableDisableFlag>("clampctrl", localDefault.ClampCtrl);
WarmStart = mjcf.GetEnumAttribute<EnableDisableFlag>("warmstart", localDefault.WarmStart);
@@ -115,13 +121,15 @@ public struct MjcfOptionFlag {
MultiCCD = mjcf.GetEnumAttribute<EnableDisableFlag>("multiccd", localDefault.MultiCCD);
}
public void ToMjcf(XmlElement mjcf) {
public void ToMjcf(XmlElement mjcf)
{
mjcf.SetAttribute("constraint", Constraint.ToString());
mjcf.SetAttribute("equality", Equality.ToString());
mjcf.SetAttribute("frictionloss", FrictionLoss.ToString());
mjcf.SetAttribute("limit", Limit.ToString());
mjcf.SetAttribute("contact", Contact.ToString());
// mjcf.SetAttribute("passive", Passive.ToString());
mjcf.SetAttribute("spring", Spring.ToString());
mjcf.SetAttribute("damper", Damper.ToString());
mjcf.SetAttribute("gravity", Gravity.ToString());
mjcf.SetAttribute("clampctrl", ClampCtrl.ToString());
mjcf.SetAttribute("warmstart", WarmStart.ToString());
@@ -136,27 +144,31 @@ public struct MjcfOptionFlag {
}
[Serializable]
public struct MjSizeStruct {
public struct MjSizeStruct
{
public String Memory;
public static MjSizeStruct Default = new MjSizeStruct() {
public static MjSizeStruct Default = new MjSizeStruct()
{
Memory = "-1"
};
public void ParseMjcf(XmlElement mjcf) {
public void ParseMjcf(XmlElement mjcf)
{
Memory = mjcf.GetStringAttribute("memory", "-1");
}
public XmlElement ToMjcf(XmlElement mjcf) {
public XmlElement ToMjcf(XmlElement mjcf)
{
mjcf.SetAttribute("memory", $"{Memory}");
return mjcf;
}
}
[Serializable]
public struct MjOptionStruct {
public struct MjOptionStruct
{
// "timestep" and "gravity" come from global settings.
// "apirate" is only relevant to HAPTIX.
[Tooltip("Ratio of frictional-to-normal constraint impedance.")]
public float ImpRatio;
[Tooltip("Global magnetic flux used by magnetometer sensors.")]
@@ -197,7 +209,8 @@ public struct MjOptionStruct {
public MjcfOptionFlag Flag;
// Default values copied from the "XML reference" page in the MuJoCo documentation.
public static MjOptionStruct Default = new MjOptionStruct() {
public static MjOptionStruct Default = new MjOptionStruct()
{
ImpRatio = 1.0f,
Magnetic = Vector3.zero,
Wind = new Vector3(0.0f, 0.0f, 0.0f),
@@ -219,17 +232,21 @@ public struct MjOptionStruct {
Flag = MjcfOptionFlag.Default
};
public void ParseMjcf(XmlElement mjcf) {
if (mjcf.HasAttribute("timestep")) {
public void ParseMjcf(XmlElement mjcf)
{
if (mjcf.HasAttribute("timestep"))
{
var mjTimestep = mjcf.GetFloatAttribute("timestep", Time.fixedDeltaTime);
if (mjTimestep != Time.fixedDeltaTime) {
if (mjTimestep != Time.fixedDeltaTime)
{
Debug.unityLogger.LogWarning(
"MuJoCo",
$"MuJoCo's timestep ({mjTimestep}s) ignored, please set fixedDeltaTime manually.",
null);
}
}
if (mjcf.HasAttribute("gravity")) {
if (mjcf.HasAttribute("gravity"))
{
var mjGravity = mjcf.GetVector3Attribute("gravity", Vector3.zero);
Debug.unityLogger.LogWarning(
"MuJoCo",
@@ -262,17 +279,22 @@ public struct MjOptionStruct {
CcdTolerance = mjcf.GetFloatAttribute("ccd_tolerance", localDefault.CcdTolerance);
var flagElements = mjcf.GetElementsByTagName("flag");
if (flagElements.Count == 1) {
if (flagElements.Count == 1)
{
Flag.FromMjcf(flagElements[0] as XmlElement);
} else if (flagElements.Count > 1) {
}
else if (flagElements.Count > 1)
{
throw new ArgumentException("More than one <flag> node is not supported.");
}
}
public XmlElement ToMjcf(XmlElement mjcf) {
public XmlElement ToMjcf(XmlElement mjcf)
{
mjcf.SetAttribute("impratio", MjEngineTool.MakeLocaleInvariant($"{ImpRatio}"));
mjcf.SetAttribute("magnetic", MjEngineTool.MakeLocaleInvariant($"{Magnetic.x} {Magnetic.y} {Magnetic.z}"));
mjcf.SetAttribute("magnetic",
MjEngineTool.MakeLocaleInvariant($"{Magnetic.x} {Magnetic.y} {Magnetic.z}"));
mjcf.SetAttribute("wind", MjEngineTool.MakeLocaleInvariant($"{Wind.x} {Wind.y} {Wind.z}"));
mjcf.SetAttribute("density", MjEngineTool.MakeLocaleInvariant($"{Density}"));
@@ -302,13 +324,15 @@ public struct MjOptionStruct {
}
[Serializable]
public class NumericEntry {
public class NumericEntry
{
public String Name;
[Tooltip("Space-separated list of floats.")]
public String Data;
}
public class MjGlobalSettings : MonoBehaviour {
public class MjGlobalSettings : MonoBehaviour
{
[Tooltip("Filename for the generated scene XML.")]
public string DebugFileName;
@@ -325,14 +349,20 @@ public class MjGlobalSettings : MonoBehaviour {
public List<NumericEntry> CustomNumeric = new List<NumericEntry>() { };
public static MjGlobalSettings Instance {
get {
if (_instance == null) {
public static MjGlobalSettings Instance
{
get
{
if (_instance == null)
{
var instances = FindObjectsOfType<MjGlobalSettings>();
if (instances.Length > 1) {
if (instances.Length > 1)
{
throw new InvalidOperationException(
"Only one MjGlobalSettings instance is allowed - please resolve manually.");
} else if (instances.Length == 1) {
}
else if (instances.Length == 1)
{
_instance = instances[0];
}
}
@@ -342,31 +372,41 @@ public class MjGlobalSettings : MonoBehaviour {
private static MjGlobalSettings _instance = null;
public void Awake() {
if (_instance == null) {
public void Awake()
{
if (_instance == null)
{
_instance = this;
} else if (_instance != this) {
}
else if (_instance != this)
{
throw new InvalidOperationException(
"At most one MjGlobalSettings should be present.");
}
}
public void ParseGlobalMjcfSections(XmlElement mujocoNode) {
public void ParseGlobalMjcfSections(XmlElement mujocoNode)
{
var optionNode = mujocoNode.SelectSingleNode("option") as XmlElement;
var sizeNode = mujocoNode.SelectSingleNode("size") as XmlElement;
var customNode = mujocoNode.SelectSingleNode("custom") as XmlElement;
if (optionNode != null) {
if (optionNode != null)
{
GlobalOptions.ParseMjcf(optionNode);
}
if (sizeNode != null) {
if (sizeNode != null)
{
GlobalSizes.ParseMjcf(sizeNode);
}
if (customNode != null) {
foreach (var childNode in customNode.ChildNodes) {
if (customNode != null)
{
foreach (var childNode in customNode.ChildNodes)
{
var child = childNode as XmlElement;
if (child.Name == "numeric") {
if (child.Name == "numeric")
{
var numeric = new NumericEntry();
numeric.Name = child.GetAttribute("name");
numeric.Data = child.GetAttribute("data");
@@ -376,14 +416,16 @@ public class MjGlobalSettings : MonoBehaviour {
}
}
public void GlobalsToMjcf(XmlElement mjcf) {
public void GlobalsToMjcf(XmlElement mjcf)
{
var doc = mjcf.OwnerDocument;
var optionMjcf = (XmlElement)mjcf.AppendChild(doc.CreateElement("option"));
GlobalOptions.ToMjcf(optionMjcf);
var sizeMjcf = (XmlElement)mjcf.AppendChild(doc.CreateElement("size"));
GlobalSizes.ToMjcf(sizeMjcf);
var customMjcf = (XmlElement)mjcf.AppendChild(doc.CreateElement("custom"));
foreach (var numeric in CustomNumeric) {
foreach (var numeric in CustomNumeric)
{
var numericMjcf = (XmlElement)customMjcf.AppendChild(doc.CreateElement("numeric"));
numericMjcf.SetAttribute("name", numeric.Name);
// TODO: add validation that data is a space-separated list of floating numbers?