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