示例#1
0
def correct_and_pos_fix(processed_measurements: List[GNSSMeasurement],
                        dog: AstroDog):
    # pos fix needs more than 5 processed_measurements
    pos_fix = calc_pos_fix(processed_measurements)

    if len(pos_fix) == 0:
        return [], []
    est_pos = pos_fix[0][:3]
    corrected = correct_measurements(processed_measurements, est_pos, dog)
    return calc_pos_fix(corrected), corrected
示例#2
0
    def process_ublox_msg(self, ublox_msg, ublox_mono_time: int):
        if ublox_msg.which == 'measurementReport':
            report = ublox_msg.measurementReport
            new_meas = read_raw_ublox(report)
            measurements = process_measurements(new_meas, self.astro_dog)
            pos_fix = calc_pos_fix(measurements, min_measurements=4)
            # To get a position fix a minimum of 5 measurements are needed.
            # Each report can contain less and some measurements can't be processed.
            corrected_measurements = []
            if len(pos_fix) > 0 and linalg.norm(pos_fix[1]) < 100:
                corrected_measurements = correct_measurements(
                    measurements, pos_fix[0][:3], self.astro_dog)

            t = ublox_mono_time * 1e-9
            self.update_localizer(pos_fix, t, corrected_measurements)
            localizer_valid = self.localizer_valid(t)
            ecef_pos = self.gnss_kf.x[GStates.ECEF_POS].tolist()
            ecef_vel = self.gnss_kf.x[GStates.ECEF_VELOCITY].tolist()

            pos_std = float(np.linalg.norm(self.gnss_kf.P[GStates.ECEF_POS]))
            vel_std = float(
                np.linalg.norm(self.gnss_kf.P[GStates.ECEF_VELOCITY]))

            bearing_deg, bearing_std = get_bearing_from_gnss(
                ecef_pos, ecef_vel, vel_std)

            meas_msgs = [
                create_measurement_msg(m) for m in corrected_measurements
            ]

            dat = messaging.new_message("gnssMeasurements")
            measurement_msg = log.GnssMeasurements.Measurement.new_message
            dat.gnssMeasurements = {
                "positionECEF":
                measurement_msg(value=ecef_pos,
                                std=pos_std,
                                valid=localizer_valid),
                "velocityECEF":
                measurement_msg(value=ecef_vel,
                                std=vel_std,
                                valid=localizer_valid),
                "bearingDeg":
                measurement_msg(value=[bearing_deg],
                                std=bearing_std,
                                valid=localizer_valid),
                "ubloxMonoTime":
                ublox_mono_time,
                "correctedMeasurements":
                meas_msgs
            }
            return dat
        elif ublox_msg.which == 'ephemeris':
            ephem = convert_ublox_ephem(ublox_msg.ephemeris)
            self.astro_dog.add_ephem(ephem, self.astro_dog.orbits)
示例#3
0
    def test_station_position(self):
        print(
            'WARNING THIS TAKE CAN TAKE A VERY LONG TIME THE FIRST RUN TO DOWNLOAD'
        )
        dog = AstroDog()
        # Building this cache takes forever just copy it from repo
        cache_directory = '/tmp/gnss/cors_coord/'
        try:
            os.mkdir('/tmp/gnss/')
        except OSError:
            pass

        try:
            os.mkdir(cache_directory)
        except OSError:
            pass

        examples_directory = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), '../examples')
        copyfile(os.path.join(examples_directory, 'cors_station_positions'),
                 os.path.join(cache_directory, 'cors_station_positions'))

        station_name = 'sc01'
        time = GPSTime.from_datetime(datetime(2020, 1, 11))
        slac_rinex_obs_file = download_cors_station(time, station_name,
                                                    dog.cache_dir)
        obs_data = RINEXFile(slac_rinex_obs_file)
        sc01_exact_position = get_station_position('sc01')

        rinex_meas_grouped = raw.read_rinex_obs(obs_data)
        rinex_corr_grouped = []
        for meas in tqdm(rinex_meas_grouped):
            proc = raw.process_measurements(meas, dog=dog)
            corr = raw.correct_measurements(meas, sc01_exact_position, dog=dog)
            rinex_corr_grouped.append(corr)

        # Using laika's WLS solver we can now calculate position
        # fixes for every epoch (every 30s) over 24h.
        ests = []
        for corr in tqdm(rinex_corr_grouped[:]):
            fix, _ = raw.calc_pos_fix(corr)
            ests.append(fix)
        ests = np.array(ests)

        mean_fix = np.mean(ests[:, :3], axis=0)
        np.testing.assert_allclose(mean_fix,
                                   sc01_exact_position,
                                   rtol=0,
                                   atol=1)
