Skip to content

Commit cf84146

Browse files
committed
Add Unit tests for OpenPLX integration
1 parent f2e8f28 commit cf84146

10 files changed

+651
-0
lines changed

Diff for: Tests/Runtime/AGXUnityTests.asmdef

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
"excludePlatforms": [],
1717
"allowUnsafeCode": false,
1818
"overrideReferences": false,
19+
"precompiledReferences": [
20+
"openplx.dll",
21+
"agxDotNet.dll",
22+
"agxMathDotNet.dll"
23+
],
1924
"autoReferenced": false,
2025
"versionDefines": [],
2126
"noEngineReferences": false

Diff for: Tests/Runtime/AuxiliaryScripts.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using AGXUnity;
2+
using AGXUnity.IO.OpenPLX;
3+
using AGXUnity.Utils;
4+
using UnityEngine;
5+
6+
namespace AGXUnityTesting.Runtime.Aux
7+
{
8+
9+
class PDController
10+
{
11+
public double KP { get; set; }
12+
public double KD { get; set; }
13+
public double Goal { get; set; }
14+
15+
public PDController( double kp, double kd, double goal )
16+
{
17+
KP = kp;
18+
KD = kd;
19+
Goal = goal;
20+
}
21+
22+
public double Observe( double x, double xdot )
23+
{
24+
double error = Goal - x;
25+
return KP * error - KD * xdot;
26+
}
27+
}
28+
29+
public class InvertedPendulumController : ScriptComponent
30+
{
31+
OpenPLXSignals signal = null;
32+
33+
InputTarget motor_input = null;
34+
PDController cart;
35+
PDController pole;
36+
37+
38+
// Start is called before the first frame update
39+
protected override bool Initialize()
40+
{
41+
signal = gameObject.GetInitializedComponent<OpenPLXSignals>();
42+
motor_input = signal.FindInputTarget( "PendulumScene.motor_input" );
43+
44+
if ( motor_input == null )
45+
Debug.LogWarning( "Could not find motor input" );
46+
47+
cart = new PDController( 11, 5, 0 );
48+
pole = new PDController( 19, 5, 0 );
49+
50+
Simulation.Instance.StepCallbacks.PreStepForward += Pre;
51+
52+
hao = signal.FindOutputSource( "PendulumScene.hinge_angle_output" );
53+
havo = signal.FindOutputSource( "PendulumScene.hinge_angular_velocity_output" );
54+
poso = signal.FindOutputSource( "PendulumScene.cart_position_output" );
55+
velo = signal.FindOutputSource( "PendulumScene.cart_velocity_output" );
56+
57+
return true;
58+
}
59+
60+
OutputSource hao;
61+
OutputSource havo;
62+
OutputSource poso;
63+
OutputSource velo;
64+
65+
double ha = 0.0f;
66+
double hav = 0.0f;
67+
double xpos = 0.0f;
68+
double xvel = 0.0f;
69+
double u_cart = 0.0f;
70+
double u_pole = 0.0f;
71+
double raw = 0.0f;
72+
73+
private void Pre()
74+
{
75+
try {
76+
ha = hao.GetCachedValue<double>();
77+
hav = havo.GetCachedValue<double>();
78+
xpos = poso.GetCachedValue<Vector3>().x;
79+
xvel = velo.GetCachedValue<Vector3>().x;
80+
}
81+
catch {
82+
return;
83+
}
84+
85+
u_cart = cart.Observe( xpos, xvel );
86+
u_pole = pole.Observe( ha, hav );
87+
88+
raw = -u_cart - u_pole;
89+
90+
motor_input.SendSignal( Math.Clamp( raw, -1000, 1000 ) );
91+
}
92+
93+
private void OnGUI()
94+
{
95+
GUILayout.Label( $"Angle: {ha}" );
96+
GUILayout.Label( $"A. Vel: {hav}" );
97+
GUILayout.Label( $"Pos: {xpos}" );
98+
GUILayout.Label( $"Vel: {xvel}" );
99+
GUILayout.Label( $"u_cart: {u_cart}" );
100+
GUILayout.Label( $"u_pole: {u_pole}" );
101+
GUILayout.Label( $"Raw: {raw}" );
102+
}
103+
}
104+
}

