diff --git a/.circleci/config.yml b/.circleci/config.yml index dc5a5ed..1264928 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,8 +24,8 @@ jobs: . venv/bin/activate - run: apt-get update -y - run: apt-get install -y libcv-dev libopencv-photo-dev libopencv-contrib-dev libusb-1.0.0-dev - - run: pip3 install git+https://github.com/sourcebots/sb-vision@44356ec0fc4738508d22bf15137bb4429ba3410f - - run: pip3 install git+https://github.com/sourcebots/robotd@4ae124ba4d75f4be64a2b0bbc3f4abd37c94726f + - run: pip3 install git+https://github.com/sourcebots/sb-vision@f69d7190543b92c2067377f8ddd8f2607e9aa2ca + - run: pip3 install git+https://github.com/sourcebots/robotd@e0be841816d4c778e98498193f6fd7e3de35813d - run: pip3 install -r requirements.txt - run: pip3 install -r script/linting/requirements.txt - run: pip3 install -r script/typing/requirements.txt diff --git a/robot/markers.py b/robot/markers.py index a8306b8..a5f69ff 100644 --- a/robot/markers.py +++ b/robot/markers.py @@ -46,6 +46,43 @@ def rot_y_degrees(self) -> Degrees: return Degrees(math.degrees(self.rot_y_radians)) +_Orientation = NamedTuple('Orientation', ( + ('rot_x_radians', Radians), + ('rot_y_radians', Radians), + ('rot_z_radians', Radians), +)) + + +class Orientation(_Orientation): + """ + Represents the orientation in 3d space as rotations around x, y, and z axes. + + Rotations around the different axes can be thought of as follows: + - X rotation represents pitch. A good way to think of this is a person + leaning towards you (like they're doing a bow in respect of your amazing + robot) would be a positive X rotation. + - Y rotation represents yaw. A good way to think of this is a person + spinning clockwise on the spot would be a positive Y rotation. + - Z rotation represents roll. A good way to think of this is a person + doing a cart-wheel to the right would be a positive Z rotation. + """ + + @property + def rot_x_degrees(self) -> Degrees: + """Rotation about the x-axis in degrees.""" + return Degrees(math.degrees(self.rot_x_radians)) + + @property + def rot_y_degrees(self) -> Degrees: + """Rotation about the y-axis in degrees.""" + return Degrees(math.degrees(self.rot_y_radians)) + + @property + def rot_z_degrees(self) -> Degrees: + """Rotation about the z-axis in degrees.""" + return Degrees(math.degrees(self.rot_z_radians)) + + class PolarCoord: """ Deprecated: represents a point expressed in legacy "polar" co-ordinates. @@ -168,6 +205,21 @@ def spherical(self) -> SphericalCoord: """ return SphericalCoord(*self._raw_data['spherical']) + @property + def orientation(self) -> Orientation: + """ + The rotation of the marker in relative to the camera. + + Describes a rotation as angles about the x, y, and z axes, which + corresponds pitch, yaw, and roll of the marker respectively. The + angles are measured as an offset from a marker directly facing + the camera. + + The rotations are applied in the order of Z, Y, then X rotations. Each rotation + is applied relative to the marker. + """ + return Orientation(*self._raw_data['orientation']) + def __str__(self): bearing = self.spherical.rot_y_degrees return "".format( diff --git a/tests/test_camera.py b/tests/test_camera.py index 18c535c..14440be 100644 --- a/tests/test_camera.py +++ b/tests/test_camera.py @@ -3,7 +3,7 @@ import unittest from robot.camera import ResultList -from robot.markers import CartCoord, PolarCoord, SphericalCoord +from robot.markers import CartCoord, Orientation, PolarCoord, SphericalCoord from robot.robot import Robot from sb_vision.camera import FileCamera from tests.mock_robotd import MockRobotD @@ -80,6 +80,12 @@ def test_can_see_something(self): "Invalid spherical coordinates", ) + self.assertIsInstance( + token.orientation, + Orientation, + "Invalid orientation coordinates", + ) + self.assertIsInstance( token.polar, PolarCoord,