示例#4
0
  def process_ublox_msg(self, ublox_msg, ublox_mono_time: int, block=False):
    if ublox_msg.which == 'measurementReport':
      t = ublox_mono_time * 1e-9
      report = ublox_msg.measurementReport
      if report.gpsWeek > 0:
        latest_msg_t = GPSTime(report.gpsWeek, report.rcvTow)
        self.fetch_orbits(latest_msg_t + SECS_IN_MIN, block)

      new_meas = read_raw_ublox(report)
      processed_measurements = process_measurements(new_meas, self.astro_dog)

      if self.last_pos_fix_t is None or abs(self.last_pos_fix_t - t) >= 2:
        min_measurements = 5 if any(p.constellation_id == ConstellationId.GLONASS for p in processed_measurements) else 4
        pos_fix, pos_fix_residual = calc_pos_fix_gauss_newton(processed_measurements, self.posfix_functions, min_measurements=min_measurements)
        if len(pos_fix) > 0:
          self.last_pos_fix = pos_fix[:3]
          self.last_pos_residual = pos_fix_residual
          self.last_pos_fix_t = t

      corrected_measurements = correct_measurements(processed_measurements, self.last_pos_fix, self.astro_dog) if self.last_pos_fix_t is not None else []

      self.update_localizer(self.last_pos_fix, t, corrected_measurements)
      kf_valid = all(self.kf_valid(t))
      ecef_pos = self.gnss_kf.x[GStates.ECEF_POS].tolist()
      ecef_vel = self.gnss_kf.x[GStates.ECEF_VELOCITY].tolist()

      pos_std = np.sqrt(abs(self.gnss_kf.P[GStates.ECEF_POS].diagonal())).tolist()
      vel_std = np.sqrt(abs(self.gnss_kf.P[GStates.ECEF_VELOCITY].diagonal())).tolist()

      meas_msgs = [create_measurement_msg(m) for m in corrected_measurements]
      dat = messaging.new_message("gnssMeasurements")
      measurement_msg = log.LiveLocationKalman.Measurement.new_message
      dat.gnssMeasurements = {
        "gpsWeek": report.gpsWeek,
        "gpsTimeOfWeek": report.rcvTow,
        "positionECEF": measurement_msg(value=ecef_pos, std=pos_std, valid=kf_valid),
        "velocityECEF": measurement_msg(value=ecef_vel, std=vel_std, valid=kf_valid),
        "positionFixECEF": measurement_msg(value=self.last_pos_fix, std=self.last_pos_residual, valid=self.last_pos_fix_t == t),
        "ubloxMonoTime": ublox_mono_time,
        "correctedMeasurements": meas_msgs
      }
      return dat
    elif ublox_msg.which == 'ephemeris':
      ephem = convert_ublox_ephem(ublox_msg.ephemeris)
      self.astro_dog.add_navs({ephem.prn: [ephem]})
      self.cache_ephemeris(t=ephem.epoch)
