GPSFix vs. NavSatFix

TLDR; Which of these alternative message types for satellite navigation data are people using today?

As some of you know we have written software that fuses satellite navigation data with LIDAR and camera data and puts it all in to a particle filter based navigation stack that runs on a Raspberry Pi. In the current software this was implemented using the NavSatFix messages.

We are doing a hardware upgrade cycle across all our robots and will be building a high performance satellite navigation module, that connects with a Raspberry pi and publishes Satellite Navigation fix data as a topic under ROS2. In addition to being a multi-constellation module that can, for example, make use of newer high accuracy modes in Galileo, the new module will be dual antenna and thus, potentially, will be able to provide heading and other data that is not supported by the NavSatFix messages. What does everyone use for the satellite navigation message types? What do they want?

We can rewrite all the current software, including our indoor/ourdoor nav. stack, to use GPSFix messages but before we do I thought I’d ask people, what are you all using? What would be most useful for the community? Are there other standards that I should think about?

The gps_common/GPSFix (or, in ROS 2, gps_msgs/GPSFix) was never a part of the core ROS repos. However, the contents of these messages are quite useful. What we do is we publish both NavSatFix and GPSFix from our drivers.

Regarding heading, we have come with our type compass_msgs/Azimuth, a part of our compass repo. The ROS 2 Jazzy port is being finished these days. The Azimuth message has not been standardized into core ROS, but my long-term aim is to gather a few users and then try to “upstream” it into sensor_msgs. Publishing the heading from the dual-antenna GNSS receiver then just means that in addition to the fix topic, you also publish azimuth.

robot_localization does not support Azimuth messages yet and they chose to support heading via Imu messages. Our compass repo provides the necessary tools to convert Azimuth to a georeferenced Imu message.

As a bonus, if your robot has a 9-DOF IMU, you can use its magnetometer as another Azimuth source using magnetometer compass.

If there is value in merging them, or otherwise making it so you only need one message, now is a good time to start working towards that. You’ve got about 9 or 10 months before the L-Turtle freeze to iterate and soak it.

2 Likes

I’ve been looking at this recently because I’ve been experimenting with a significant refactor of gps_umd. The main goal of the refactor is to isolate the ROS 2 pieces from the GPSd interface for maintainability reasons, but it’s also proving to be a good chance to update and expand on the messages in gps_msgs.

We use a string to carry GNSS because the data is much more than lat lon. Message contents that could be useful:

  • satellite time
  • data age
  • reference frame (datum)
  • constellations (gps/glonass/galileo/beidou/etc)
  • RTK data
  • DOP

Would you like to start a public discussion? If so, please, tell me, I’d like to contribute.

However, @gbiggs , seeing the tens of hours burnt in the new IMU REP without going anywhere, I kind of lost belief that changing the base interfaces is still possible. Could OSRA or ROS PMC do something to give the community belief that this is not the general case?

1 Like

There has already been a discussion about a new GNSS message. The discussion was quite fruitful, however, it was not pursued any further.

That’s right. And exactly because Discourse is not suitable for these long-running discussions, I propose to create an issue on GitHub - ros2/common_interfaces: A set of packages which contain common interface files (.msg and .srv). to talk about it. Would you like to propose the issue? Or should I?

@gbiggs I think from reviewing the discussion both here and in the other thread I think it is absolutely clear that we need to move beyond NavSatFix for L-Turtle.

I would propose that, rather than creating yet another message standard and imitating the situation found here xkcd: Standards , we all move towards GPSFix as it is somewhat established reasonably rich and seems to cover most needs. However if @peci1 and @Conpleks feel strongly about needing more data than is contained in GPSFix then we could discuss it further and try to come up with a better message type, probably one that is a variation on GPSFix.

Overall I think that most of the issues that @Conpleks raises around

satellite time
data age
reference frame (datum)
constellations (gps/glonass/galileo/beidou/etc)
RTK data
DOP

could mostly be addressed by tweaking or tightening the definition in GPS fix (for starters most modules these days grab data from all constellations and spit out the long and lat.) can we just agree that we can settle on wgs84 for the datum, etc.

What does everyone else think?

@davecrawly Thank you for reviewing and summarizing the threads. I am against using GPSFix as base since it contains some data that is not well understood (like dip angle) but I may be mistaken. Thus, I would prefer NavSatFix as starting point adding the following:

  • Velocity (in ENU frame) and attitude(*) (incl. covariances).
  • Datum (datum in frame_id, antenna frame in child_frame_id).
  • RTK status(**) and age
  • GNSS time stamp (maybe incl. covariance wrt. position, ie., a 4x4 covariance matrix)
  • Constellations (bitfield?)

