New ROS Enhancement Proposal for Marine Robotics


Folks at the Maritime WG have been holding discussions regarding a new REP submission for marine robotics. We would like to gather feedback on our current ideas and also gauge interest from those that aren’t involved in the WG.


The aim for this REP is to provide a reference for the coordinate conventions used by marine robotics software within ROS that targets underwater vehicles or surface vessels.


The maritime industry has standardized notation that was first proposed by The Society of Naval Architects and Marine Engineers (SNAME, refer to the figure at the bottom of this post). These conventions are contradictory to the standards used in robotics (i.e., REP 103). The resulting inconsistency can lead to integration issues across projects.

Coordinate Frame Conventions

All coordinate frames for marine robotics software within ROS should follow these conventions.

Axis Orientation

In relation to a body, the standard is:

  • x forward
  • y right
  • z down

For short-range Cartesian representations of geographic locations, use the north, east, down (NED) convention:

  • X north
  • Y east
  • Z down

Additional Comments/Notes

  1. Discussions were held regarding proposing standard messages for marine robotics (e.g., sensor messages). We came to the consensus that the initial proposal won’t include standard messages and will prioritize common conventions that are well agreed upon by the maritime industry. There are also existing, well-supported projects that already provide these interfaces including marine_msgs and ros_acomms.

This figure was retrieved from Gianluca Antonelli’s Underwater Robots book:



To start off the discussion, I wanted to make note of a few things:

  1. REP 103 currently includes a section noting the use of suffixes for frames that deviate from the existing ROS conventions (e.g., _ned). Instead of describing a completely new convention, we could instead standardize the use of the “suffixed” frames. The benefit is that there isn’t any confusion regarding which convention is used.
  2. There are some folks that use NED for Cartesian representations of geographic locations for surface vessels. Is this the standard? If so, it may be valuable to include a separate section distinguishing underwater vehicles from surface vessels.
  3. The coordinate frames used in marine robotics largely overlap with those described in REP 105. However, @rolker mentioned that tides can add a bit of difficulty into their use for surface vessels. In particular, he proposes:

I’ve thought about this for surface vehicles where tides add an extra bit of difficulty. I haven’t tested the idea, but here are some suggestions:

  • have “map” be relative to a chart datum, so it can be used as the frame for S57 data
  • for gps data with altitude relative to the ellipsoid, have a “map_ellipsoid” frame with “map” as the parent.
  • have frame to express tides, such as “map_tide” that has “map” as a parent. A mechanisim would be needed to update the map_tide to map offset
  • “odom” would have “map_tide” as parent
  • an optional “base_link_no_heave” could exist between “base_link” and “odom” for platforms where heave is measured.

EDIT: Updated to use Roland’s handle

Thanks for taking this on Evan!

So far, my approach for mostly surface vehicles, but also a few underwater vehicles, has been to stick with REPs 103 and 105. My rational, other than the lack of a marine oriented REP when I started, was to keep things simple within the ROS world. That means I would take care of converting to ENU at the ROS driver level for sensors and such.

To represent spatial data outside of ROS, such as listing waypoints or line plans, I’ve been converting to Lat/Lon using GeoPoint and similar messages. This effectivly hides the implementation detail of which cooordinate frame is actually used under the hood.

This has been working fine for me, so I’m not really in favor yet of recommending that marine robotics should use NED and forward, right, down. I would be in favor or recommending the use of both a _ned suffixed frame as well as the unsuffixed REP recommended frame to hopefully let tf2 deal with their differences.

Anyway, I’m interested to hear what others have to say about this.


I’ve taken a similar approach with my previous projects for underwater vehicles. The points of friction that I have run into in the past have come into play more at the controller level where folks often define their hydrodynamic parameters using SNAME notation. This isn’t necessarily a problem; it just adds to the implementation complexity and is something to keep track of.

That being said, I would also probably tend towards recommending the _ned suffixed frames. An _frd suffixed frame for body frames would be useful too. It seems like we could unintentionally create confusion if folks are expecting the frames used in REP 103 and aren’t aware of the marine REP.

Yeah, this is annoying because of the need to balance existing ROS conventions with the (much older) conventions used throughout the marine domain.

I don’t love decorating all of our frames with _ned and _fsd/_frd (I’m not actually sure whether more people say forward-right-down vs. forward-starboard-down), but I think it may be important in order to avoid confusing people encountering this project coming from the ROS robotics side, rather than the maritime side.

The most important bit to me is to have the expectation that a marine TF tree will have an equivalent to /odom that is NED, and an equivalent to /base_link that is FSD. Right now, I’m just using /odom and /base_link for those, but you might convince me to migrate (or at least adopt a different convention for my next project.) @evan-palmer – maybe the next step is to propose a standardized TF tree, and get reactions to it?

I haven’t thought about tides enough in this context to opine on Roland’s proposed frames for dealing with them. In the applications I’ve worked in for underwater robots, we used pressure-depth for depth in real-time control, converting to WGS84 in post-processing if the application required it. I’ve also worked on a number of non-ocean robots, where sea level and tides didn’t come into it, and pressure-depth was all that was available.