示例#5
0
  def process_ublox_msg(self, ublox_msg, ublox_mono_time: int, block=False):
    if ublox_msg.which == 'measurementReport':
      t = ublox_mono_time * 1e-9
      report = ublox_msg.measurementReport
      if report.gpsWeek > 0:
        self.got_first_ublox_msg = True
        latest_msg_t = GPSTime(report.gpsWeek, report.rcvTow)
        if self.auto_fetch_orbits:
          self.fetch_orbits(latest_msg_t, block)

      new_meas = read_raw_ublox(report)
      # Filter measurements with unexpected pseudoranges for GPS and GLONASS satellites
      new_meas = [m for m in new_meas if 1e7 < m.observables['C1C'] < 3e7]

      processed_measurements = process_measurements(new_meas, self.astro_dog)

      est_pos = self.get_est_pos(t, processed_measurements)

      corrected_measurements = correct_measurements(processed_measurements, est_pos, self.astro_dog) if len(est_pos) > 0 else []

      self.update_localizer(est_pos, t, corrected_measurements)
      kf_valid = all(self.kf_valid(t))
      ecef_pos = self.gnss_kf.x[GStates.ECEF_POS].tolist()
      ecef_vel = self.gnss_kf.x[GStates.ECEF_VELOCITY].tolist()

      pos_std = np.sqrt(abs(self.gnss_kf.P[GStates.ECEF_POS].diagonal())).tolist()
      vel_std = np.sqrt(abs(self.gnss_kf.P[GStates.ECEF_VELOCITY].diagonal())).tolist()

      meas_msgs = [create_measurement_msg(m) for m in corrected_measurements]
      dat = messaging.new_message("gnssMeasurements")
      measurement_msg = log.LiveLocationKalman.Measurement.new_message
      dat.gnssMeasurements = {
        "gpsWeek": report.gpsWeek,
        "gpsTimeOfWeek": report.rcvTow,
        "positionECEF": measurement_msg(value=ecef_pos, std=pos_std, valid=kf_valid),
        "velocityECEF": measurement_msg(value=ecef_vel, std=vel_std, valid=kf_valid),
        "positionFixECEF": measurement_msg(value=self.last_pos_fix, std=self.last_pos_residual, valid=self.last_pos_fix_t == t),
        "ubloxMonoTime": ublox_mono_time,
        "correctedMeasurements": meas_msgs
      }
      return dat
    elif ublox_msg.which == 'ephemeris':
      ephem = convert_ublox_ephem(ublox_msg.ephemeris)
      self.astro_dog.add_navs({ephem.prn: [ephem]})
      self.cache_ephemeris(t=ephem.epoch)
示例#6
0
 def handle_ublox_gnss(self, log, current_time):
     if hasattr(log.ubloxGnss, 'measurementReport'):
         self.raw_gnss_counter += 1
         if True or self.raw_gnss_counter % 3 == 0:
             processed_raw = gnss.process_measurements(gnss.read_raw_ublox(
                 log.ubloxGnss.measurementReport),
                                                       dog=self.dog)
             corrected_raw = gnss.correct_measurements(processed_raw,
                                                       self.kf.x[:3],
                                                       dog=self.dog)
             corrected_raw = np.array([c.as_array()
                                       for c in corrected_raw]).reshape(
                                           (-1, 14))
             self.update_kalman(current_time,
                                ObservationKind.PSEUDORANGE_GPS,
                                corrected_raw)
             self.update_kalman(current_time,
                                ObservationKind.PSEUDORANGE_RATE_GPS,
                                corrected_raw)
示例#7
0
    def run_station_position(self, length):
        dog = AstroDog()
        # Building this cache takes forever just copy it from repo
        cache_directory = '/tmp/gnss/cors_coord/'
        os.makedirs('/tmp/gnss/', exist_ok=True)
        os.makedirs(cache_directory, exist_ok=True)

        examples_directory = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), '../examples')
        copyfile(os.path.join(examples_directory, 'cors_station_positions'),
                 os.path.join(cache_directory, 'cors_station_positions'))

        station_name = 'sc01'
        time = GPSTime.from_datetime(datetime(2020, 1, 11))
        slac_rinex_obs_file = download_cors_station(time, station_name,
                                                    dog.cache_dir)
        obs_data = RINEXFile(slac_rinex_obs_file)
        sc01_exact_position = get_station_position('sc01')

        rinex_meas_grouped = raw.read_rinex_obs(obs_data)
        # Select small sample out of ~2800 to reduce computation time
        rinex_meas_grouped = rinex_meas_grouped[:length]
        rinex_corr_grouped = []
        for meas in tqdm(rinex_meas_grouped):
            proc = raw.process_measurements(meas, dog=dog)
            corr = raw.correct_measurements(proc, sc01_exact_position, dog=dog)
            rinex_corr_grouped.append(corr)

        # Using laika's WLS solver we can now calculate position
        # fixes for every epoch (every 30s) over 24h.
        ests = []
        for corr in tqdm(rinex_corr_grouped):
            ret = raw.calc_pos_fix(corr)
            if len(ret) > 0:
                fix, _ = ret
                ests.append(fix)
        ests = np.array(ests)

        mean_fix = np.mean(ests[:, :3], axis=0)
        np.testing.assert_allclose(mean_fix,
                                   sc01_exact_position,
                                   rtol=0,
                                   atol=1)
    def test_get_fix(self):
        dog = AstroDog()
        position_fix_found = 0
        count_processed_measurements = 0
        count_corrected_measurements = 0
        position_fix_found_after_correcting = 0

        pos_ests = []
        for measurements in self.gnss_measurements[:self.
                                                   NUM_TEST_PROCESS_MEAS]:
            processed_meas = process_measurements(measurements, dog)
            count_processed_measurements += len(processed_meas)
            pos_fix = calc_pos_fix(processed_meas)
            if len(pos_fix) > 0 and all(pos_fix[0] != 0):
                position_fix_found += 1

                corrected_meas = correct_measurements(processed_meas,
                                                      pos_fix[0][:3], dog)
                count_corrected_measurements += len(corrected_meas)

                pos_fix = calc_pos_fix(corrected_meas)
                if len(pos_fix) > 0 and all(pos_fix[0] != 0):
                    pos_ests.append(pos_fix[0])
                    position_fix_found_after_correcting += 1

        mean_fix = np.mean(np.array(pos_ests)[:, :3], axis=0)
        np.testing.assert_allclose(
            mean_fix, [-2452306.662377, -4778343.136806, 3428550.090557],
            rtol=0,
            atol=1)

        # Note that can happen that there are less corrected measurements compared to processed when they are invalid.
        # However, not for the current segment
        self.assertEqual(position_fix_found, self.NUM_TEST_PROCESS_MEAS)
        self.assertEqual(position_fix_found_after_correcting,
                         self.NUM_TEST_PROCESS_MEAS)
        self.assertEqual(count_processed_measurements, 69)
        self.assertEqual(count_corrected_measurements, 69)
