Skip to content

Conversation

notoriaga
Copy link
Contributor

@notoriaga notoriaga commented Apr 28, 2021

Adds

fn gps_time(&self) -> Option<Result<swiftnav_rs::time::GpsTime, crate::GpsTimeError>>;

to the SBPMessage trait behind a swiftnav-rs feature flag. Also reexports GpsTime as sbp::messages::GpsTime

  • I went with Option<Result<swiftnav_rs::time::GpsTime, crate::GpsTimeError>>, but maybe the Result/Option should be swapped?
  • Maybe should go with a default impl of gps_time that returns None instead of actually implementing a bunch of functions that return None. would make it easier to search for the impls and validate they are correct (also tests would be nice)
  • This crate already has a GpsTime struct which might be a little confusing -
    pub struct GPSTime {

Comment on lines 125 to 148
def gps_time(msg, all_messages):
def time_aware_header(type_id):
for m in all_messages:
if m.identifier == type_id:
return any([f.identifier == "t" for f in m.fields])
return False

has_tow = False
has_wn = False

for f in msg.fields:
if f.identifier == "header" and time_aware_header(f.type_id):
return GPS_TIME_HEADER
elif f.identifier == "tow":
has_tow = True
elif f.identifier == "wn":
has_wn = True

if has_tow and has_wn:
return GPS_TIME
elif has_tow:
return GPS_TIME_ONLY_TOW
else:
return 'None'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is the best way to determine which messages are time-aware/how that time is stored but it seems to work so far

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good starting point at the very least. I'd have to peruse all the message definitions to figure out if there's other ways we include a GPS time in messages, but this should cover the vast majority if not all of them.

I think it should be noted that the time values can have different meanings depending on the message type they're in. For instance the time value in MSG_OBS is the time that the observations were made, but in MSG_EPHEMERIS_GPS (or any ephemeris message) it's a center point in the period of time the data is valid so it is typically several minutes to a couple of hours in the future from when the message was actually generated. We can discuss offline if this is a problem for what you're working on.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this use case the "time of event" or "time of occurrence" is the meaning of .gps_time() -- that is, we want to define a linear time ordering of the messages for use in things like the "sbp chopper" and the interleaver.

I talked with @notoriaga about this briefly and I agree that "t"/"wn"/"tow" covers most of the use case correctly, but we should do an audit of everything that gets grabbed by this and then maybe introduce a "time_ordering" property that we can expose to the yaml spec for this purpose.

@silverjam
Copy link
Contributor

silverjam commented Apr 28, 2021

  • I went with Option<Result<swiftnav_rs::time::GpsTime, crate::GpsTimeError>>, but maybe the Result/Option should be swapped?

Should definitely be swapped, without swapping it makes it kind of hard to use with ?, right?

  • Maybe should go with a default impl of gps_time that returns None instead of actually implementing a bunch of functions that return None. would make it easier to search for the impls and validate they are correct (also tests would be nice)

👍

Maybe MessageGpsTime or MsgGpsTime could help differentiate?

@notoriaga
Copy link
Contributor Author

Should definitely be swapped, without swapping it makes it kind of hard to use with ?, right?

It depends on if your function returns Option or Result. Maybe a custom enum with three variants is best, with two helpers to convert to option or result

Copy link
Contributor

@jbangelo jbangelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with Option<Result<swiftnav_rs::time::GpsTime, crate::GpsTimeError>>, but maybe the Result/Option should be swapped?

I'd vote to keep the Option on the outside, it seems more logical to me. Getting the time is the first operation, and the not having a time isn't an error per se. The second operation is converting the message's time representation into a common format which is a fallible operation. I think the ? operator also works with Option, assuming that the function is returning an Option as well.

@john-michaelburke
Copy link
Contributor

LGTM thank you for doing this!!

@silverjam
Copy link
Contributor

I went with Option<Result<swiftnav_rs::time::GpsTime, crate::GpsTimeError>>, but maybe the Result/Option should be swapped?

I'd vote to keep the Option on the outside, it seems more logical to me. Getting the time is the first operation, and the not having a time isn't an error per se. The second operation is converting the message's time representation into a common format which is a fallible operation. I think the ? operator also works with Option, assuming that the function is returning an Option as well.

👍

MESSAGES_TEMPLATE_NAME = "sbp_messages_template.rs"
MESSAGES_MOD_TEMPLATE_NAME = "sbp_messages_mod.rs"

GPS_TIME = """\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mentioned offline, but if the type uses GPSTime, then we potentially have the "nanosecond residual" available... but digging in to this deeper I don't think we need to worry about this (maybe?). The bare GPSTime object is only used in MSG_TRACKING_STATE_DETAILED_DEP_A, MSG_SPECAN, and (the only one that might matter) is MSG_OBS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really a technical problem since the two structs with the same name are defined in different crates, so they're in different name spaces. It's mostly a potential cause for confusion among developers, right? I'd like to think that's less likely to happen since the libsbp GPSTime struct typically won't be instantiated directly. I imagine it would be accessed as a member of a larger SBP message most of the time. Maybe some clarification in the docs would help?

Copy link
Contributor

@silverjam silverjam Apr 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really a technical problem since the two structs with the same name are defined in different crates, so they're in different name spaces. It's mostly a potential cause for confusion among developers, right? I'd like to think that's less likely to happen since the libsbp GPSTime struct typically won't be instantiated directly. I imagine it would be accessed as a member of a larger SBP message most of the time. Maybe some clarification in the docs would help?

Yeah, that's probably sufficient, I was also thinking a wrapper type might be appropriate in libsbp to disambiguate MessageTime(GpsTime) or something similar.


//! (((description | replace("\n", "\n//! "))))
#[allow(unused_imports)]
Copy link
Contributor

@jayvdb jayvdb Apr 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could remove the need for this, and other lint exclusion rules with

diff --git a/generator/sbpg/targets/resources/sbp_messages_template.rs b/generator/sbpg/targets/resources/sbp_messages_template.rs
index e2f85da1..ffd7729c 100644
--- a/generator/sbpg/targets/resources/sbp_messages_template.rs
+++ b/generator/sbpg/targets/resources/sbp_messages_template.rs
@@ -15,16 +15,10 @@

 //! (((description | replace("\n", "\n//! "))))

-#[allow(unused_imports)]
-use std::convert::TryFrom;
-
-#[allow(unused_imports)]
-use byteorder::{LittleEndian,ReadBytesExt};
-
 #[allow(unused_imports)]
 use crate::SbpString;
 #[allow(unused_imports)]
-use crate::serialize::SbpSerialize;
+use byteorder::ReadBytesExt;

 ((*- for i in includes *))
 use super::(((i)))::*;
diff --git a/generator/sbpg/targets/rust.py b/generator/sbpg/targets/rust.py
index cf1e0268..adedd574 100644
--- a/generator/sbpg/targets/rust.py
+++ b/generator/sbpg/targets/rust.py
@@ -46,6 +46,8 @@ Some(swiftnav_rs::time::GpsTime::new(0, tow_s).map_err(Into::into))
 GPS_TIME_IMPL = """\
 #[cfg(feature = "swiftnav-rs")]
 fn gps_time(&self) -> Option<std::result::Result<swiftnav_rs::time::GpsTime, crate::GpsTimeError>> {{
+    #[allow(unused_imports)]
+    use std::convert::TryFrom;
     {}
 }}
 """
@@ -110,7 +112,7 @@ def parse_type(field):
     return '_buf.read_i8()'
   elif field.type_id in TYPE_MAP.keys():
     # Primitive java types have extractor methods in SBPMessage.Parser
-    return '_buf.read_%s::<LittleEndian>()' % TYPE_MAP[field.type_id]
+    return '_buf.read_%s::<byteorder::LittleEndian>()' % TYPE_MAP[field.type_id]
   if field.type_id == 'array':
     # Call function to build array
     t = field.options['fill'].value

clippy doesnt seem to mind; it does however have another 150 warnings :/

fn gps_time(
&self,
) -> Option<std::result::Result<crate::time::MessageTime, crate::time::GpsTimeError>> {
let tow_s = (self.tow as f64) / 1000.0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is is correct to assume that the tow field always is in milliseconds?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jbangelo @denniszollo are there some messages that report tow in seconds, not ms?

@notoriaga there is a "units" field in the yaml spec that we could potentially inspect here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added an assert that the units are ms. Only one wasn't IMU_MSG_RAW. For now just skipping that msg, it seems like it might not actually be representing 'rover' time - but rather 'Time since reference epoch in milliseconds' which seems like not what we want

@notoriaga notoriaga marked this pull request as draft April 30, 2021 21:35
Copy link
Contributor

@john-michaelburke john-michaelburke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!

@notoriaga
Copy link
Contributor Author

I pulled together a list of all the rover-time messages

MsgAgeCorrections
MsgAngularRate
MsgBaselineECEF
MsgBaselineECEFDepA
MsgBaselineHeading
MsgBaselineHeadingDepA
MsgBaselineNED
MsgBaselineNEDDepA
MsgDops
MsgDopsDepA
MsgExtEvent
MsgGPSTime
MsgGPSTimeDepA
MsgGPSTimeGnss
MsgInsUpdates
MsgMagRaw
MsgObsDepA
MsgObsDepB
MsgObsDepC
MsgOdometry
MsgOrientEuler
MsgOrientQuat
MsgPosECEF
MsgPosECEFCov
MsgPosECEFCovGnss
MsgPosECEFDepA
MsgPosECEFGnss
MsgPosLLH
MsgPosLLHCov
MsgPosLLHCovGnss
MsgPosLLHDepA
MsgPosLLHGnss
MsgProtectionLevel
MsgProtectionLevelDepA
MsgSbasRaw
MsgSolnMeta
MsgUtcTime
MsgUtcTimeGnss
MsgVelBody
MsgVelECEF
MsgVelECEFCov
MsgVelECEFCovGnss
MsgVelECEFDepA
MsgVelECEFGnss
MsgVelNED
MsgVelNEDCov
MsgVelNEDCovGnss
MsgVelNEDDepA
MsgVelNEDGnss

would be nice to get some eyes on this. One thing I'm wondering is that we have MSG_OBS as base time, but we have MSG_OBS_DEP_{A,B,C} here - is that correct?

@notoriaga notoriaga marked this pull request as ready for review May 10, 2021 19:43
Copy link
Contributor

@silverjam silverjam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this to note that we decided to add something custom to handle IMU_RAW and WHEELTICKS messages from thachoppa: https://github.com/swift-nav/thachoppa/blob/master/src/lib.rs#L148

@notoriaga notoriaga merged commit 40bd485 into master May 11, 2021
@notoriaga notoriaga deleted the steve/time branch May 11, 2021 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants