예제 #1
0
def main():
    while True:
        try:
            time.sleep(1)
            with get_android() as android:
                print('connected to Samsung GS3')

                while True:
                    raw_data = android.read()
                    if raw_data:
                        frame = AndroidFrame(raw_data)

                        odom_msg = Odometry()
                        odom_msg.latitude_deg = int(frame.lat_deg)
                        odom_msg.latitude_min = frame.lat_min
                        odom_msg.longitude_deg = int(frame.lon_deg)
                        odom_msg.longitude_min = frame.lon_min
                        odom_msg.bearing_deg = frame.azimuth_deg
                        odom_msg.speed = 0
                        lcm_.publish('/odometry', odom_msg.encode())

                        bearing_msg = Bearing()
                        bearing_msg.bearing = frame.azimuth_deg
                        lcm_.publish('/bearing', bearing_msg.encode())
                    else:
                        print('read timed out, retrying the connection')
                        break
        except usb.core.USBError:
            traceback.print_exception(*sys.exc_info())
            print('USBError occured, retrying...')
예제 #2
0
 def odometry_cb(self, channel, msg):
     m = Odometry.decode(msg)
     self.OdometryMsg.latitude_deg = m.latitude_deg
     self.OdometryMsg.latitude_min = m.latitude_min
     self.OdometryMsg.longitude_deg = m.longitude_deg
     self.OdometryMsg.longitude_min = m.longitude_min
     self.OdometryMsg.bearing_deg = m.bearing_deg
     self.OdometryMsg.speed = m.speed
예제 #3
0
 def odom_callback(self, channel, msg):
     odom = Odometry.decode(msg)
     if (time.time()*1000 - self.odom_millis) > \
             self.logConfig['rate_millis']['odom']:
         self.write([
             odom.latitude_deg, odom.latitude_min, odom.longitude_deg,
             odom.longitude_min, odom.bearing_deg, odom.speed
         ], 'odom')
         self.odom_millis = time.time() * 1000
예제 #4
0
def state2odom(state):
    '''
    Converts a numpy state represenation to an Odometry message

    @param ndarray(3,)/ndarray(5,): state
    @return Odometry: odometry message
    '''
    odom = Odometry()
    if state.shape[0] == 3:
        odom.latitude_deg, odom.latitude_min = decimal2min(state[0])
        odom.longitude_deg, odom.longitude_min = decimal2min(state[1])
        odom.bearing_deg = state[2]
        odom.speed = 0
        return odom
    elif state.shape[0] == 5:
        odom.latitude_deg, odom.latitude_min = decimal2min(state[0])
        odom.longitude_deg, odom.longitude_min = decimal2min(state[2])
        odom.bearing_deg = state[4]
        odom.speed = np.hypot(state[1], state[3])
        return odom
예제 #5
0
    def asOdom(self):
        '''
        Returns the current state estimate as an Odometry LCM object

        @return Odometry: state estimate in Odometry LCM format
        '''
        odom = Odometry()
        odom.latitude_deg = self.pos["lat_deg"]
        odom.latitude_min = self.pos["lat_min"]
        odom.longitude_deg = self.pos["long_deg"]
        odom.longitude_min = self.pos["long_min"]
        odom.bearing_deg = self.bearing_deg
        odom.speed = np.hypot(self.vel["north"], self.vel["east"])
        return odom
예제 #6
0
async def transmit_fake_odometry():
    while True:
        new_odom = Odometry()
        new_odom.latitude_deg = random.randint(42, 43)
        new_odom.longitude_deg = random.randint(-84, -82)
        new_odom.latitude_min = random.uniform(0, 60)
        new_odom.longitude_min = random.uniform(0, 60)
        new_odom.bearing_deg = random.uniform(0, 359)

        with await lock:
            lcm_.publish('/odom', new_odom.encode())

        print("Published new odometry")
        await asyncio.sleep(0.5)
예제 #7
0
    async def run(self):
        '''
        Runs main loop for filtering data and publishing state estimates
        '''
        while True:
            msg = None
            sensor_data = self._getFreshData()

            if self.filter is None:
                # Need position and bearing to initialize
                if sensor_data["pos"] is not None and sensor_data[
                        "bearing"] is not None:
                    msg = self._initFilter(sensor_data)
            else:
                if self.config["filter"] == "pipe":
                    # Need position and bearing to pipe
                    if sensor_data["pos"] is not None and sensor_data[
                            "bearing"] is not None:
                        msg = Odometry()
                        msg.latitude_deg, msg.latitude_min = decimal2min(
                            sensor_data["pos"][0])
                        msg.longitude_deg, msg.longitude_min = decimal2min(
                            sensor_data["pos"][1])
                        msg.bearing_deg = sensor_data["bearing"]
                        msg.speed = sensor_data["speed"] if sensor_data[
                            "speed"] is not None else 0.0

                elif self.config["filter"] == "ekf":
                    # Need accel or pos to do anything
                    if sensor_data["accel"] is not None and sensor_data[
                            "rpy"] is not None:
                        ground_accel = sensor_data["accel"][0] * np.abs(
                            np.cos(sensor_data["rpy"][1]))
                    else:
                        ground_accel = None
                    msg = self.filter.iterate(ground_accel,
                                              sensor_data["pos"],
                                              sensor_data["bearing"],
                                              rtk=self.gps.isRtk())
                    msg = state2odom(msg)

            if msg is not None:
                self.lcm.publish(self.config["odom_channel"], msg.encode())

                # DEBUG
                # print("[SensorFusion] Published odometry")
                # printOdom(msg)
                # print('\n')
            else:
                print("[SensorFusion] Unable to publish state.")

            await asyncio.sleep(self.config["dt"])
예제 #8
0
def main():
    lcm = aiolcm.AsyncLCM()
    serialPort = serial.Serial('/dev/ttyUSB0')
    serialPort.baudrate = 4800
    serialPort.bytesize = serial.EIGHTBITS
    serialPort.parity = serial.PARITY_NONE
    serialPort.stopbits = serial.STOPBITS_ONE

    while (True):
        oneByte = serialPort.read()
        if oneByte != b'$':
            continue

        fiveBytes = serialPort.read(5)
        if fiveBytes != b'GPRMC':
            continue

        odometry = Odometry()
        serialPort.read_until(b',')[:-1]
        serialPort.read_until(b',')[:-1]

        hasFix = serialPort.read_until(b',')[:-1]
        if hasFix != b'A':
            continue

        latitude = float(serialPort.read_until(b',')[:-1])
        serialPort.read_until(b',')[:-1]
        longitude = float(serialPort.read_until(b',')[:-1])
        serialPort.read_until(b',')[:-1]
        speed = float(serialPort.read_until(b',')[:-1])
        bearing = float(serialPort.read_until(b',')[:-1])

        odometry.latitude_deg = int(latitude / 100)
        odometry.longitude_deg = int(longitude / 100)
        odometry.latitude_min = latitude - (odometry.latitude_deg * 100)
        odometry.longitude_min = longitude - (odometry.longitude_deg * 100)
        odometry.bearing_deg = bearing
        odometry.speed = speed
        lcm.publish('/odometry', odometry.encode())
예제 #9
0
    def odomCallback(self, channel, msg):
        new_odom_msg = Odometry.decode(msg)
        lat = min2decimal(new_odom_msg.latitude_deg, new_odom_msg.latitude_min)
        lon = min2decimal(new_odom_msg.longitude_deg,
                          new_odom_msg.longitude_min)
        new_odom = np.array([[
            0.0,
            lat2meters(lat, ref_lat=self.ref_coords["lat"]),
            lon2meters(lon, lat, ref_lon=self.ref_coords["lon"]),
            new_odom_msg.bearing_deg, new_odom_msg.speed
        ]])

        if self.odom_history is None:
            self.odom_history = new_odom
        else:
            new_odom[0, 0] = self.odom_history[-1, 0] + self.sim_config["dt"]
            self.odom_history = np.vstack([self.odom_history, new_odom])