Diff for: Tests/Runtime/AuxiliaryScripts/InvertedPendulumController.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using AGXUnity;
2+
using AGXUnity.IO.OpenPLX;
3+
using AGXUnity.Utils;
4+
using UnityEngine;
5+
6+
namespace AGXUnityTesting.Runtime.Aux
7+
{
8+
public class SimplerInvertedPendulum : ScriptComponent
9+
{
10+
OpenPLXSignals signal = null;
11+
12+
InputTarget motor_input = null;
13+
PDController pole;
14+
15+
// Start is called before the first frame update
16+
protected override bool Initialize()
17+
{
18+
signal = gameObject.GetInitializedComponent<OpenPLXSignals>();
19+
motor_input = signal.FindInputTarget( "PendulumScene.motor_input" );
20+
21+
if ( motor_input == null )
22+
Debug.LogWarning( "Could not find motor input" );
23+
24+
pole = new PDController( 5, 0.2f, 0 );
25+
26+
Simulation.Instance.StepCallbacks.SimulationPre += Pre;
27+
28+
hao = signal.FindOutputSource( "PendulumScene.hinge_angle_output" );
29+
havo = signal.FindOutputSource( "PendulumScene.hinge_angular_velocity_output" );
30+
31+
return true;
32+
}
33+
34+
OutputSource hao;
35+
OutputSource havo;
36+
37+
double ha = 0.0f;
38+
double hav = 0.0f;
39+
double u_pole = 0.0f;
40+
41+
private void Pre()
42+
{
43+
try {
44+
ha = hao.GetCachedValue<double>();
45+
hav = havo.GetCachedValue<double>();
46+
}
47+
catch {
48+
return;
49+
}
50+
51+
u_pole = pole.Observe( ha, hav );
52+
53+
motor_input.SendSignal( u_pole );
54+
}
55+
}
56+
}

Diff for: Tests/Runtime/AuxiliaryScripts/SimplerInvertedPendulum.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Tests/Runtime/OpenPLXOperatorTests.cs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using NUnit.Framework;
2+
3+
using Math = openplx.Math;
4+
5+
namespace AGXUnityTesting.Runtime
6+
{
7+
public class OperatorTests
8+
{
9+
[Test]
10+
public void Vec3PlusTest()
11+
{
12+
var v1 = Math.Vec3.from_xyz(1, 2, 3);
13+
var v2 = Math.Vec3.from_xyz(2, 3, 4);
14+
15+
var v3 = v1 + v2;
16+
17+
Assert.AreEqual( 3, v3.x() );
18+
Assert.AreEqual( 5, v3.y() );
19+
Assert.AreEqual( 7, v3.z() );
20+
}
21+
22+
[Test]
23+
public void Vec3DotTest()
24+
{
25+
var v1 = Math.Vec3.from_xyz(1, 2, 3);
26+
var v2 = Math.Vec3.from_xyz(2, 3, 4);
27+
28+
var dot = v1 * v2;
29+
30+
Assert.AreEqual( 20, dot );
31+
}
32+
33+
[Test]
34+
public void Vec3MulTest()
35+
{
36+
var v1 = Math.Vec3.from_xyz(1, 2, 3);
37+
38+
var v2 = v1 * 3;
39+
40+
Assert.AreEqual( 3, v2.x() );
41+
Assert.AreEqual( 6, v2.y() );
42+
Assert.AreEqual( 9, v2.z() );
43+
44+
var v3 = 3 * v1;
45+
46+
Assert.AreEqual( 3, v3.x() );
47+
Assert.AreEqual( 6, v3.y() );
48+
Assert.AreEqual( 9, v3.z() );
49+
}
50+
51+
[Test]
52+
public void Vec3MinusTest()
53+
{
54+
var v1 = Math.Vec3.from_xyz(1, 2, 3);
55+
var v2 = Math.Vec3.from_xyz(2, 3, 4);
56+
57+
var v3 = v1 - v2;
58+
59+
Assert.AreEqual( -1, v3.x() );
60+
Assert.AreEqual( -1, v3.y() );
61+
Assert.AreEqual( -1, v3.z() );
62+
}
63+
64+
[Test]
65+
public void Vec3DivTest()
66+
{
67+
var v1 = Math.Vec3.from_xyz(3, 6, 9);
68+
69+
var v2 = v1 / 3;
70+
71+
Assert.AreEqual( 1, v2.x() );
72+
Assert.AreEqual( 2, v2.y() );
73+
Assert.AreEqual( 3, v2.z() );
74+
}
75+
76+
public void QuatTest()
77+
{
78+
var q1 = Math.Quat.from_to(Math.Vec3.X_AXIS(), Math.Vec3.Z_AXIS());
79+
var q2 = Math.Quat.from_to(Math.Vec3.Z_AXIS(), Math.Vec3.Y_AXIS());
80+
81+
var q3 = q1 * q2;
82+
83+
var rotated = q3.rotate(Math.Vec3.X_AXIS());
84+
var tar = Math.Vec3.Y_AXIS();
85+
86+
Assert.AreEqual( tar.x(), rotated.x() );
87+
Assert.AreEqual( tar.y(), rotated.y() );
88+
Assert.AreEqual( tar.z(), rotated.z() );
89+
}
90+
}
91+
}

Diff for: Tests/Runtime/OpenPLXOperatorTests.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)