(*) Attitude: dual antenna receivers: tilt angle might not correspond to roll or pitch. Antenna alignment wrt. base_link could be deduced from tf to child_frame_id.
(**) RTK: datum jumps possible + base stations do not transmit their datum, see here.

As I see it there are a couple of classes of problem

Problem 0) Where are you roughly (e.g. to within a couple of meters) - here the current NavSatFix works ok.
Problem 1) Where are you and what direction are you pointing - here the current NavSatFix is not adequate GPSFix is better, but I agree with you that some of the elements are not brilliantly defined - my proposal is to improve definitions here but if we still don’t like it perhaps we reconsider.
Problem 2) Where are you exactly, specifically here I am talking about adding in corrections for datum (the earth isn’t round how do we handle that), time (parts of the earth move around a few cm per year how do we correct for that) and whether RTK is on or not (whether RTK is active can affect results in ways that matter).
Problem 3) How fast are you going in a particular direction

In all the above I would argue that if you don’t have a clear idea of accuracy then your measurement is meaningless so I would argue you always need some measure of accuracy such as a covariance.

The suggestion from the other thread was to include a NavSatFix_Status message to include things like constellations and RTK status. The way I see it is that separating the message types in to fixes of position and status that rarely change makes a lot of sense if you don’t need the data why subscribe to it? How about if we did this.

A) Keep NavSatFix as it is (Problem 0)

B) Define a new message that defines the orientation generated by the Satellite navigation system (Problem 1) This would be similar to @peci1’s proposal of a compass_msgs/Azimuth, message but perhaps we can try to agree on something that includes a more complete set of data.

C) Define a NavSatFix_Status message that talks about constellation, RTK status, etc. really with a view to solving Problem 2 the only exception would be timing which as per the recommendation in the NavSatFix message type would be reported in sensor_msgs/TimeReference.

D) Define a separate NavSatVel message that describes the velocity as estimated by the satellite navigation system. Problem 3

If we did it this way then anyone who wrote any software using NavSatFix will not have to rewrite. Plus it seems like it solves all the major problems that I see in all the discourse thread.

Ultimately people have different needs and not everyone needs all the data - perhaps this is a way we can agree on something.

I was actually more in favor of defining a complete message, but you have reasoned so concisely that I am happy with the individual messages :slightly_smiling_face:. Especially the point about not having to rewrite old code using NavSatFix is very plausible.

I agree that it will most probably be easier to reach an agreement with the individual messages.

I’ve been looking at what GPSd includes in its data, and I made a pass at a GNSS message on the simplify_parsing branch of GitHub - danthony06/gps_umd. I think it hits a lot of the discussion here.

Right now I’m favoring an approach where the pose data includes all of the satellite constellation data used to determine that fix.

Curious what you mean about all of the satellite constellation data used to determine that fix. Can you expand?

I agree that keeping NavSatFix as is could be a good thing. Not everyone has a high-end receiver, and not everyone is interested in the highly detailed data.

What I do have a problem with is NavSatStatus which is clearly missing some constants for the fix type and constellations (remember there are also NAVIC, QZSS and many other private constellations). It is also missing many types of fix, and also a datum and height reference (whether ellipsoid height or MASL). In the case of non-RTK receivers, the datum should always be WGS84, but with RTK, it gets more complicated. In my view, this is the absolute minimum that needs to be known to interpret data from the NavSatFix message.

When creating the more detailed message type (starting from GPSFix or not), I’d consider it bad practice to redefine all the constellations and fix types there for the second time. So I propose that the new detailed fix message should include the updated NavSatStatus (or not include it at all and say that each detailed message is accompanied by a NavSatFix with the same stamp; then we could also leave out lat/lon/alt from the detailed message, but I’m not sure about this).

What I consider very unsuitable on the current GPSStatus is the usage of integer PRNs for satellites. That only works for GPS and QZSS. The other constellations do not use PRNs, or use fake/virtual/unofficial ones, but they are not unique. The best satellite identifier I’ve found is its Satcat ID. That is really an ID bound to a specific piece of hardware.

PRNs/other simple identifiers get reassigned e.g. when a satellite malfunctions and is replaced by a new one. The complete history of satellite IDs is published by IGS at https://files.igs.org/pub/station/general/igs_satellite_metadata.snx .

I don’t think that full RTK data should be a part of the new message. First, define full RTK data. You could get all the way down to RTCM streams from both the receiver and base stations. But most receivers can’t even reliably generate and report full RTCM streams with observations at the full speed. Or you could go half-way with something like gnss-info/gnss_info_msgs/msg at master · ctu-vras/gnss-info · GitHub which gives you full information about what did the receiver see and what were the observations (because these are the most interesting pieces for robotics, if anything). But I think these detailed messages would only be useful to a little group of people doing advanced GNSS processing.

