open-rmf / rmf_site

Experimental visualizer for dense buildings in RMF
32 stars 13 forks source link

Tracking issue: SDF Support in rmf_site #210

Open luca-della-vedova opened 5 months ago

luca-della-vedova commented 5 months ago

This issue tracks what's been done and what's currently missing for SDF support in rmf_site_editor, to make it a full replacement for the legacy rmf_traffic_editor workflow.

Why

By adding a capability in site editor to export SDF models and worlds, we can integrate it with our current pipeline and start to get some real usage and feedback from it. Users can use rmf_site to have an accurate 3D preview of what their world would be like then export it to Gazebo.

What

The plan is to have a minimal implementation of the features offered by rmf_traffic_editor to build functional sites, as well as what is offered by rmf_building_map_tools to export them to Gazebo worlds.

How

There are three large parts to this effort, ordered by increasing controversiality. 2) and 3) are split in two different branches if we decide to not go for 3).

1) Feature parity with traffic editor. 2) Export SDF functionality, branch luca/export_sdf 3) Headless mode and world export, branch luca/headless_sdf_export_poc

Feature parity with traffic editor

This is the least controversial and area that we should be working on regardless. We need to make sure that all the features offered by traffic editor are offered by site editor, and the ones that are not offer a good migration path. On the top of my head, areas to check:

Export SDF

This is where the bulk of the work lies and where I took some decisions on how to approach it. A large part of the problem is how do we export the meshes for what we see in the world?

In the legacy workflow, we used to add include tags for each model in the world and manually generate obj meshes for items such as floors and walls by doing the triangulation, calculating the texture coordinates etc. This works but in my opinion is not too optimal for a variety of reasons:

For these reasons I took the executive decision to rethink how we export meshes. I created a crate (warning it's very experimental!) to export arbitrary bevy meshes to GLB files. The idea is that we can take anything that is rendered and throw it in a GLB exactly as it is, so we are guaranteed to have parity between what we see in the site editor and what is exported. The site editor then collates all static meshes in each level into a single large file, and all non static meshes into separate files. This has a few benefits:

There are however some drawbacks:

In general I'm quite convinced that this is a good way forward but there are still rough edges. As I will discuss later.

Headless mode

The (current) idea is to make rmf_site_editor a drop in replacement for rmf_building_map_tools. If we analyze the map building pipeline we can see that map building is a several step process:

All of this is done at build time of the map package. The idea is that to replace this workflow we would need the site editor to also have the capability of being run in headless mode and export the world as an SDF.

This is the part that is most hacked together right now. In my POC implementation I added a (non wasm) command line argument --headless-export [file_name]. When the site editor is ran with it, it will not initialize a window and run until all the models either have spawned or failed spawning, finally it will send a save event and save the whole package including world meshes and navgraphs to the requested path. This is a bit hacky however, and not really CPU efficient since I believe most of the time the application is I/O bound and doesn't need to actually do much since it's fetching models. It currently seem to take a quite significant amount of time but I'm not exactly sure why. I suspect it's because for each model it needs to try to fetch them from fuel in a few different formats and that can take some time.

Current caveats and rough edges.

Test it!

As mentioned in the caveats testing is a bit involved right now. Specifically you will need to:

It should work! I tested the following:

Note that the linked rmf_demos branch switches the whole pipeline (world building, as well as building_map_server) to use .site.json files. In the branch itself I converted and committed office.site.json and hotel.site.json so these two demos (and only these two demos) should work. Other worlds can be trivially converted but I avoided it in the interest of not committing too many files.

mxgrey commented 5 months ago

floors are set to semi-transparent by default when a drawing is added to make sure the users can see both

I wonder if it would make sense to extract a clone of the world and then directly override the components for these transparency settings, and then export that replicated world instead of the original? I think it's very unlikely that the user ever intends to have a glass floor.

mxgrey commented 5 months ago

I suspect the outlines might be exported if it was to be rendered while exporting

Same for this, maybe after we duplicate the world, we can delete all outline meshes from that world before exporting?

arjo129 commented 5 months ago

The biggest one, collada meshes are not supported. This means that some worlds that use them will fail to load and export them (the airport world is one of them). In my implementation I made this a silent failure so the world will just be exported without the mesh but it can be upgraded to be an error instead. I personally don't believe it is worth it to support collada since it's an abandoned format and Gazebo supports gltf since Garden and there will be Harmonic (LTS) out soon with gltf support as well. I would actually advocate for slowly transitioning fuel models to gltf but that is just my opinion.

A third option would be to add a warning. This is what I've seen most software do for scenarios like this.

luca-della-vedova commented 5 months ago

floors are set to semi-transparent by default when a drawing is added to make sure the users can see both

I wonder if it would make sense to extract a clone of the world and then directly override the components for these transparency settings, and then export that replicated world instead of the original? I think it's very unlikely that the user ever intends to have a glass floor.

It's very simple to remove transparency from a floor then export it. I didn't do it because we do allow the possibility of setting transparent walls to support glass walls and I thought we might want ot keep the option open for transparent floors as well but I'll do that.

WRT the outlines, The bevy_mod_outline plugin uses a marker component (actually bundle) and adds a custom render pass that adds outlines to the mesh. Luckily it seems the render pass only changes the way the mesh is rendered and not its actual properties so it does not affect the output of the export. I'll update the first message to reflect that.

mxgrey commented 5 months ago

A third option would be to add a warning.

This seems like the perfect candidate for something that should go into the in-app log. Also the kind of thing that belongs in the diagnostic tool.

luca-della-vedova commented 5 months ago

The biggest one, collada meshes are not supported. This means that some worlds that use them will fail to load and export them (the airport world is one of them). In my implementation I made this a silent failure so the world will just be exported without the mesh but it can be upgraded to be an error instead. I personally don't believe it is worth it to support collada since it's an abandoned format and Gazebo supports gltf since Garden and there will be Harmonic (LTS) out soon with gltf support as well. I would actually advocate for slowly transitioning fuel models to gltf but that is just my opinion.

A third option would be to add a warning. This is what I've seen most software do for scenarios like this.

Yap we have warnings in place for this case! However, I believe warn! messages don't get propagated to stderr so are hidden by default when doing colcon build so they are not too helpful. eprintln errors do but we don't use those in rmf_site_editor so we can do better log filtering. I'll poke a bit and see if it is configurable.

luca-della-vedova commented 5 months ago

Test it!

As mentioned in the caveats testing is a bit involved right now. Specifically you will need to:

  • Build and source Gazebo Harmonic.
  • Build and source ros2-rust.
  • Add rmf_building_map_server into your workspace.
  • Checkout all the branches for the ECS based refactor and Harmonic migration in rmf_visualization, rmf_simulation, and rmf_ros2. Documented in Jazzy Jalisco checklist rmf#416
  • Checkout the SDF POC branch in rmf_demos.
  • Do a clean build.
  • Run the demos as usual.

I managed to make this a bit less painful and removed the dependency on an rclrs node by doing the following:

I am quite unhappy with the amount of duplicated code that this resulted in, but hopefully on the rmf_site side we should be able to cleanup a fair bit once we split the workcell editor mode out, and in the Python side we can either use rclrs when it's ready or slowly phase out the building yaml logic.

With these changes we can get rid of some of the steps and now the testing procedure becomes:

This is for testing legacy projects. For new projects with the site editor, those should be saved as .site.json to make them compatible with the rest of the pipeline, not .site.ron. I'm open to changing the default but I didn't do it here since it would be a more controversial change.

And once Harmonic is released as binaries we won't need any special steps. If this looks reasonable I can start to open a PR and cleanup the code. Note that we should probably get around to doing more testing and reviews on the various branches of the ECS refactor for Harmonic / Jazzy.