mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
150 lines
5.4 KiB
Python
150 lines
5.4 KiB
Python
|
|
import pytest
|
||
|
|
import math
|
||
|
|
|
||
|
|
from wpimath import Pose2d, Rotation2d, Translation2d, Transform2d
|
||
|
|
from wpimath.units import feetToMeters
|
||
|
|
|
||
|
|
|
||
|
|
def test_rotate_by():
|
||
|
|
x = 1
|
||
|
|
y = 2
|
||
|
|
initial = Pose2d(x, y, math.radians(45))
|
||
|
|
|
||
|
|
rotation = Rotation2d(math.radians(5))
|
||
|
|
rotated = initial.rotateBy(rotation)
|
||
|
|
|
||
|
|
# Translation is rotated by CCW rotation matrix
|
||
|
|
c = rotation.cos()
|
||
|
|
s = rotation.sin()
|
||
|
|
assert rotated.x == pytest.approx(c * x - s * y)
|
||
|
|
assert rotated.y == pytest.approx(s * x + c * y)
|
||
|
|
assert rotated.rotation().degrees() == pytest.approx(
|
||
|
|
initial.rotation().degrees() + rotation.degrees()
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def test_transform_by():
|
||
|
|
initial = Pose2d(x=1, y=2, rotation=Rotation2d.fromDegrees(45))
|
||
|
|
transform = Transform2d(Translation2d(x=5, y=0), Rotation2d.fromDegrees(5))
|
||
|
|
|
||
|
|
transformed = initial + transform
|
||
|
|
|
||
|
|
assert transformed.x == pytest.approx(1.0 + 5.0 / math.sqrt(2.0))
|
||
|
|
assert transformed.y == pytest.approx(2.0 + 5.0 / math.sqrt(2.0))
|
||
|
|
assert transformed.rotation().degrees() == pytest.approx(50.0)
|
||
|
|
|
||
|
|
|
||
|
|
def test_relative_to():
|
||
|
|
initial = Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(45))
|
||
|
|
final = Pose2d(x=5, y=5, rotation=Rotation2d.fromDegrees(45.0))
|
||
|
|
|
||
|
|
final_relative_to_initial = final.relativeTo(initial)
|
||
|
|
|
||
|
|
assert final_relative_to_initial.x == pytest.approx(5.0 * math.sqrt(2.0), abs=1e-9)
|
||
|
|
assert final_relative_to_initial.y == pytest.approx(0.0, abs=1e-9)
|
||
|
|
assert final_relative_to_initial.rotation().degrees() == pytest.approx(
|
||
|
|
0.0, abs=1e-9
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def test_rotate_around():
|
||
|
|
initial = Pose2d(x=5, y=0, rotation=Rotation2d.fromDegrees(0))
|
||
|
|
point = Translation2d(x=0, y=0)
|
||
|
|
|
||
|
|
rotated = initial.rotateAround(point, Rotation2d.fromDegrees(180))
|
||
|
|
|
||
|
|
assert rotated.x == pytest.approx(-5.0, abs=1e-9)
|
||
|
|
assert rotated.y == pytest.approx(0.0, abs=1e-9)
|
||
|
|
assert rotated.rotation().degrees() == pytest.approx(180.0, abs=1e-9)
|
||
|
|
|
||
|
|
|
||
|
|
def test_equality():
|
||
|
|
a = Pose2d(x=0, y=5, rotation=Rotation2d.fromDegrees(43))
|
||
|
|
b = Pose2d(x=0, y=5, rotation=Rotation2d.fromDegrees(43))
|
||
|
|
assert a == b
|
||
|
|
|
||
|
|
|
||
|
|
def test_inequality():
|
||
|
|
a = Pose2d(x=0, y=5, rotation=Rotation2d.fromDegrees(43))
|
||
|
|
b = Pose2d(x=0, y=feetToMeters(5), rotation=Rotation2d.fromDegrees(43))
|
||
|
|
assert a != b
|
||
|
|
|
||
|
|
|
||
|
|
def test_minus():
|
||
|
|
initial = Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(45))
|
||
|
|
final = Pose2d(x=5, y=5, rotation=Rotation2d.fromDegrees(45))
|
||
|
|
|
||
|
|
transform = final - initial
|
||
|
|
|
||
|
|
assert transform.x == pytest.approx(5.0 * math.sqrt(2.0), abs=1e-9)
|
||
|
|
assert transform.y == pytest.approx(0.0, abs=1e-9)
|
||
|
|
assert transform.rotation().degrees() == pytest.approx(0.0, abs=1e-9)
|
||
|
|
|
||
|
|
|
||
|
|
def test_nearest():
|
||
|
|
origin = Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(0))
|
||
|
|
|
||
|
|
pose1 = Pose2d(
|
||
|
|
Translation2d(distance=1.0, angle=Rotation2d.fromDegrees((45))),
|
||
|
|
Rotation2d.fromDegrees(0),
|
||
|
|
)
|
||
|
|
pose2 = Pose2d(
|
||
|
|
Translation2d(distance=2.0, angle=Rotation2d.fromDegrees((90))),
|
||
|
|
Rotation2d.fromDegrees(0),
|
||
|
|
)
|
||
|
|
pose3 = Pose2d(
|
||
|
|
Translation2d(distance=3.0, angle=Rotation2d.fromDegrees((135))),
|
||
|
|
Rotation2d.fromDegrees(0),
|
||
|
|
)
|
||
|
|
pose4 = Pose2d(
|
||
|
|
Translation2d(distance=4.0, angle=Rotation2d.fromDegrees((180))),
|
||
|
|
Rotation2d.fromDegrees(0),
|
||
|
|
)
|
||
|
|
pose5 = Pose2d(
|
||
|
|
Translation2d(distance=5.0, angle=Rotation2d.fromDegrees((270))),
|
||
|
|
Rotation2d.fromDegrees(0),
|
||
|
|
)
|
||
|
|
|
||
|
|
assert origin.nearest([pose5, pose3, pose4]).x == pytest.approx(pose3.x)
|
||
|
|
assert origin.nearest([pose5, pose3, pose4]).y == pytest.approx(pose3.y)
|
||
|
|
|
||
|
|
assert origin.nearest([pose1, pose2, pose3]).x == pytest.approx(pose1.x)
|
||
|
|
assert origin.nearest([pose1, pose2, pose3]).y == pytest.approx(pose1.y)
|
||
|
|
|
||
|
|
assert origin.nearest([pose4, pose2, pose3]).x == pytest.approx(pose2.x)
|
||
|
|
assert origin.nearest([pose4, pose2, pose3]).y == pytest.approx(pose2.y)
|
||
|
|
|
||
|
|
# Rotation component sort (when distance is the same)
|
||
|
|
# Use the same translation because using different angles at the same
|
||
|
|
# distance can cause rounding error.
|
||
|
|
translation = Translation2d(distance=1.0, angle=Rotation2d.fromDegrees(0))
|
||
|
|
|
||
|
|
pose_a = Pose2d(translation, Rotation2d.fromDegrees(0))
|
||
|
|
pose_b = Pose2d(translation, Rotation2d.fromDegrees(30))
|
||
|
|
pose_c = Pose2d(translation, Rotation2d.fromDegrees(120))
|
||
|
|
pose_d = Pose2d(translation, Rotation2d.fromDegrees(90))
|
||
|
|
pose_e = Pose2d(translation, Rotation2d.fromDegrees(-180))
|
||
|
|
|
||
|
|
assert Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(360)).nearest(
|
||
|
|
[pose_a, pose_b, pose_d]
|
||
|
|
).rotation().degrees() == pytest.approx(pose_a.rotation().degrees())
|
||
|
|
assert Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(-335)).nearest(
|
||
|
|
[pose_b, pose_c, pose_d]
|
||
|
|
).rotation().degrees() == pytest.approx(pose_b.rotation().degrees())
|
||
|
|
assert Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(-120)).nearest(
|
||
|
|
[pose_b, pose_c, pose_d]
|
||
|
|
).rotation().degrees() == pytest.approx(pose_c.rotation().degrees())
|
||
|
|
assert Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(85)).nearest(
|
||
|
|
[pose_a, pose_c, pose_d]
|
||
|
|
).rotation().degrees() == pytest.approx(pose_d.rotation().degrees())
|
||
|
|
assert Pose2d(x=0, y=0, rotation=Rotation2d.fromDegrees(170)).nearest(
|
||
|
|
[pose_a, pose_d, pose_e]
|
||
|
|
).rotation().degrees() == pytest.approx(pose_e.rotation().degrees())
|
||
|
|
|
||
|
|
|
||
|
|
def test_to_matrix():
|
||
|
|
before = Pose2d(x=1, y=2, rotation=Rotation2d.fromDegrees(20))
|
||
|
|
after = Pose2d.fromMatrix(before.toMatrix())
|
||
|
|
|
||
|
|
assert before == after
|