So, if anything should be retained from RTK, it is just the status (fix/float/nothing), the datum of the reference station, age of corrections and the integer ambiguity/AR ratio value (this is very important for deciding whether to trust the results or not!).

You could even leave out the fix/float binary decision and provide only integer ambiguity, because the "fix" state is only a thresholded integer ambiguity (most libraries have this threshold set to 3.0). But I guess many people just look for a simple indicator, so keeping the simple fix/float decision is reasonable (with the downside that you don't actually know what exactly does it mean).

Regarding the orientation (heading from dual antennas), I don’t think putting it inside the detailed fix message is a good idea. First, many receivers just can’t produce this information. Second, dual-antenna receivers aren’t the only possible source of heading (you have magnetic/sun/star compasses and more). If the heading is kept separate, imagine how nice it would be to have it as an additional supported type in robot_localization, being able to pass heading from any source, not just dual-antenna GNSS. If someone is interested in both fix and heading, there is the standard mechanism of message synchronizer, so if the timestamps are kept identical, I don’t see a problem.

What to do with tilt from dual-antenna GNSS receivers, I don’t really know. The height measurements from GNSS sometimes suck, and so does the tilt. But hey, is anyone actually using it? I mean, using an IMU for that is just so much more precise (not sure about airplanes/rockets/other things with high acceleration, though). And if you really want, you could publish an IMU message for the tilt. You could also include the heading there, too, but it would probably be lying (because the receivers give heading in geographic frame, but in IMU message, you should have heading in a local cartesian frame/UTM).

Last idea - some receivers (like Septentrio) can directly produce position output in a local cartesian system or UTM. I guess that such messages can be easily converted to Odometry. The only unclear thing is what should be the parent frame. Maybe creating a common naming convention wouldn’t be bad, at least for the UTM frames.

1 Like

Curious what you mean about all of the satellite constellation data used to determine that fix. Can you expand?

Sure. I’ve been thinking about whether it’s better to have one publisher that publishes a message with both the pose related information and the constellation information that was measured when that pose information was generated, or have two separate publishers, one for positioning information and one for constellation data.

My feeling, and I’m happy to have my mind changed on it, is most users are going to want a single message because they’ll typically be looking at the satellite data at different locations along a robot’s path, or trying to figure out why a GPS receiver is being flaky around a certain location. If we publish two streams, a user will need a downstream message filter to match the two streams.

The third alternative is to do both, and have have a runtime switch that lets the user decide how they want the data presented.

What I do have a problem with is NavSatStatus which is clearly missing some constants for the fix type and constellations (remember there are also NAVIC, QZSS and many other private constellations).

I’ve also been looking at how to represent the different constellations. It’s kind of a mess, because there’s a lot of vendor specific representations out there that use different conventions, and it’s not always possible to know what the convention is from a data stream.

If I summarize it sounds like @pec1 is pushing for

  1. NavSatFix
  2. Some kind of direction pointing topic, but maybe better than Azimuth
  3. Corrections to NavSatFix but not NavSatFix_Status

It sounds like we are coming to agreement

@danthony I don’t think we are proposing having two message streams with conflicting information which you’d need to filter, I think we are talking about 0-position and 2-corrections to position. I think what we could do is write a node that takes 0 and 2 and tries to give the best possible location in your chosen coordinate frame. This is something we will surely need anyways.

It sounds to me like we need to come up with a clean definition for 1 and 2. Agree?

Uh, what exactly is 2? I thought NavSatFix already contains the best pose estimate. How should it be corrected?

What I was proposing was more like:

0: NavSatFix with tweaked NavSatStatus
1: Heading
2: Fix details (AR ratio, satellites visible/used, velocities etc). Basically a tweaked GPSFix.
(4: raw observations)

It is hard to make a standard for GNSS (XKCD said it well) I will just argue that either datum should be a boundless field, or not included at all. Saying all GNSS operates in WGS84 is wrong.
Datum is both the ellipsoidal model and its epoch.
For example QZSS (Japanese) uses ITRF reference frame, so hard coding datum to WGS84 is confusing. GPS uses WGS84 (epoch 1984.0), GLONASS uses PZ-90, BeiDou uses CGCS2000.

This is important when using GNSS positioning for sub-meter accuracy.

Any way GNSS is still a great way to tell time if you have no internet :smiley:

1 Like

Datums could be encoded according to EPSG. WGS84 is EPSG:4326 for example.

3 Likes