예제 #10
0
    def _initFilter(self, sensor_data):
        '''
        Constructs filter depending on filter type in config

        @return Odometry: odometry LCM message to broadcast
        '''
        if self.config["filter"] == "ekf":
            config_path = getenv('MROVER_CONFIG')
            config_path += "/config_filter/ekf_config.json"
            with open(config_path, "r") as config:
                ekf_config = json.load(config)

            if self.config["track_vel"]:
                self.filter = EkfFusionVel(
                    ekf_config["vel"],
                    sensor_data["pos"],
                    0.0,
                    sensor_data["bearing"],
                    self.config["dt"],
                    ref_lat=self.config["ref_coords"]["lat"],
                    ref_lon=self.config["ref_coords"]["lon"],
                    rtk=self.gps.isRtk(),
                    filter_rtk=self.config["filter_rtk"])
            else:
                self.filter = EkfFusionNoVel(
                    ekf_config["no_vel"],
                    sensor_data["pos"],
                    sensor_data["bearing"],
                    self.config["dt"],
                    ref_lat=self.config["ref_coords"]["lat"],
                    ref_lon=self.config["ref_coords"]["lon"],
                    rtk=self.gps.isRtk(),
                    filter_rtk=self.config["filter_rtk"])

        elif self.config["filter"] == "pipe":
            self.filter = "pipe"
        else:
            raise ValueError("Invalid filter type!")

        msg = Odometry()
        msg.latitude_deg, msg.latitude_min = decimal2min(sensor_data["pos"][0])
        msg.longitude_deg, msg.longitude_min = decimal2min(
            sensor_data["pos"][1])
        msg.bearing_deg = sensor_data["bearing"]
        msg.speed = sensor_data["speed"] if sensor_data[
            "speed"] is not None else 0.0
        return msg
예제 #11
0
    def __init__(self):  # other args if ya want em
        # all initially defined variables should be here
        # while not technically globals, this is basically where they are
        # defined for the sim, since the entire instance is the SimMetaClass

        # below: class list, one class for each message type
        # published or recieved. instantiate them at the bottom
        # of this message definition block
        # use the provided imported classes and dump these later
        # you still need to set all the defaults

        self.AutonStateMsg = AutonState()
        self.AutonStateMsg.is_auton = False

        self.CourseMsg = Course()
        self.CourseMsg.num_waypoints = 0
        self.CourseMsg.hash = 0
        self.CourseMsg.waypoints = []

        self.GPSMsg = GPS()
        self.GPSMsg.latitude_deg = 39
        self.GPSMsg.latitude_min = 0
        self.GPSMsg.longitude_deg = -110
        self.GPSMsg.longitude_min = 0
        self.GPSMsg.bearing_deg = 0
        self.GPSMsg.speed = -999  # this value is never used
        # so it's being set to a dummy value. DO NOT USE IT

        self.JoystickMsg = Joystick()
        self.JoystickMsg.forward_back = 0
        self.JoystickMsg.left_right = 0
        self.JoystickMsg.dampen = 0
        self.JoystickMsg.kill = False
        self.JoystickMsg.restart = False

        self.NavStatusMsg = NavStatus()
        self.NavStatusMsg.nav_state = 0
        self.NavStatusMsg.nav_state_name = ""
        self.NavStatusMsg.completed_wps = 0
        self.NavStatusMsg.missed_wps = 0
        self.NavStatusMsg.total_wps = 0
        self.NavStatusMsg.found_tbs = 0
        self.NavStatusMsg.total_tbs = 0

        self.ObstacleMsg = Obstacle()
        self.ObstacleMsg.detected = False
        self.ObstacleMsg.bearing = 0.0
        self.ObstacleMsg.distance = 0.0

        self.ObstaclesMsg = Obstacles()
        self.ObstaclesMsg.num_obstacles = 0
        self.ObstaclesMsg.hash = 0
        self.ObstaclesMsg.obstacles = []

        self.OdometryMsg = Odometry()
        self.OdometryMsg.latitude_deg = 0
        self.OdometryMsg.latitude_min = 0
        self.OdometryMsg.longitude_deg = 0
        self.OdometryMsg.longitude_min = 0
        self.OdometryMsg.bearing_deg = 0
        self.OdometryMsg.speed = 0

        self.TargetMsg = Target()
        self.TargetMsg.distance = 0
        self.TargetMsg.bearing = 0

        self.TargetListMsg = TargetList()
        self.TargetListMsg.targetList = [Target(), Target()]

        self.WaypointMsg = Waypoint()
        self.WaypointMsg.search = False
        self.WaypointMsg.gate = False
        self.WaypointMsg.odom = Odometry()
