implementation of drecon in unity 2022 lts
forked from:
https://github.com/joanllobera/marathon-envs
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
4.3 KiB
108 lines
4.3 KiB
9 months ago
|
// Helper Utilities to work with agent's rigid bodies charateristics. Allows to
|
||
|
// calculate Angles between rotations in radians, find center of mass of an agent,
|
||
|
// and find Angular Momentum of an agent.
|
||
|
|
||
|
using UnityEngine;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System;
|
||
|
|
||
|
public static class JointHelper002 {
|
||
|
|
||
|
// Return rotation from one rotation to another
|
||
|
public static Quaternion FromToRotation(Quaternion from, Quaternion to) {
|
||
|
if (to == from) return Quaternion.identity;
|
||
|
|
||
|
return to * Quaternion.Inverse(from);
|
||
|
}
|
||
|
|
||
|
// Calculate rotation between two rotations in radians. Adjusts the value to lie within [-pi, +pi].
|
||
|
public static Vector3 NormalizedEulerAngles(Vector3 eulerAngles) {
|
||
|
var x = eulerAngles.x < 180f ?
|
||
|
eulerAngles.x :
|
||
|
-360 + eulerAngles.x;
|
||
|
var y = eulerAngles.y < 180f ?
|
||
|
eulerAngles.y :
|
||
|
-360 + eulerAngles.y;
|
||
|
var z = eulerAngles.z < 180f ?
|
||
|
eulerAngles.z :
|
||
|
-360 + eulerAngles.z;
|
||
|
x = x * Mathf.Deg2Rad;
|
||
|
y = y * Mathf.Deg2Rad;
|
||
|
z = z * Mathf.Deg2Rad;
|
||
|
return new Vector3(x, y, z);
|
||
|
}
|
||
|
|
||
|
// Adjust the value of an angle to lie within [-pi, +pi].
|
||
|
public static float NormalizedAngle(float angle) {
|
||
|
if (angle < 180) {
|
||
|
return angle * Mathf.Deg2Rad;
|
||
|
}
|
||
|
return (angle - 360) * Mathf.Deg2Rad;
|
||
|
}
|
||
|
|
||
|
// Find rotation and convert to radians within [-pi, +pi].
|
||
|
public static Vector3 CalcDeltaRotationNormalizedEuler(Quaternion from, Quaternion to) {
|
||
|
var rotationVelocity = FromToRotation(from, to);
|
||
|
var angularVelocity = NormalizedEulerAngles(rotationVelocity.eulerAngles);
|
||
|
return angularVelocity;
|
||
|
}
|
||
|
|
||
|
// Find the center of mass of a list of Body Parts beloning to an agent. Relative to the root bone, i. e. "butt" for humanoid.
|
||
|
public static Vector3 GetCenterOfMassRelativeToRoot(List<BodyPart002> BodyParts) {
|
||
|
var centerOfMass = Vector3.zero;
|
||
|
float totalMass = 0f;
|
||
|
var bodies = BodyParts
|
||
|
.Select(x => x.Rigidbody)
|
||
|
.Where(x => x != null)
|
||
|
.ToList();
|
||
|
var rootBone = BodyParts[0];
|
||
|
foreach (Rigidbody rb in bodies) {
|
||
|
centerOfMass += rb.worldCenterOfMass * rb.mass;
|
||
|
totalMass += rb.mass;
|
||
|
}
|
||
|
centerOfMass /= totalMass;
|
||
|
centerOfMass -= rootBone.InitialRootPosition;
|
||
|
return centerOfMass;
|
||
|
}
|
||
|
|
||
|
// Find the center of mass of a List of Body Parts relative to the world coordinate system.
|
||
|
public static Vector3 GetCenterOfMassWorld(List<BodyPart002> BodyParts) {
|
||
|
var centerOfMass = GetCenterOfMassRelativeToRoot(BodyParts) + BodyParts[0].InitialRootPosition;
|
||
|
return centerOfMass;
|
||
|
}
|
||
|
|
||
|
// Calculate Angular Momentum of a List of Body Parts. In the world coordinate system about the center
|
||
|
// of mass of the Body Parts. Formulas at https://ocw.mit.edu/courses/aeronautics-and-astronautics/16-07-dynamics-fall-2009/lecture-notes/MIT16_07F09_Lec11.pdf
|
||
|
public static Vector3 GetAngularMoment(List<BodyPart002> BodyParts) {
|
||
|
var centerOfMass = GetCenterOfMassWorld(BodyParts);
|
||
|
var bodies = BodyParts
|
||
|
.Select(x => x.Rigidbody)
|
||
|
.Where(x => x != null)
|
||
|
.ToList();
|
||
|
Vector3 totalAngularMoment = Vector3.zero;
|
||
|
foreach (Rigidbody rb in bodies) {
|
||
|
|
||
|
var w_local = rb.transform.rotation * rb.angularVelocity;
|
||
|
var w_inertiaFrame = rb.inertiaTensorRotation * w_local;
|
||
|
|
||
|
Vector3 L_inertiaFrame = Vector3.zero;
|
||
|
L_inertiaFrame[0] = w_inertiaFrame[0] * rb.inertiaTensor[0];
|
||
|
L_inertiaFrame[1] = w_inertiaFrame[1] * rb.inertiaTensor[1];
|
||
|
L_inertiaFrame[2] = w_inertiaFrame[2] * rb.inertiaTensor[2];
|
||
|
|
||
|
Vector3 L_world = Quaternion.Inverse(rb.transform.rotation) * Quaternion.Inverse(rb.inertiaTensorRotation) * L_inertiaFrame;
|
||
|
|
||
|
Vector3 bodyPartCenterOfMassRelativeTobodyPartsCenterOfMass = rb.worldCenterOfMass - centerOfMass;
|
||
|
Vector3 LofBodyPartCenterOfMass = rb.mass * Vector3.Cross(bodyPartCenterOfMassRelativeTobodyPartsCenterOfMass, rb.velocity);
|
||
|
|
||
|
totalAngularMoment += L_world + LofBodyPartCenterOfMass;
|
||
|
|
||
|
}
|
||
|
return totalAngularMoment;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|