Lanes in Free Fleet (#675)

Posted by @0RBalaji:

Hello, I have used the RMF directly to the robot with the fleet_adapter and now want to use the free_fleet so that I can directly add the Zenoh comms feature.
I saw the example implementation of tb3 robot and have a doubt.
Can’t we use lanes while using _free_fleet?

In the example shown in the documentation: Here, the robot is using the Nav2 planner and navigating, there are no features of lanes and nodes.

Chosen answer

Answer chosen by @0RBalaji at 2025-04-21T10:10:54Z.
Answered by @aaronchongth:

@0RBalaji I see what your question is about. The free fleet adapter is still just an Open-RMF fleet adapter, and therefore will obey all the expected behaviors in an RMF scenario. With your given example,

One example scenario is: If one robot is at a node (lets call it loading node) and another robot is set to go and pick there itself. In traditional RMF, the second robot would wait until the lane is cleared but in free_fleet and Nav2, the robot will keep trying to move to the loading node from other directions, which might cause issues for the first robot to come out after pickup successful.

It will still do this the second robot would wait until the lane is cleared.

Posted by @aaronchongth:

Hi @0RBalaji! By lanes do you mean the lanes drawn up in using RMF’s traffic editor?

The concept of lanes and waypoints are used by RMF to command the robots and handle traffic negotiations on a high level. Since all lanes are linear, there is a basic assumption that commanding a robot to travel from one waypoint to another waypoint connected by a lane, the robot will travel along that lane and utilize it’s own navigation stack to perform obstacle avoidance.

Posted by @0RBalaji:

Hey @aaronchongth! Thanks for the reply.

True, when we won’t consider the dynamic obstacles cases.
In traditional RMF method, the lane occupying and nodes occupying is maintained by the RMF, thus it plans, makes robots wait if the node they want to go is occupied by other robot and keeps everything maintained.
In case of Nav2, when it doesn’t have any lanes to obey, it will just move around an dynamic obstacle (lets say another agent). If multiple agents are implemented, they wont wait till the obstacle in front of them is moved, rather it moves around the obstacle to go to its goal. It makes the environment high unstable as one agent replaning might cause issue to others.

One example scenario is: If one robot is at a node (lets call it loading node) and another robot is set to go and pick there itself. In traditional RMF, the second robot would wait until the lane is cleared but in free_fleet and Nav2, the robot will keep trying to move to the loading node from other directions, which might cause issues for the first robot to come out after pickup successful.

This is just one scenario I am mentioning. What do you think about this.

Posted by @aaronchongth:

@0RBalaji I see what your question is about. The free fleet adapter is still just an Open-RMF fleet adapter, and therefore will obey all the expected behaviors in an RMF scenario. With your given example,

One example scenario is: If one robot is at a node (lets call it loading node) and another robot is set to go and pick there itself. In traditional RMF, the second robot would wait until the lane is cleared but in free_fleet and Nav2, the robot will keep trying to move to the loading node from other directions, which might cause issues for the first robot to come out after pickup successful.

It will still do this the second robot would wait until the lane is cleared.


This is the chosen answer.

Posted by @0RBalaji:

Thank you very much for the answer @aaronchongth. The visualization video in the documentation didn’t show the lanes thus I was confused whether it will follow or not.

Thanks for clarifying it.

Posted by @aaronchongth:

no problem, the rviz windows are launched via the nav2_bringup command, not by RMF. The RMF rviz window can also be started via modifying the launch files.

Posted by @ptientho:

I have the same doubt as @0RBalaji about how robots move according to Nav2 and RMF, whether they use lanes or not. Do you have a video showing robots moving in RMF rviz?

Posted by @aaronchongth:

Hi @ptientho You can try it out using the demos. RMF commands the robot from waypoint to waypoint, and it leaves the low level navigation to each robot’s navigation stack. So if the robot chooses to use a non-straight route, it means that the RMF navigation graph might need to be re-drawn or reconsidered (if there are constant obstacles around), or the navigation stack of the robot should be tuned to allow tighter tolerances for static/dynamic obstacles.

For example the command provided in the README sends the robot along those few waypoints, one after the other, but how the robot chooses to navigate between them is out of RMF’s control, since RMF does not have dynamic obstacle information, or if there are new static obstacles, it needs to be reflected into RMF’s traffic navigation graph.

ros2 run rmf_demos_tasks dispatch_patrol \
  -p north_west north_east south_east south_west \
  -n 3 \
  -st 0 \
  -F turtlebot3 \
  -R nav1_tb3

Posted by @ptientho:

This answered my question. Thank you @aaronchongth

Posted by @ptientho:

Screencast from 05-27-2025 11:34:09 AM.webm

Is there any suggestion of tuning Nav2 stack with RMF? My robot was trying to move to the destination but it got stuck somewhere in the middle along the path lane. The navigation output “goal succeeded”, but the RMF was updating that the robot was not reaching the goal.

Posted by @balaji020:

Hey @ptientho

If you could provide a better video, showing a process/task and how robot is entering that state we could suggest your easily.

Also, what I see is your robot is out of traffic lanes. Is the RMF trying to bring it back or is it as it is?

Posted by @ptientho:

Yes, RMF is trying to bring the robot back to the goal. That’s why you see the green line in the RMF map.

In the following video, I send a patrol task from “charger1” to “ent_dock1”.
I made the following change

  1. the nav2 controller parameter xy_goal_tolerance: from 0.25 down to 0.08 to bring the robot pose closer to a goal
  2. the nav2 local costmap parameter global_frame: from odom to map to align the local costmap with the map frame
  3. the rmf fleet adapter parameter publish_fleet_state: and robot_state_update_frequency: from 0.5 to 10.0 to update the robot position faster

Here is the result:
Screencast from 05-27-2025 12:52:19 PM.webm

Posted by @ptientho:

This seems right to me. But when I send another patrol task. The robot’s navigating to a wrong location, which is related to the Nav2 stack itself; you can see the laser scan is not aligned with the map frame, resulting in the wrong navigation.

Screencast from 05-27-2025 01:05:49 PM.webm

Posted by @balaji020:

What I see here might be a potential localisation issue.
The robot is not localized properly and the parameters of it are also untuned.

Try altering the alpha4, alpha5 and alpha6 values.

If the localization is also going bad while the robot is moved straight then change the first 3 alpha values also.

Posted by @ptientho:

Thank you @balaji020. You are right about the localization issue. I tuned the alpha parameters down, and the robot starts aligning better with the map.

Posted by @ptientho:

I am still facing an issue with RMF system tuning. My robot is coming back and forth as shown in the figure. I’m not sure what parameter I need to focus on.

https://github.com/user-attachments/assets/370d208c-cb9e-4122-976b-4ca5d062fdd2

Posted by @ptientho:

This delays the robot navigation. Could you guide me on this?

Posted by @aaronchongth:

Hi @ptientho, the yellow blob indicator shows how RMF has commanded and is expecting of the movements of the robot. In this case, it appears that RMF has commanded the robot to move off, but is somehow stuck at p4. You might need to check the logs and verify what is happening on that end.

As for the second image, can you explain a little more what is happening?

Posted by @0RBalaji:

Hey @ptientho. As @aaronchongth mentioned, the yellow blob is what the RMF is expecting or planning the robot to do, while the blue blob is actual robot status. Based on the it seems the robot isn’t taking the RMF commands. This might be an issue in the fleet_adapter. The robot isn’t taking the new commands or the adapter isn’t conveying, or Nav2 issue. Not exactly sure if that is the case, don’t limit it to that only.

In my case, I am facing an issue which is a bit similar to this and am trying to resolve it also.

Posted by @ptientho:

Hi @aaronchongth, @0RBalaji, Yes the problem is within my fleet adapter that it somehow does not respond to RMF commands as in the following log message

[rmf_task_dispatcher-7] [ERROR] [1748960731.495016394] [rmf_dispatcher_node]: Dispatch command [0] type [1] for task [patrol.dispatch-1] directed at fleet [Fastbot] has expired. This likely means something is wrong with the fleet adapter for [Fastbot] preventing it from responding.

I also found warnings from Zenoh side, which is about Timeout 10s ! Not sure if the problem is related to that.

zenohd
2025-06-03T13:24:02.736322Z  INFO main ThreadId(01) zenohd: zenohd v1.4.0 built with rustc 1.85.0 (4d91de4e4 2025-02-17)
2025-06-03T13:24:02.736636Z  INFO main ThreadId(01) zenohd: Initial conf: {"access_control":{"default_permission":"deny","enabled":false,"policies":null,"rules":null,"subjects":null},"adminspace":{"enabled":true,"permissions":{"read":true,"write":false}},"aggregation":{"publishers":[],"subscribers":[]},"connect":{"endpoints":[],"exit_on_failure":null,"retry":null,"timeout_ms":null},"downsampling":[],"id":"44b1e5a093a1a1e6d46fe9c4590ae47","listen":{"endpoints":{"peer":["tcp/[::]:0"],"router":["tcp/[::]:7447"]},"exit_on_failure":null,"retry":null,"timeout_ms":null},"low_pass_filter":[],"metadata":null,"mode":"router","namespace":null,"open":{"return_conditions":{"connect_scouted":null,"declares":null}},"plugins":{},"plugins_loading":{"enabled":true,"search_dirs":[{"kind":"current_exe_parent","value":null},".","~/.zenoh/lib","/opt/homebrew/lib","/usr/local/lib","/usr/lib"]},"qos":{"network":[],"publication":[]},"queries_default_timeout":null,"routing":{"interests":{"timeout":null},"peer":{"linkstate":{"transport_weights":[]},"mode":null},"router":{"linkstate":{"transport_weights":[]},"peers_failover_brokering":null}},"scouting":{"delay":null,"gossip":{"autoconnect":null,"autoconnect_strategy":null,"enabled":null,"multihop":null,"target":null},"multicast":{"address":null,"autoconnect":null,"autoconnect_strategy":null,"enabled":true,"interface":null,"listen":null,"ttl":null},"timeout":null},"timestamping":{"drop_future_timestamp":null,"enabled":null},"transport":{"auth":{"pubkey":{"key_size":null,"known_keys_file":null,"private_key_file":null,"private_key_pem":null,"public_key_file":null,"public_key_pem":null},"usrpwd":{"dictionary_file":null,"password":null,"user":null}},"link":{"protocols":null,"rx":{"buffer_size":65535,"max_message_size":1073741824},"tcp":{"so_rcvbuf":null,"so_sndbuf":null},"tls":{"close_link_on_expiration":null,"connect_certificate":null,"connect_private_key":null,"enable_mtls":null,"listen_certificate":null,"listen_private_key":null,"root_ca_certificate":null,"so_rcvbuf":null,"so_sndbuf":null,"verify_name_on_connect":null},"tx":{"batch_size":65535,"keep_alive":4,"lease":10000,"queue":{"allocation":{"mode":"lazy"},"batching":{"enabled":true,"time_limit":1},"congestion_control":{"block":{"wait_before_close":5000000},"drop":{"max_wait_before_drop_fragments":50000,"wait_before_drop":1000}},"size":{"background":2,"control":2,"data":2,"data_high":2,"data_low":2,"interactive_high":2,"interactive_low":2,"real_time":2}},"sequence_number_resolution":"32bit","threads":1},"unixpipe":{"file_access_mask":null}},"multicast":{"compression":{"enabled":false},"join_interval":2500,"max_sessions":1000,"qos":{"enabled":false}},"shared_memory":{"enabled":true,"mode":"lazy"},"unicast":{"accept_pending":100,"accept_timeout":10000,"compression":{"enabled":false},"lowlatency":false,"max_links":1,"max_sessions":1000,"open_timeout":10000,"qos":{"enabled":true}}}}
2025-06-03T13:24:02.736911Z  INFO main ThreadId(01) zenoh::net::runtime: Using ZID: 44b1e5a093a1a1e6d46fe9c4590ae47
2025-06-03T13:24:02.737739Z  INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::42:c0ff:fea8:b008]:7447
2025-06-03T13:24:02.737759Z  INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/192.168.176.8:7447
2025-06-03T13:24:02.737787Z  INFO main ThreadId(01) zenoh::net::runtime::orchestrator: zenohd listening scout messages on 224.0.0.224:7446
2025-06-03T13:26:04.694405Z  WARN net-0 ThreadId(03) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:3 Didn't receive final reply for query Face{3, 989b7be71feb97cf8df6f7c62d5124f1}:3: Timeout(10s)!
2025-06-03T13:26:04.694700Z  WARN  rx-1 ThreadId(07) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:3 Route reply: Query not found!
2025-06-03T13:26:04.694727Z  WARN  rx-1 ThreadId(07) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:3 Route final reply: Query not found!
2025-06-03T13:26:21.704674Z  WARN net-0 ThreadId(03) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:4 Route reply: Query not found!
2025-06-03T13:26:38.712272Z  WARN net-0 ThreadId(03) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:5 Didn't receive final reply for query Face{3, 989b7be71feb97cf8df6f7c62d5124f1}:5: Timeout(10s)!
2025-06-03T13:26:38.713500Z  WARN  rx-0 ThreadId(06) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:5 Route reply: Query not found!
2025-06-03T13:26:38.713547Z  WARN  rx-0 ThreadId(06) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:5 Route final reply: Query not found!
2025-06-03T13:26:55.721681Z  WARN  rx-1 ThreadId(07) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:6 Route final reply: Query not found!
2025-06-03T13:26:55.721681Z  WARN net-0 ThreadId(03) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:6 Didn't receive final reply for query Face{3, 989b7be71feb97cf8df6f7c62d5124f1}:6: Timeout(10s)!
2025-06-03T14:30:48.738590Z  WARN net-0 ThreadId(03) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:655 Didn't receive final reply for query Face{5, 9d4dc4783e3ada48578489573a036e61}:69: Timeout(10s)!
2025-06-03T14:30:48.739779Z  WARN  rx-1 ThreadId(07) zenoh::net::routing::dispatcher::queries: Face{2, 8cb23f808ff07dc5dba172b3b7a043bd}:655 Route final reply: Query not found!