Version 2.1.2: Python bindings, OBJ assets support, bugfixes.

PiperOrigin-RevId: 434731612
Change-Id: I0cfda3e7a3d1c72036764986efc252ffa1b8c6b0
This commit is contained in:
Saran Tunyasuvunakool
2022-03-15 14:04:44 +00:00
parent 175d25cd9f
commit 3577e2cf8b
304 changed files with 23906 additions and 1013 deletions
@@ -0,0 +1,52 @@
// Copyright 2019 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Xml;
using UnityEngine;
namespace Mujoco {
// The component represents a joint with 1 degree of translational freedom.
public class MjBallJoint : MjBaseJoint {
[Tooltip("In radians.")]
public float RangeUpper;
[Tooltip("Joint settings.")]
public MjJointSettings Settings = MjJointSettings.Default;
protected override void OnParseMjcf(XmlElement mjcf) {
// Transform.
transform.localPosition =
MjEngineTool.UnityVector3(mjcf.GetVector3Attribute("pos", defaultValue: Vector3.zero));
Settings.FromMjcf(mjcf);
var rangeValues = mjcf.GetFloatArrayAttribute("range", defaultValue: new float[] { 0, 0 });
// rangeValues[0] is always 0 for ball joints.
RangeUpper = rangeValues[1];
}
protected override XmlElement OnGenerateMjcf(XmlDocument doc) {
var mjcf = (XmlElement)doc.CreateElement("joint");
mjcf.SetAttribute("type", "ball");
MjEngineTool.PositionToMjcf(mjcf, this);
Settings.ToMjcf(mjcf);
mjcf.SetAttribute("range", MjEngineTool.MakeLocaleInvariant($"0 {RangeUpper}"));
return mjcf;
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: bc71be844486c4586ba729c1ab4d914a
timeCreated: 1552056297
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,63 @@
// Copyright 2019 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Xml;
using UnityEngine;
namespace Mujoco {
public abstract class MjBaseJoint : MjComponent {
public override MujocoLib.mjtObj ObjectType => MujocoLib.mjtObj.mjOBJ_JOINT;
public int QposAddress { get; private set; } = -1;
public int DofAddress { get; private set; } = -1;
// Joint will add Degrees of Freedom to this MjBaseBody.
// It's the MjBaseBody located immediately above this joint in the scene tree.
// NOTE: This property won't be initialized until runtime.
public MjBaseBody ParentBody { get; private set; }
// Joint will constrain the ParentBody to this MjBaseBody.
// It's the MjBaseBody located two levels above this joint in the scene tree.
// For some joints, such as MjFreeJoint, this can be null.
// NOTE: This property won't be initialized until runtime.
public MjBaseBody GrandParentBody { get; private set; }
// Return the bodies connected by this joint.
public void GetConnectedBodies(out MjBaseBody grandParent, out MjBaseBody parent) {
parent = MjHierarchyTool.FindParentComponent<MjBaseBody>(this);
if (parent != null) {
grandParent = MjHierarchyTool.FindParentComponent<MjBaseBody>(parent);
} else {
grandParent = null;
}
}
protected override unsafe void OnBindToRuntime(MujocoLib.mjModel_* model, MujocoLib.mjData_* data) {
QposAddress = model->jnt_qposadr[MujocoId];
DofAddress = model->jnt_dofadr[MujocoId];
}
protected override void Start() {
base.Start();
MjBaseBody grandparentBody, parentBody;
GetConnectedBodies(out grandparentBody, out parentBody);
GrandParentBody = grandparentBody;
ParentBody = parentBody;
if (ParentBody == null) {
throw new Exception("The joint doesn't have a ParentBody.");
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 07bd997db28964e5daf6af0ff47e157f
timeCreated: 1538399740
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,29 @@
// Copyright 2019 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Xml;
using UnityEngine;
namespace Mujoco {
// The component represents a joint with 6 degrees of freedom.
public class MjFreeJoint : MjBaseJoint {
protected override void OnParseMjcf(XmlElement mjcf) {}
protected override XmlElement OnGenerateMjcf(XmlDocument doc) {
return (XmlElement)doc.CreateElement("freejoint");
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 7ef627bd3075d42d886135a149a187a2
timeCreated: 1537540954
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,88 @@
// Copyright 2019 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Xml;
using UnityEngine;
namespace Mujoco {
public class MjHingeJoint : MjBaseJoint {
[Tooltip("In degrees.")]
public float RangeLower;
[Tooltip("In degrees.")]
public float RangeUpper;
[Tooltip("The current joint angle, in degrees. Read-only at play time.")]
public float Configuration;
[Tooltip("Joint movement, in rad/sec. Read-only at play time.")]
public float Velocity;
[Tooltip("Joint settings.")]
public MjJointSettings Settings = MjJointSettings.Default;
// World space rotation axis.
public Vector3 RotationAxis => transform.rotation * Vector3.right;
protected override unsafe void OnBindToRuntime(MujocoLib.mjModel_* model, MujocoLib.mjData_* data) {
base.OnBindToRuntime(model, data);
data->qvel[DofAddress] = Velocity;
}
public override unsafe void OnSyncState(MujocoLib.mjData_* data) {
var qpos = (float)data->qpos[QposAddress];
Configuration = (qpos % (2 * Mathf.PI)) * Mathf.Rad2Deg;
Velocity = (float)data->qvel[DofAddress];
}
protected override void OnParseMjcf(XmlElement mjcf) {
transform.localPosition =
MjEngineTool.UnityVector3(mjcf.GetVector3Attribute("pos", defaultValue: Vector3.zero));
var rotationAxis =
MjEngineTool.UnityVector3(mjcf.GetVector3Attribute("axis", defaultValue: Vector3.right));
transform.localRotation = Quaternion.FromToRotation(Vector3.right, rotationAxis);
var rangeValues = mjcf.GetFloatArrayAttribute("range", defaultValue: new float[] { 0, 0 });
RangeLower = rangeValues[0];
RangeUpper = rangeValues[1];
if (!MjSceneImportSettings.AnglesInDegrees) {
RangeLower *= Mathf.Rad2Deg;
RangeUpper *= Mathf.Rad2Deg;
}
Configuration = mjcf.GetFloatAttribute("ref", 0.0f);
Settings.FromMjcf(mjcf);
}
protected override XmlElement OnGenerateMjcf(XmlDocument doc) {
var mjcf = (XmlElement)doc.CreateElement("joint");
mjcf.SetAttribute("type", "hinge");
MjEngineTool.PositionAxisToMjcf(mjcf, this);
Settings.ToMjcf(mjcf);
if (RangeLower > RangeUpper) {
throw new ArgumentException("Lower range value can't be bigger than Higher");
}
mjcf.SetAttribute("range", $"{RangeLower} {RangeUpper}");
mjcf.SetAttribute("ref", $"{Configuration}");
return mjcf;
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 517cde9d618b143a19f0ad61355a7f31
timeCreated: 1537542636
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,171 @@
// Copyright 2019 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Xml;
using UnityEngine;
namespace Mujoco {
[Serializable]
public struct MjJointSettings {
[Tooltip("Added inertia of all DoFs created by this joint.")]
public float Armature;
[Tooltip("Joint spring settings.")]
public SpringSettings Spring;
[Tooltip("Joint solver settings.")]
public SolverSettings Solver;
// Default joint settings.
public static MjJointSettings Default = new MjJointSettings() {
Solver = SolverSettings.Default,
};
public void FromMjcf(XmlElement mjcf) {
Armature = mjcf.GetFloatAttribute("armature", 0.0f);
Spring.FromMjcf(mjcf);
Solver.FromMjcf(mjcf);
}
public void ToMjcf(XmlElement mjcf) {
mjcf.SetAttribute("armature", MjEngineTool.MakeLocaleInvariant($"{Armature}"));
Spring.ToMjcf(mjcf);
Solver.ToMjcf(mjcf);
}
}
[Serializable]
public struct SpringSettings {
public float TimeConstant;
public float DampingRatio;
[Tooltip("Joint stiffness. If this value is positive, a spring will be created.")]
public float Stiffness;
[Tooltip("Damping applied to all degrees of freedom created by this joint.")]
public float Damping;
[Tooltip("Spring equilibrium pose.")]
public float EquilibriumPose;
public void ToMjcf(XmlElement mjcf) {
// Spring settings.
mjcf.SetAttribute("springref", MjEngineTool.MakeLocaleInvariant($"{EquilibriumPose}"));
mjcf.SetAttribute("springdamper", MjEngineTool.MakeLocaleInvariant($"{TimeConstant} {DampingRatio}"));
mjcf.SetAttribute("damping", MjEngineTool.MakeLocaleInvariant($"{Damping}"));
mjcf.SetAttribute("stiffness", MjEngineTool.MakeLocaleInvariant($"{Stiffness}"));
}
public void FromMjcf(XmlElement mjcf) {
var springDamper = mjcf.GetVector2Attribute("springdamper", Vector2.zero);
TimeConstant = springDamper.x;
DampingRatio = springDamper.y;
EquilibriumPose = mjcf.GetFloatAttribute("springref", 0.0f);
Damping = mjcf.GetFloatAttribute("damping", 0.0f);
Stiffness = mjcf.GetFloatAttribute("stiffness", 0.0f);
}
}
[Serializable]
public struct SolverImpedance {
public float DMin;
public float DMax;
public float Width;
public float Midpoint;
public float Power;
public static SolverImpedance Default =
new SolverImpedance() { DMin = 0.9f, DMax = 0.95f, Width = 0.001f, Midpoint = 0.5f,
Power = 2.0f };
public void FromMjcf(XmlElement element, string attributeName) {
var values = element.GetFloatArrayAttribute(
attributeName, new float[] { Default.DMin, Default.DMax, Default.Width, Default.Midpoint,
Default.Power });
DMin = values[0];
DMax = values[1];
Width = values[2];
Midpoint = values[3];
Power = values[4];
}
public void ToMjcf(XmlElement element, string attributeName) {
element.SetAttribute(attributeName, MjEngineTool.MakeLocaleInvariant($"{DMin} {DMax} {Width} {Midpoint} {Power}"));
}
}
[Serializable]
public struct SolverReference {
public float TimeConst;
public float DampRatio;
public static SolverReference Default =
new SolverReference() { TimeConst = 0.02f, DampRatio = 1.0f };
public void FromMjcf(XmlElement element, string attributeName) {
var values = element.GetFloatArrayAttribute(
attributeName, new float[] { Default.TimeConst, Default.DampRatio });
TimeConst = values[0];
DampRatio = values[1];
}
public void ToMjcf(XmlElement element, string attributeName) {
element.SetAttribute(attributeName, MjEngineTool.MakeLocaleInvariant($"{TimeConst} {DampRatio}"));
}
}
[Serializable]
public struct SolverSettings {
[Tooltip("Does the joint have limits.")]
public bool Limited;
[Tooltip("Limit margin - always in radians/meters.")]
public float Margin;
public SolverReference RefLimit;
public SolverImpedance ImpLimit;
[Tooltip("Friction loss due to dry friction.")]
public float FrictionLoss;
public SolverImpedance ImpFriction;
public SolverReference RefFriction;
public static SolverSettings Default = new SolverSettings() {
ImpFriction = SolverImpedance.Default,
ImpLimit = SolverImpedance.Default,
RefFriction = SolverReference.Default,
RefLimit = SolverReference.Default,
};
public void ToMjcf(XmlElement mjcf) {
RefLimit.ToMjcf(mjcf, "solreflimit");
ImpLimit.ToMjcf(mjcf, "solimplimit");
RefFriction.ToMjcf(mjcf, "solreffriction");
ImpFriction.ToMjcf(mjcf, "solimpfriction");
mjcf.SetAttribute("frictionloss", MjEngineTool.MakeLocaleInvariant($"{FrictionLoss}"));
mjcf.SetAttribute("limited", $"{Limited}".ToLower());
mjcf.SetAttribute("margin", MjEngineTool.MakeLocaleInvariant($"{Margin}"));
}
public void FromMjcf(XmlElement mjcf) {
RefLimit.FromMjcf(mjcf, "solreflimit");
ImpLimit.FromMjcf(mjcf, "solimplimit");
RefFriction.FromMjcf(mjcf, "solreffriction");
ImpFriction.FromMjcf(mjcf, "solimpfriction");
FrictionLoss = mjcf.GetFloatAttribute("frictionloss", 0.0f);
Limited = mjcf.GetBoolAttribute("limited", false);
Margin = mjcf.GetFloatAttribute("margin", defaultValue: 0.0f);
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: c02a22208190149a6a949f4247c77155
timeCreated: 1537542636
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,85 @@
// Copyright 2019 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Xml;
using UnityEngine;
namespace Mujoco {
// The component represents a joint with 1 degree of translational freedom.
public class MjSlideJoint : MjBaseJoint {
[Tooltip("In meters.")]
public float RangeLower;
[Tooltip("In meters.")]
public float RangeUpper;
[Tooltip("The current joint angle, in degrees. Read-only at play time.")]
public float Configuration;
[Tooltip("Joint movement, in rad/sec. Read-only at play time.")]
public float Velocity;
[Tooltip("Joint settings.")]
public MjJointSettings Settings = MjJointSettings.Default;
// World space slide axis.
public Vector3 SlideAxis => transform.rotation * Vector3.right;
protected override unsafe void OnBindToRuntime(MujocoLib.mjModel_* model, MujocoLib.mjData_* data) {
base.OnBindToRuntime(model, data);
data->qvel[DofAddress] = Velocity;
}
public override unsafe void OnSyncState(MujocoLib.mjData_* data) {
var qpos = (float)data->qpos[QposAddress];
Configuration = (qpos % (2 * Mathf.PI)) * Mathf.Rad2Deg;
Velocity = (float)data->qvel[DofAddress];
}
protected override void OnParseMjcf(XmlElement mjcf) {
// Transform.
transform.localPosition =
MjEngineTool.UnityVector3(mjcf.GetVector3Attribute("pos", defaultValue: Vector3.zero));
var rotationAxis =
MjEngineTool.UnityVector3(mjcf.GetVector3Attribute("axis", defaultValue: Vector3.right));
transform.localRotation = Quaternion.FromToRotation(Vector3.right, rotationAxis);
var rangeValues = mjcf.GetFloatArrayAttribute("range", defaultValue: new float[] { 0, 0 });
RangeLower = rangeValues[0];
RangeUpper = rangeValues[1];
Configuration = mjcf.GetFloatAttribute("ref", 0.0f);
Settings.FromMjcf(mjcf);
}
protected override XmlElement OnGenerateMjcf(XmlDocument doc) {
var mjcf = (XmlElement)doc.CreateElement("joint");
mjcf.SetAttribute("type", "slide");
MjEngineTool.PositionAxisToMjcf(mjcf, this);
Settings.ToMjcf(mjcf);
if (RangeLower > RangeUpper) {
throw new ArgumentException("Lower range value can't be bigger than Higher");
}
mjcf.SetAttribute("range", MjEngineTool.MakeLocaleInvariant($"{RangeLower} {RangeUpper}"));
mjcf.SetAttribute("ref", MjEngineTool.MakeLocaleInvariant($"{Configuration}"));
return mjcf;
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 0f0920b38d2fe4e21bb645eff3f73be4
timeCreated: 1537527115
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: