Velocity and Acceleration Interface
From Sign in to GitHub · GitHub
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 base_upright
.
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 earth
and 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 earth
to local_enu
and a correction transform from local_enu
to 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:
/earth
-- (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_enu
and /map
if the vehicle has no absolute orientation information. In this case, viewed from a earth-fixed frame like /earth
or /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_enu
to /map
rotation from the robot motion and its location in an earth-fixed frame without the need for a calibrated magnetometer.
Altitude representation
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 Welcome gpsinformation.org - Hostmonster.com.
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 /local_enu
to /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.