I’ve recently been working with MicroStrain, Trimble, and ArduPilot on their ExternalAHRS support. I’m adding support for the bleeding edge GNSS+INS devices from these companies into ArduPilot. The sensors provide 1cm positioning, orientation, and run a full kalman filter. Both can output a ton of data, including covariances. They also have validity flags for different parts of the data, and much more fine reporting of the health of the EKF.
There currently are not any messages in ROS I know of to support these kinds of devices. GNSS+INS gives different data than a dual antenna GNSS system that does orientation.
Exactly how fuse is supposed to work when the GNSS+INS is already running a kalman filter is not clear to me, however MicroStrain’s device supports outputting both the raw sensor measurements (traditional GPS data from each antenna), as well as its fused data in the filter packets. I have a pretty comprehensive document on message definitions.
If we can take 3-4 commercial GNSS+INS devices and generate a comparison of the data fields added, I think that will be really helpful in drafting either a new or modified message
Another thing to note is that many SLAM frameworks using IMU build models under ECI (Earth-centered inertial) coordinates. Because the model under ECI is more concise than that under ECEF. So we also need a tool for ECI to ECEF conversion.
I don’t understand the argument for ECEF. In my opinion, ECEF shouldn’t be a target coordinate system, as the z-axis here does not correspond to the direction of gravity (except at the poles :-)).
Pros and Cons of UTM and ECEF from my perspective:
ECEF:
[+] no distortions of angles or distances/areas
[- - -] not a horizontal coordinate system
UTM:
[++] horizontal coordinate system (x= easting, y=northing, z=altitude)
[++] global standard for all kinds of geodata
[++] angle-preserving, so it is a conformal map projection
[+] covariances of GNSS receiver are typically given in such a horizontal coordinate system
[-] UTM has minimal distortions of distances (scale varies between 0.996 and 1.0), however, I can’t imagine that these are relevant in a typical robotic application
[-] Splitting into zones, but it shouldn’t be a problem to fix the zone for a single robotic mission
Certain minor problems exist in both coordinate systems:
[-] large coordinates (ECEF: x,y,z, UTM: only y), meaning you have to reduce the coordinates through a local origin in both cases.
But maybe I’m just misunderstanding something. In my opinion, ECEF should maximally be an intermediate coordinate system when transforming from LLA to UTM.
I think @pglira makes some good points about ECEF vs UTM, but I want to touch on one specifically that has been problematic both for myself and for others: UTM
[-] Splitting into zones, but it shouldn’t be a problem to fix the zone for a single robotic mission
I think this is generally true for a lot of engineer-operated robots and robots that operate only in a few areas. I previously worked with UAV applications where we used UTM as the underlying coordinate system to great success. Whenever we operated, we did many simulations and tests and validated that the specific flight plans we used would not be problematic. However, for wide-usage and operators that may not have ever heard of UTM, let alone be aware of the complications that can arise operating across a zone boundary, this will come up and it will be an issue. As unlikely as it seems, in one of our very early deployments at Greenzie, we were mowing a field that had the boundary of two UTM zones go straight through the middle.
This led to the implementation of a local-coordinate system option (instead of UTM) inside R_L’s navsat_transform node. While that supports some use cases fairly well (robotic lawn mowing), it does not all of them. Especially as we want robots traveling further distances from where they turn on.
If we want robots that are capable of being operated anywhere at any time (within reason), we will need a robust solution for handling operation across a UTM zone boundary (possibly avoiding UTM entirely).
I don’t understand the argument for ECEF. In my opinion, ECEF shouldn’t be a target coordinate system, as the z-axis here does not correspond to the direction of gravity (except at the poles :-)).
I don’t think the argument was for ECEF, it’s for a local cartesian coordinate system, what you would get out of ecef2ned or lla2ned in MATLAB/navpy.
That eliminates the large coordinates (as everything is referenced to some local datum), and makes it a horizontal coordinate system with very very small distortions when you move far enough away from the datum.
Hi !
Very excited about the discussion open here. I’m working with underwater robots, and we also needed to integrate gps measurements.
I can see multiple issues presented here. Here is my take on it.
Handling and passing gps information around
Geodetic informations as mentionned by @AaronP1 and @Val_Schmidt need both the datum and epoch.
A GeoPoseWithCovarianceStamped with additional fields to hold this information would be a good start to hold all the required details.
Transforming GPS information to cartesian
We’re using proj to transform all our geodetic transformations to cartesian and vice-versa. We’ve implemented an abstraction layer to allow us to pass different types (a la tf2_geometry_msgs). Proj also allows us to handle many datum and epoch. (not a geodesy expert here so I don’t know how it compare to GeographicLib in terms of functionalities, but it seems to be pretty complete)
ECEF vs UTM
We have decided to go with the ecef frame as described in REP-105
By taking the convention that everything expressed in the earth frame has to use the WGS84.
We can create as many map frame as needed, each one being a local tangent plane. Having the earth frame always present gives us “transfer-ability” between different maps through the tf2 tree and even between rosbag. If we used UTM data, we wouldn’t be able to replay a rosbag of cartesian data (tfs) without also storing the UTM zone in which it was recorded and recomputing the tf between zones at replay-time.
Using the tf tree
Once everything is in cartesian the tf tree can be used to convert from/to any local/global frames.
A nice extension of tf2, that I though could be useful is to design a GeoTransform message that could be also used with tf2. Internally it could be transformed to ecef. The benefit is that you won’t have to convert GPS data yourself to a local plane before storing it in the tf tree. Tf2 could expose or not that earth frame. You can then have a getGeoTransform method that can convert any frame/pose into geodetic information directly from the tf tree.
Fusing data
Fuse is also our choice for fusing 3d informations, although it is still missing the implementation for processing 3D sensor, on which we started working.
Sorry to be MIA, somehow I got unsubscribed from this thread -_-
Can you both expand on that? That sounds actionable to me. What else are we missing, hit me with it.
Zeerek, can you respond to this? @AGummyBear did a good job on some of them!
This sounds like what we’re talking about (@Iliabara)! @ejalaa12 is this something you can provide more information / implementation about? That could be a really nice accelerator to moving forward with ROS 2 ECEF GPS support if we can take something broadly working and just refine it for public consumption!
@tfoote would something like adding Geo support for TF be possibly on the table? I don’t want to spend time going down a direction if the answer is a hard no.
I’m not sure exactly what this is asking for. At it’s core TF just keeps track of a number of named (euclidean) coordinate frames and helps you move data between them in a way that you don’t care about the connectivity as long as it exists. We definitely aren’t going to be able to support non-euclidean coordinate frames in the internals of tf2.
I think that there is a moderately low bar to writing a small adapter class that can convert ECEF representations to and from a projection of your choice. The challenge I think will be agreeing on the semantics of the projection and sharing the projections appropriately. Likely embedding that projection into the pose representation so that you can use an automated tool like proposed above to automatically convert points in your projection. But you need to remember that the transform between two points in free space will still be a euclidean transform and not necessarily a [delta lat, delta lon, delta heading]. But if you have a clear way to ask that something be represented in a certain projection, and clear instrumentation of the current projection. A tool to automatically convert that to ecef first should be relatively straight forward.
As explained by others (@Val_Schmidt, correct me if I’m wrong), the missing information to fully qualify a geodetic position (lat/lon/alt) is the datum/epoch in which it was expressed. PROJ uses CRS (Coordinate Reference System) codes to identify that datum/epoch combo.
We could add a crs string field to the GeoPoseWithCovarianceStamped which gives us the information that we are missing to fully project/convert/transform the geodetic information.
Note:why not use the frame_id ? because the frame_id is suppose to contain the id of the device that generated the information (e.g.the gps receiver)
Sure! It’s more of a solution than an implementation. What would you need to know ?
An important thing to note is that an ECEF origin is always tied to a CRS.
So selecting a good CRS as a default is crucial to make sure your earth frame is always the same point on earth.
Then any geodetic data that needs to be expressed/displayed in cartesian can be transformed into the selected CRS and then projected to cartesian (ecef). For example any map frame could be geo-referenced
As mentioned, PROJ can handle all the projections.
I’m not sure if this answers your question. I can clarify if needed.
Hey all, Zeerek here one of the authors of the document Steve shared at the top! I apologize for jumping on this thread a bit late.
To clarify some confusion (and agreeing with the others who said this), the idea is that we make a successor to NavSatNode that fulfills the requirements of the greater ROS community. We would like this successor to utilize an ECEF coordinate as the datum for a local coordinate frame. This datum (similar to navsat node) can either be generated by the initialization location OR pre-set. The output is a pose in that local coordinate frame.
This successor node’s responsibility is to handle world → map poses. If we enter regions where this transform needs to be updated to maintain accuracy, it should take care of it.
Map is a local coordinate frame regardless of if you utilize UTM or ECEF. The local coordinate frame can be configured to be ENU aligned. ECEF would work out of the box without need to pay attention to zone. However for UTM we are effectively taking a “standardized” tangent plane and then creating another frame within that to get to map. However, that “standardized” tangent plane has drawbacks at zone boundaries (echoing what @AGummyBear brought up quoted below) as well as other issues highlighted in the original doc. This makes ECEF a less complicated and more reliable way of having euclidian world coordinates while making the “map frame” functionality not change.
Hadn’t really looked at PROJ before, thanks for sharing! I’ve been using geographiclib for my transforms, but geographiclib has a disclaimer that it is unable to do datum conversions and to use PROJ. Maybe that’s the method of implementation of LLA to ECEF to Map we should move towards.
At my previous job doing large outdoor robotics, we actually had a wrapper over TF(2) which added support to transform to or from non-euclidean frames (like /wgs84 and /utm) to any other valid TF frame by name in our library swri_transform_util using PROJ internally.
This approach can easily be expanded to add other reference frames. Note that we didn’t end up using UTM too much since it was a bit of a mess to work with, so that side may be a bit rough around the edges in our implementation.
In practice we would only use WGS84 and our /map frame which was just a frame perpendicular to the earth (generally) centered at our startup location called the “local_xy_origin” which we published on a topic named /local_xy_origin. This avoids most of the odd cases where you might accidentally be on the edge of UTM grids. If you ever travel far enough from the origin and get too much distortion, you can always re-center the origin. We never actually encountered needing to do this in practice, so doing it in practice smoothly would probably need some additional work to avoid glitches. One could always pause the robot for a few seconds and do the origin swap if needed.
I’d be happy to go into more detail if anyone is interested in the approach.
I will note one thing that is often forgotten about large local grids like UTM that definitely got me once or twice, is that there is the concept of “Grid North” which is different than “True North”. In order to properly transform rotations into these frames you’d likely need to handle that somehow and make it clear which heading references you are using throughout your code.
@smac sorry I just saw this. I’m currently maintaining gps_umd, which has the gps_common messages packages among others, as well as SwRI’s novatel_gps_driver package. I’ve got quite a few thoughts about the shortcomings of the existing implementation and ways to approve. I’d be happy to talk sometime about this.
Although not 100% related to the first message in this thread, I’d just like to mention another future GNSS discussion: https://github.com/ros2/common_interfaces/pull/220 which discusses feature-completing NavSatStatus message with the long missing constants e.g. for RTK. If you want, please, help the discussion to converge
Part of what has held me back from deploying more features for the GPS common is testing. I have a handful of GPS receivers, but given how loosely a lot of them implement the NMEA 0183 protocol, I’m always a little afraid to make big changes that work for me and break lots of other people. Maybe now that ROS 2 Rolling is a thing, that would be an avenue for doing some more aggressive changes in the future.
I would like to discourage a solution that relies on assuming we only use ROS 2 on robots that can pause. Hardly any fixed-wing aircraft can hover. If there is a map origin change for a local cartesian frame, it ideally is designed in a way that it’s seamless.
With respect to message standardization, I believe the library geographic _msgs might be useful because it provides standard geo based messages that also includes orientation. geographic_msgs Msg/Srv Documentation
We at Polymath Robotics have begun work on the proposal at the beginning of this discussion. The current scope for the first version of this is to have NavSatNode parity. Notable changes/additions should be:
Create a ROS2 Lifecycle Node
Utilize ECEF to anchor the “map” local tangent plane instead of UTM
Allow for manual LLA reference (called datum in navsatnode). To lay the groundwork for autnomous datum updates, allow for datum updates without jumping position in map frame.
Add metadata message with information on initialization settings including reference lat,lon,yaw and date time.
Utilizes Proj so that in the long term the community can work together to add other transformations outside of geocentric ECEF WGS84. This also means that it would be possible to support UTM again via Proj and we can use the Metadata to record useful information
Service toLLA and fromLLA will allow for vectors of points
Initialization improvements for clarity and flexibility (ENU aligned map frame option, no yaw option, etc.)
It’s my preference to actually use the gps_msgs/msg/GPSFix. However @danthony, I wanted to understand the dip and track nomenclature as it is a bit confusing. “Heading” or “Bearing” might make more sense than track as standardized words. I would also love a “yaw rate” equivalent addition as some GPS’s are able to give this data. This message is the most feature complete one I’ve found, and we quite like it overall. I also like that there’s a node provided that translates NavSatFix to GPSFix allowing for us to use this for our node right away and maintain backwards compatibility through this.
This message is missing core GPS data that that may be useful and is provided by the GPS drivers. We use it at Polymath, but not as an output from the GPS Driver.