I’m jealous of Roland’s ability to convert to lat/lon in real time =) For all the underwater vehicles I’ve worked on, our real-time on-robot coordinates were in an odom frame, which was again converted to lat/lon in post in a re-navigation step using USBL and other data. (If necessary and if USBL was available.)

I’m gonna steal two links @lindzey gave us and post it here for context.

A similar discussion on coordinate frame convention has occurred in the UW APL marine_msgs repo, which has been a community effort since 2020:

The result of the discussion is here, and has been adopted in that repo:

The significance and relevance of that discussion to the REP is that, the marine_msgs repo was a ROS maritime community effort in hopes of having some kind of standard in the ROS ecosystem for marine sensor messages.

That package has gone through a couple iterations to release into the ROS ecosystem, the latest being from last week

Since both the REP and the marine_msgs efforts are related to having a standard for the ROS ecosystem, it would be in the community’s interest to consider them both and see if they can be compatible. Ideally they don’t clash, if we intend for them to be complementary standards.

One commonly-cited source of conventions in this field is “Nomenclature for treating the motion of a submerged body through a fluid”, published by the Society of Naval Architects and Marine Engineers (SNAME) in 1950.


Personally, I’ve found it surprisingly difficult to convert between ENU+FPU and NED+FSD on the fly when implementing complex simulation / control stuff. But I keep forgetting its a transform on both the navigation and local frame side, so maybe my fault? Whatever.

Tagging @kkrasnosky who was involved in the marine_msgs discussions.

How do you usually do this? Are you doing the math internally to the node, or are you defining a static transformation for FPU<->FSD and using tf?

Internally in the node, or sometimes internally in the module (i.e., with Gazebo).

If you say your on-the-wire-protocol is then you should always make it that . I tried messing with using TF to do the transform ages ago, but it ended up being more confusing than helpful. Especially when writing URDFs and similar things.

Some sort of built-in support for TF would be nice, although I’m sure the OSRF folks would say its out of scope.

Actually @woensug-choi also suggested having a static tf transform for this exact purpose, back in the January Maritime Working Group meeting discussions.

I think @incebellipipo likes to configure robots with ENU, and transform everything to NED using a static transform publisher.

It’s probably not in the scope of the REP, but I can imagine some go-to repo having such a thing that people can be generally pointed to use. If marine_msgs gets released and becomes a go-to repo, that’s a potential option.

1 Like

In my current project i use Blender (RUF), Unity (left-handed, RFU) and ROS (FLU) as well as implementing SNAME-based physics and control… With all this in mind, i dont love the idea of having /frame_ned and frame_frd’s everywhere. On the other hand, I know that my setup is kind of extreme.
In my simulator, everything that happens in Unity uses the standard Unity coordinate convention, and everything in ROS uses ROS conventions. The translation is of course done whenever data is sent in either direction.

This approach has issues, and geographical coordinates are especially annoying. However, there is at least some comfort in knowing that the data i am accessing follows the governing convention of the tool I’m “in”, be it Unity, Ros or blender.

Overall I’m really on the fence about this.

That’s why I’m suggesting something at the API layer. Choice of convention is really an API presentation choice, not TF tree design issue.

Including a parameter would allow each module to pick based on its internal convention and let us all get back to working in our chosen frames. This avoids the extra static transforms floating around in TF where they make the tree way more complicated than it needs to be and also generally confusing things.

Just a thought.

1 Like

Interested bystander here, not active in Marine at the moment.

One of the strong points of ROS is the standardization in my opinion.
How does a different convention work with the rest of the ROS tooling? Can we just use the nav2 stack on a boat?

How about amphibious vehicles, do you switch conventions when transitioning to water? :slightly_smiling_face:

As @edvart stated:

The translation is of course done whenever data is sent in either direction.

I would advocate for this. We have had the same discussions with GPS providers which have a zero north instead of a zero east. Which is fine, but please switch to the ROS convertion when you switch to a ROS interface (message / tf).

Developer wise: it will probably be hard for folks with marine background to think in a different coordinate system, but on the other hand, letting folks with a ROS background think in different conventions for a particular application of course holds the same problem.

This is an important question, and is something that has been brought up in previous WG meetings. I think @arjo129 might be able to speak more to this, especially from a Gazebo perspective. My concern is more about things like URDFs and SDFs.

As @lindzey mentioned earlier, the issue that we run into is that much of the maritime industry (including those that develop the robots, sensors, etc.) has adopted this standard, and the consequence is that we can’t always adhere to the ROS conventions in our ROS code, e.g., in controllers or kinodynamic planners. This can create inconsistencies and integration issues across maritime projects.

