UML Diagram

Orbital - Page 2.png

Rough Notes

IMG_0034.PNG

SecondaryPayload::getDirection()

Python Code

from math import *

class XY:
    """
    Useful class for holding pairs of floats
    """

    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def __truediv__(self, other):
        return XY(self.x / other.x, self.y / other.y)

    def __sub__(self, other):
        if isinstance(other, XYZ):
            return XYZ(self.x - other.x, self.y - other.y, -other.z)

class XYZ:
    """
    Useful class for holding triplets of floats
    """
    
    def __init__(self, x: float, y: float, z: float):
        self.x = x
        self.y = y
        self.z = z

    def __sub__(self, other):
        if isinstance(other, XYZ):
            return XYZ(self.x - other.x, self.y - other.y, self.z - other.z)

    def __str__(self):
        return "({}, {}, {})".format(self.x, self.y, self.z)

class SecondaryPayloadCamera:
    screen_resolution: XY = XY(2000.0, 2000.0) # the number of pixels in each direction
    screen_size: XY = XY(1000.0, 1000.0) # the size of the screen
    relative_position: XYZ = XYZ(500.0, 500.0, 500.0) # the position the laser is pointing at, relative to the camera
    relative_orientation: XYZ = XYZ(0, 0, 0) # the orientation of the camera, relative to the satellite

class SecondaryPayload:
    # Public interface
    def get_direction(self, c1: XY, c2: XY) -> XYZ:
        """
        Gets the orientation delta required to move the bright spot from c1 to c2
        :param c1: the current coordinates of the bright spot in the camera
        :param c2: the target coordinates of the bright spot in the camera
        :return:
        """
        return self.get_orientation(c2) - self.get_orientation(c1)

    # Private helper functions
    def calculate_angle(self, opp: float, adj: float) -> float:
        """
        Calculates an angle using arctan, given the opposite and adjacent sides of the triangle
        :param opp: the length of the side opposite of the angle
        :param adj: the length of the side adjacent to the angle
        :return: the angle
        """
        return atan(opp/adj)

    def get_relative_angles(self, c: XY) -> XY:
        """
        Returns the relative x and y incident angles of the beam relative to the perpendicular line from the center
        :param c: the coordinates of the bright spot
        :return: the angle
        """
        adj: float = SecondaryPayloadCamera.relative_position.z
        factor: XY = SecondaryPayloadCamera.screen_size / SecondaryPayloadCamera.screen_resolution
        return XY(
            self.calculate_angle(c.x * factor.x, adj),
            self.calculate_angle(c.y * factor.y, adj)
        )

    def get_orientation(self, c: XY) -> XYZ:
        """
        Returns the current orientation of the satellite
        :param c: the coordinates of the bright spot
        :return: the orientation
        """
        return self.get_relative_angles(c) - SecondaryPayloadCamera.relative_orientation

o_in_radians = SecondaryPayload().get_direction(XY(-1000, 50), XY(0, 0))
o_in_degrees = XYZ(degrees(o_in_radians.x), degrees(o_in_radians.y), degrees(o_in_radians.z))

print(o_in_degrees)