예제 #12
0
class SimulatorMetaClass:

    # variables defined here are common to all classes
    # ideally it shouldn't matter bc we only ever need one instance
    # this is bad practice imho, just defined vars in the block below
    def __init__(self):  # other args if ya want em
        # all initially defined variables should be here
        # while not technically globals, this is basically where they are
        # defined for the sim, since the entire instance is the SimMetaClass

        # below: class list, one class for each message type
        # published or recieved. instantiate them at the bottom
        # of this message definition block
        # use the provided imported classes and dump these later
        # you still need to set all the defaults

        self.AutonStateMsg = AutonState()
        self.AutonStateMsg.is_auton = False

        self.CourseMsg = Course()
        self.CourseMsg.num_waypoints = 0
        self.CourseMsg.hash = 0
        self.CourseMsg.waypoints = []

        self.GPSMsg = GPS()
        self.GPSMsg.latitude_deg = 39
        self.GPSMsg.latitude_min = 0
        self.GPSMsg.longitude_deg = -110
        self.GPSMsg.longitude_min = 0
        self.GPSMsg.bearing_deg = 0
        self.GPSMsg.speed = -999  # this value is never used
        # so it's being set to a dummy value. DO NOT USE IT

        self.JoystickMsg = Joystick()
        self.JoystickMsg.forward_back = 0
        self.JoystickMsg.left_right = 0
        self.JoystickMsg.dampen = 0
        self.JoystickMsg.kill = False
        self.JoystickMsg.restart = False

        self.NavStatusMsg = NavStatus()
        self.NavStatusMsg.nav_state = 0
        self.NavStatusMsg.nav_state_name = ""
        self.NavStatusMsg.completed_wps = 0
        self.NavStatusMsg.missed_wps = 0
        self.NavStatusMsg.total_wps = 0
        self.NavStatusMsg.found_tbs = 0
        self.NavStatusMsg.total_tbs = 0

        self.ObstacleMsg = Obstacle()
        self.ObstacleMsg.detected = False
        self.ObstacleMsg.bearing = 0.0
        self.ObstacleMsg.distance = 0.0

        self.ObstaclesMsg = Obstacles()
        self.ObstaclesMsg.num_obstacles = 0
        self.ObstaclesMsg.hash = 0
        self.ObstaclesMsg.obstacles = []

        self.OdometryMsg = Odometry()
        self.OdometryMsg.latitude_deg = 0
        self.OdometryMsg.latitude_min = 0
        self.OdometryMsg.longitude_deg = 0
        self.OdometryMsg.longitude_min = 0
        self.OdometryMsg.bearing_deg = 0
        self.OdometryMsg.speed = 0

        self.TargetMsg = Target()
        self.TargetMsg.distance = 0
        self.TargetMsg.bearing = 0

        self.TargetListMsg = TargetList()
        self.TargetListMsg.targetList = [Target(), Target()]

        self.WaypointMsg = Waypoint()
        self.WaypointMsg.search = False
        self.WaypointMsg.gate = False
        self.WaypointMsg.odom = Odometry()

    # definitions for message processing are below, with callbacks (cb)
    # at the top and publishing at the bottom
    # in this setup, camelCasing denotes a class instance
    # while under_scored_variables indicate a variable within the class
    # to avoid confusion

    def autonstate_cb(self, channel, msg):
        m = AutonState.decode(msg)
        self.AutonStateMsg.is_auton = m.is_auton

    def course_cb(self, channel, msg):
        m = Course.decode(msg)
        self.CourseMsg.num_waypoints = m.num_waypoints
        self.CourseMsg.hash = m.hash
        self.CourseMsg.waypoints = m.waypoints

    def gps_cb(self, channel, msg):
        m = GPS.decode(msg)
        self.GPSMsg.latitude_deg = m.latitude_deg
        self.GPSMsg.latitude_min = m.latitude_min
        self.GPSMsg.longitude_deg = m.longitude_deg
        self.GPSMsg.longitude_min = m.longitude_min
        self.GPSMsg.bearing_deg = m.bearing_deg
        self.GPSMsg.speed = m.speed

    def joystick_cb(self, channel, msg):
        m = Joystick.decode(msg)
        self.JoystickMsg.forward_back = m.forward_back
        self.JoystickMsg.left_right = m.left_right
        self.JoystickMsg.dampen = m.dampen
        # 1-dampen/2
        self.JoystickMsg.kill = m.kill
        self.JoystickMsg.restart = m.restart

    def navstatus_cb(self, channel, msg):
        m = NavStatus.decode(msg)
        self.NavStatusMsg.nav_state = m.nav_state
        self.NavStatusMsg.nav_state_name = m.nav_state_name
        self.NavStatusMsg.completed_wps = m.completed_wps
        self.NavStatusMsg.missed_wps = m.missed_wps
        self.NavStatusMsg.total_wps = m.total_wps
        self.NavStatusMsg.found_tbs = m.found_tbs
        self.NavStatusMsg.total_tbs = m.total_tbs

    def obstacle_cb(self, channel, msg):
        m = Obstacle.decode(msg)
        self.ObstacleMsg.detected = m.detected
        self.ObstacleMsg.bearing = m.bearing
        self.ObstacleMsg.distance = m.distance

    def obstacles_cb(self, channel, msg):
        m = Obstacles.decode(msg)
        self.ObstaclesMsg.num_obstacles = m.num_obstacles
        self.ObstaclesMsg.hash = m.hash
        self.ObstaclesMsg.obstacles = m.obstacles

    def odometry_cb(self, channel, msg):
        m = Odometry.decode(msg)
        self.OdometryMsg.latitude_deg = m.latitude_deg
        self.OdometryMsg.latitude_min = m.latitude_min
        self.OdometryMsg.longitude_deg = m.longitude_deg
        self.OdometryMsg.longitude_min = m.longitude_min
        self.OdometryMsg.bearing_deg = m.bearing_deg
        self.OdometryMsg.speed = m.speed

    def target_cb(self, channel, msg):
        m = Target.decode(msg)
        self.TargetMsg.distance = m.distance
        self.TargetMsg.bearing = m.bearing

    def targetlist_cb(self, channel, msg):
        m = TargetList.decode(msg)
        self.TargetListMsg.targetList = m.targetList

    def waypoint_cb(self, channel, msg):
        m = Waypoint.decode(msg)
        self.WaypointMsg.search = m.search
        self.WaypointMsg.gate = m.gate
        self.WaypointMsg.odom = m.odom

    async def publish_autonstate(self, lcm):
        while True:
            lcm.publish("/autonstate", self.AutonStateMsg.encode())
            await asyncio.sleep(1)

    async def publish_course(self, lcm):
        while True:
            lcm.publish("/course", self.CourseMsg.encode())
            await asyncio.sleep(1)

    async def publish_gps(self, lcm):
        while True:
            lcm.publish("/gps", self.GPSMsg.encode())
            await asyncio.sleep(1)

    async def publish_joystick(self, lcm):
        while True:
            lcm.publish("/joystick", self.JoystickMsg.encode())
            await asyncio.sleep(1)

    async def publish_navstatus(self, lcm):
        while True:
            lcm.publish("/navstatus", self.NavStatusMsg.encode())
            await asyncio.sleep(1)

    async def publish_obstacle(self, lcm):
        while True:
            lcm.publish("/obstacle", self.ObstacleMsg.encode())
            await asyncio.sleep(1)

    async def publish_obstacles(self, lcm):
        while True:
            lcm.publish("/obstacles", self.ObstaclesMsg.encode())
            await asyncio.sleep(1)

    async def publish_odometry(self, lcm):
        while True:
            lcm.publish("/odometry", self.OdometryMsg.encode())
            await asyncio.sleep(1)

    async def publish_target(self, lcm):
        while True:
            lcm.publish("/target", self.TargetMsg.encode())
            await asyncio.sleep(1)

    async def publish_targetlist(self, lcm):
        while True:
            lcm.publish("/targetlist", self.TargetListMsg.encode())
            await asyncio.sleep(1)

    async def publish_waypoint(self, lcm):
        while True:
            lcm.publish("/waypoint", self.WaypointMsg.encode())
            await asyncio.sleep(1)

    # callback function: takes in variable from LCM, sets values locally

    # SimObject definitions are below
    # SimObj is the abstract base class that contains properties
    # common to all objects. define additional simulator objects
    # as if you would the Rover class, including proper
    # superclass init

    # identical to the GPS message, minus speed, bc it's a useful
    # object to have internally

    class AutonState:
        def __init__(self, is_auton):
            self.is_auton = is_auton

    class Course:
        def __init__(self, num_waypoints, hash, waypoints):
            self.num_waypoints = num_waypoints
            self.hash = hash
            self.waypoints = waypoints

    class GPS:
        def __init__(self, latitude_deg, latitude_min, longitude_deg,
                     longitude_min, bearing_deg, speed):
            self.latitude_deg = latitude_deg
            self.latitude_min = latitude_min
            self.longitude_deg = longitude_deg
            self.longitude_deg = longitude_min
            self.bearing = bearing_deg
            self.speed = speed

    class Joystick:
        def __init__(self, forward_back, left_right, dampen, kill, restart):
            self.forward_back = forward_back
            self.left_right = left_right
            self.dampen = dampen
            self.kill = kill
            self.restart = restart

    class NavStatus:
        def __init__(self, nav_state, nav_state_name, completed_wps,
                     missed_wps, total_wps, found_tbs, total_tbs):
            self.nav_state = nav_state
            self.nav_state_name = nav_state_name
            self.completed_wps = completed_wps
            self.missed_wps = missed_wps
            self.total_wps = total_wps
            self.found_tbs = found_tbs
            self.total_tbs = total_tbs

    class Obstacle:
        def __init__(self, detected, bearing, distance):
            self.detected = detected
            self.bearing = bearing
            self.distance = distance

    class Obstacles:
        def __init__(self, num_obstacles, hash, obstacles):
            self.num_obstacles = num_obstacles
            self.hash = hash
            self.obstacles = obstacles
            # pull exact coordinates from GPS
            self.lat_deg = GPS.latitude_deg
            self.lat_min = GPS.latitude_min
            self.lon_deg = GPS.longitude_deg
            self.lon_min = GPS.longitude_min
            self.bearing = GPS.bearing_deg

    class Odometry:
        def __init__(self, latitude_deg, latitude_min, longitude_deg,
                     longitude_min, bearing_deg, speed):
            self.latitude_deg = latitude_deg
            self.latitude_min = latitude_min
            self.longitude_deg = longitude_deg
            self.longitude_min = longitude_min
            self.bearing = bearing_deg
            self.speed = speed

    class Target:
        def __init__(self, distance, bearing):
            self.distance = distance
            self.bearing = bearing

    class TargetList:
        def __init__(self, targetList):
            self.targetList = targetList

    class Waypoint:
        def __init__(self, search, gate, odom):
            self.search = search
            self.gate = gate
            self.odom = odom

    # parent class of sim objects. Has all properties common to all
    # objects

    class SimObj(ABC):
        # define initial location and other properties
        def __init__(self, GPS):
            self.lat_deg = GPS.latitude_deg
            self.lat_min = GPS.latitude_min
            self.lon_deg = GPS.longitude_deg
            self.lon_min = GPS.longitude_min
            self.bearing = GPS.bearing_deg
            self.shape = 0  # need to create a seed system?

        # any methods common to all classes should be defined
        def get_coords(self):
            return [self.lat_deg, self.lat_min, self.lon_deg, self.lon_min]

        def get_bearing(self):
            return self.bearing

        # here is an abstract method, may be useful
        # @abstractmethod
        # def sample_abs_method(self):
        #     pass
    class Field(SimObj):
        def __init__(self, GPS, radius=2):  # other properties
            super().__init__(GPS)
            self.radius = radius  # in degrees, if not specified
            # radius is 2

    class Rover(SimObj):
        def __init__(self, GPS, speed_trans=1, speed_rot=1):
            super().__init__(GPS)
            self.fov = 120  # units of degrees,
            # 120 if not specified
            self.cv_thresh = 5
            self.speed_translational = speed_trans
            # speed multiplier, 1 if not specified
            self.speed_rotational = speed_rot

    """
예제 #13
0
lcm_ = aiolcm.AsyncLCM()
odom_port = os.environ.get('MROVER_ODOM_PORT', '/dev/ttyUSB0')
gps_port = os.environ.get('MROVER_GPS_PORT', '/dev/ttyUSB1')


mutex = threading.Lock()
condition = threading.Condition(mutex)
start_condition = threading.Barrier(3)

imu_ready = False
gps_ready = False
sat_count_ready = False
changed = False
gps_valid = False
msg = Odometry()
num_satellites = 0


class OdomFrame:
    def __init__(self, buf):
        data = struct.unpack('<fffififi??', buf)
        self.roll = data[0]
        self.pitch = data[1]
        self.bearing = data[2]
        self.lat_deg = data[3]
        self.lat_min = data[4]
        self.lon_deg = data[5]
        self.lon_min = data[6]
        self.num_sats = data[7]
        self.gps_read = data[8]