As we continue working towards adopting more standardized tooling in marine robotics (e.g., marine_msgs), I think that it’s important that users can have clear expectations regarding how to interface with those projects, given that some of those projects will be forced into using maritime notation. I agree that adding suffixed frames is cumbersome, but I think that solution fits in best with the established ROS conventions and tooling while still supporting the marine projects that need to operate under different conventions.

I also like the idea that @woensug-choi presented (linked above in a comment from @mabelzhang) regarding a common repo that helps folks implement a “marine-to-mobile” transform.

At Kraken Robotics, we take a similar approach to what @rolker described. We define the following frames in an attempt to comply with both REP103, REP105 and SNAME conventions.

The frames suffixed by _ned are pretty self-explanatory and are connected by static transforms from ENU to NED in the above image. As for the base_link_app, the static transform from base_link to base_link_app is defined in the robot’s URDF along with all the other static and dynamic transforms (robot_state_publisher and joint_state_publisher can be used to keep such body-attached transforms updated in the TF tree)

The _app suffix stands for application since this frame is supposed to be the main target for the nodes of a given application case, ours being underwater robotics and, consequently, following the SNAME convention (forward-starboard-down).

If the relevant GNC (guidance, navigation, and control) nodes have expected frame_ids as parameters, one could both transform incoming data (if needed) and automatically compute intermediate transforms to broadcast and update the TF tree. For instance, broadcasting the intermediate odom->base_link knowing actually odom_ned->base_link_app (odometry component) and/or broadcasting map->odom knowing actually map_ned->base_link_app (localization component).

Regarding earth->map, there is an interesting open thread that is more general (not maritime-related) but from which this discussion may leverage, it also contains a nice proposal from Polymath Robotics.


As somone who works with different types of vehicles and wants to be able to have them work together I think it’s important that we stick to REP103. I also want to use as many off-the-shelf ROS components as possible, so yet another reason to respect REP103.

Like it’s been pointed out, REP103 does provide for the use of NED and it’s done so using a suffix frames.

So far, the arguments for not useing suffix frames have not been convincing to me. Calling a frame odom_ned instead of odom is not difficult. The extra static transform to support both odom and odom_ned is a small price to pay in my opinion for the ability to easily interect with the rest of the ROS echosystem. However, if that extra static transform is really a burden, I don’t see why a simpler TF tree with all _ned frames can’t be used for cases where all the nodes expect data in _ned frames.

I think the proposed marine robotics REP in the original post is a good start by point out the SNAME conventions but we should update the Coordinate Frame Conventions to reinterate the use of suffix frames to support NED/FSD while agreeing with REP103.

Adding an illustration of a TF tree to the REP like @gpacheco showed us would be great.


Here is an updated version that includes those changes:

Coordinate Frame Conventions

All coordinate frames for marine robotics software within ROS should follow these conventions.

Axis Orientation

In relation to a body, the standard is:

  • x forward
  • y starboard (right)
  • z down

For short-range Cartesian representations of geographic locations, use the north, east, down (NED) convention:

  • X north
  • Y east
  • Z down

Coordinate Frames

Coordinate frames should comply with REP 103 and REP 105 by providing secondary suffix frames that implement the described axis orientation:

This is s a good step. We need to clarify in the Axis Orientation section that both default REP103 Axis Orientation standard and SNAME standard may be used. For SNAME convention, the frame ids should use the _ned and _fsd suffixes.

This would complement well the Coordinates Frame section that illustrates both conventions.

Maybe the Rationale section can be somethin like:

The maritime industry has standardized notation that was first proposed by The Society of Naval Architects and Marine Engineers (SNAME, refer to the figure at the bottom of this post). These conventions differ from REP103 so the following are recomendations to improve interopability across projects.

I think we have the opportunity to come up with recommendations that can address both users that want to work in a single coordinate system as well those who wish to mix existing non-maritime ROS nodes with maritime systems that use SNAME conventions.

For @ivaughn’s case. He could write node that takes in Odometry and expects it in odom_ned frame. It should be documented that the node will not transform data from a different frame. In that case, the node would work well in a system that already supports odom_ned messages but would need external help on a system that only has the REP103 odom frame. A simple “to_ned” node could be added to the system to transform the data in such case.

Alternatively, a node could be written to support either convention by having an optional TF transform step built in. It should be documented which is the node’s internal convention so the TF step can be avoided if the data is already available in that frame.

Also, to better accomodate a system that is primarily ned/fsd, the TF tree could have, I think, the _ned/_fsd suffixed frames as the main nodes and the unsiffixed ones as the add-ons.

For example:
with map hanging off of map_ned, odom off of odom_ned, and so on.

Is there a reason this would not work?

I err on the side of the non-suffixed frames still being the primary/parent frames, but I don’t have strong feelings, it’s more or less arbitrary. Having thought about it some more, I support this REP in general, either way.

This makes sense to me. It may be helpful to recommend a default/primary orientation to help with consistency across future projects. If there is a reason to diverge from the recommendation, then we have a documented alternative.

What are your thoughts @lindzey? Is this what you had in mind with your previous comment?