Velocity and Acceleration Interface
Following @jack-oquin and @meyerj’s comments above I’ve revised it to use the very simple cmd_vel and a new very similar Twist for acceleration.
I would vote for using the stamped message variants for the rate and acceleration interface, too.
Rationale: Even in a real-time context and without querying tf a vehicle can check the
frame_id and interpret the commands accordingly. A velocity command in the real body frame is quite unusual for multirotors because you do not want to climb or descend while flying forward only, independent of the current roll and pitch angle. You could argue that in this case the velocity command could be given in a fixed frame, but the vehicle’s yaw angle should still be respected to determine what “forward” is, without the need to update the command continuously to align with the latest yaw estimation (which might not even be available). This control mode would correspond to standard flight modes like Loiter (ArduPilot) or P-mode (DJI). Having a header frame_id would be one good way to determine the desired control mode, next to a dedicated MAV message with an enum-like field for this purpose. I don’t think a separate control mode switch interface would be wise - the command messages should have a clearly defined meaning and be self-contained (e.g. for playing back from recorded data). In Hector we used to call the frame with the same origin as
base_link but roll and pitch set to zero the
base_stabilized frame, but I do not really like this name and would prefer something like
The header timestamp might be useful to measure delays in the command and control link and a vehicle should ignore commands that have a non-zero timestamp but are too old.
For fixed-wing aircraft it might be more appropriate to command the forward velocity in body frame.
+1 for using the more abstract standard messages. I think it is quite straight-forward to translate them to less abstract messages like MAVLink as advocated by @LorenzMaier, but the conversion function might already depend on the exact type of vehicle and/or auto-pilot in use.
UTM connection and map frame
In my opinion it is nice that REP 105 recommends that the map frame is aligned with north, east and mean sea level if such global reference information is available, but this should not be enforced or even identified with a UTM frame. Afaik most mapping frameworks assume that the map frame is under their control and the robot always start at the frame’s origin with z set to 0. Also visualization tools like rviz would require some usability patches if robots spawn at positions far away from the origin and the map frame would be the only appropriate drift-free reference frame. The current draft of REP-105 also states that there might be other guidelines for defining the map frame, like aligning it with structures in the environment.
What I would propose is to introduce another frame between the
map, which could be UTM or any other local ENU frame. It would be the task of a node like the
navsat_transform_node to choose an appropriate
local_enu frame and publish a static transform from
local_enu and a correction transform from
map (or another intermediate frame), so that the GNSS antenna’s frame is at the measured coordinates in the map. Unfortunately this transform is not fully defined by a only GNSS measurement because it does not carry absolute yaw information and the map frame could rotate freely around the GNSS antenna. In order to solve this we would need yet another frame, e.g.
map_enu which shares the origin with the map frame and enforces ENU alignment:
-- (static) --> /local_enu (could be UTM)
-- (from GNSS and/or barometric altitude measurement of /base_link or one of its children) --> /map_enu
-- (from magnetic heading of base_link or one of its children - provides yaw correction only) --> /map
-- (from mapping) --> /odom
-- (from odometry) --> /base_link
Some of those frames could be identified if the respective information are unknown, e.g.
/map if the vehicle has no absolute orientation information. In this case, viewed from a earth-fixed frame like
/local_enu, the map frame would rotate around the robot while the robot is moving in the map frame and the GNSS node tries to keep it at the measured GNSS position. It might also be possible to come up with a node that estimates the fixed
/map rotation from the robot motion and its location in an earth-fixed frame without the need for a calibrated magnetometer.
I also share the concerns of using AMSL as an altitude reference and tended to vote for the WGS84 geoid, mainly for the reasons already mentioned above:
- consistency with sensor_msgs/NavSatFix (@joq)
- eventual problems with poor quality of built-in geoid correction in GNSS receivers and/or costly calculations (@Tommy_Persson)
- No other sensor can directly measure the altitude in MSL. Barometric altimeters need an external pressure reference anyway, which could either be the local QNH (referenced to MSL), the known elevation at startup (MSL or WGS84) or GNSS (MSL or WGS84). The altitude representation is simply determined by what is used as a reference. A fusion algorithm could take care of the geoid correction and publish the result in WGS84.
On the other hand compatibility with MAVLink (see mavlink/mavlink#298) is also a good argument, but in this case it should be considered to change the definition of the sensor_msgs/NavSatFix message, too. Is this possible without breaking the MD5 sum? This would enforce all GNSS drivers to either publish AMSL altitude as given by the receiver or do the geoid correction themselves. I think the current implementation of nmea_navsat_driver is handling altitude incorrectly because it adds the geoid height (field 11 of the NMEA GGA message) to the altitude already converted to AMSL (field 9 of the GGA message) according to the NMEA specs found at http://www.gpsinformation.org/dale/nmea.htm#GGA.
I think @tfoote’s boat on the ocean visualization example is not relevant here because even MSL is still a theoretical reference. It refers to the mean sea level and does not take into account tidal changes. The
/map or the
/map_enu frame as proposed in the previous section would solve this problem by providing a local earth-fixed reference frame which can be at any desirable altitude, depending on whether the
/base_link has a non-zero altitude relative to
/map or not. Only the
/base_link transform would contain the absolute altitude relative to either WGS84 or MSL.
Hmm, probably there is no right and wrong answer to this question. +1 for MSL.