示例#9
0
    def process_gnss_msg(self, gnss_msg, gnss_mono_time: int, block=False):
        if self.is_good_report(gnss_msg):
            week, tow, new_meas = self.read_report(gnss_msg)

            t = gnss_mono_time * 1e-9
            if week > 0:
                self.got_first_gnss_msg = True
                latest_msg_t = GPSTime(week, tow)
                if self.auto_fetch_orbits:
                    self.fetch_orbits(latest_msg_t, block)

            # Filter measurements with unexpected pseudoranges for GPS and GLONASS satellites
            new_meas = [
                m for m in new_meas if 1e7 < m.observables['C1C'] < 3e7
            ]

            processed_measurements = process_measurements(
                new_meas, self.astro_dog)
            est_pos = self.get_est_pos(t, processed_measurements)

            corrected_measurements = correct_measurements(
                processed_measurements, est_pos,
                self.astro_dog) if len(est_pos) > 0 else []
            if gnss_mono_time % 10 == 0:
                cloudlog.debug(
                    f"Measurements Incoming/Processed/Corrected: {len(new_meas), len(processed_measurements), len(corrected_measurements)}"
                )

            self.update_localizer(est_pos, t, corrected_measurements)
            kf_valid = all(self.kf_valid(t))
            ecef_pos = self.gnss_kf.x[GStates.ECEF_POS]
            ecef_vel = self.gnss_kf.x[GStates.ECEF_VELOCITY]

            p = self.gnss_kf.P.diagonal()
            pos_std = np.sqrt(p[GStates.ECEF_POS])
            vel_std = np.sqrt(p[GStates.ECEF_VELOCITY])

            meas_msgs = [
                create_measurement_msg(m) for m in corrected_measurements
            ]
            dat = messaging.new_message("gnssMeasurements")
            measurement_msg = log.LiveLocationKalman.Measurement.new_message
            dat.gnssMeasurements = {
                "gpsWeek":
                week,
                "gpsTimeOfWeek":
                tow,
                "positionECEF":
                measurement_msg(value=ecef_pos.tolist(),
                                std=pos_std.tolist(),
                                valid=kf_valid),
                "velocityECEF":
                measurement_msg(value=ecef_vel.tolist(),
                                std=vel_std.tolist(),
                                valid=kf_valid),
                "positionFixECEF":
                measurement_msg(value=self.last_pos_fix,
                                std=self.last_pos_residual,
                                valid=self.last_pos_fix_t == t),
                "ubloxMonoTime":
                gnss_mono_time,
                "correctedMeasurements":
                meas_msgs
            }
            return dat
        # TODO this only works on GLONASS, qcom needs live ephemeris parsing too
        elif gnss_msg.which == 'ephemeris':
            ephem = convert_ublox_ephem(gnss_msg.ephemeris)
            self.astro_dog.add_navs({ephem.prn: [ephem]})
            self.cache_ephemeris(t=ephem.epoch)