Posted by @MrOCW:
Hi, when my lift has arrived on the robot boarding floor, my robot starts attempting to board the lift. However, I manually cancel the lift and sent it off. In a message callback from my lift adapter, I then send my robot back to the lift lobby to wait for the same lift to come again.
self.execution.override_schedule(
"floor name", [[lift_lobby_location[0],lift_lobby_location[1], 0]]
)
self.robot_api.<go to liftlobby>
update_handle.replan()
This is the piece of code i am using to send it back to lift lobby.
After the robot goes back to the lift lobby, it attempts to enter the lift again even though the lif has not arrived yet.
Am i doing it the right way?
Edited by @MrOCW at 2024-09-26T07:02:40Z
Posted by @mxgrey:
Before the robot will attempt to enter the lift, it must see three conditions in incoming lift state messages:
- The lift session matches the robot’s name
- The lift is on the correct floor
- The lift doors are open
If the robot is prematurely attempting to enter the lift, you may want to check if your lift states are misreporting this information.
Another factor is that the fleet adapter might misunderstand where the robot is currently located because you’ve sent it somewhere that doesn’t match the command given by RMF. Immediately before you call update_handle.replan()
, I recommend explicitly using update_handle.update_current_waypoint
(lift_lobby_location_index, yaw)
so that the planner knows the robot needs to begin from the lobby waypoint.
Posted by @MrOCW:
@mxgrey Thanks for the quick reply. I have just verified, upon the next lift call after the first call has failed
The lift session matches the robot’s name : True
The lift is on the correct floor : False
The lift doors are open: False
and the robot tried to enter the lift with the lift doors closed, and not at boarding floor yet.
Before the lift is called again by my lift adapter, the fleet adapter is showing
[<MY ROBOT>] is waiting to begin a session with lift [lift_1] but the lift is currently held by []
which quickly disappears after lift adapter calls again
rmf_lift_msgs.msg.LiftState(lift_time=builtin_interfaces.msg.Time(sec=1727335671, nanosec=912246915), lift_name='lift_1', available_floors=[XXX], current_floor='L02', destination_floor='L03', door_state=<DoorState.CLOSED: 0>, motion_state=<MotionState.UP: 1>, available_modes=[1, 2], current_mode=2, session_id='<MY ROBOT>')
In this case, my boarding floor is L03
FYI, i am using EFC
I have done the update_current_waypoint to the lift lobby and set yaw to 0 as well. Still attempting to enter lift
Edited by @MrOCW at 2024-09-26T07:47:09Z
Posted by @mxgrey:
If you’ve modeled your adapter off of rmf_demos_fleet_adapter
then you may want to also reset RobotAdapter.execution
to None
before calling replan. In any case, you’ll want to pass None
into the update function for the EFC once you’re no longer following the command that was issued by RMF.
In general the transaction between robots and lifts is a rather delicate state machine that requires enormous care if you’re not going to comply with the usual procedure. We’re working on making the transaction very customizable and robust in the ongoing next generation work, but until then I don’t recommend taking liberties when it comes to the interactions between robots and lifts.
Posted by @mxgrey:
Also make sure you do not trigger RobotAdapter.execution.finished()
after you’ve started issuing manual commands to the robot. Triggering the finished callback will make RMF think it can just anyhow move onto the next stage of the plan, which in this case will assume that the robot is inside the lift.
Posted by @MrOCW:
@mxgrey
-
The override schedule isnt actually doing anything as it doesnt send a command to go back to the lift lobby. I had to manually send the api call to the robot to go back.
-
I call lift 3, and I used the fleet_handle to close lanes to lift 1 and 2 which replans the rmf lift request to lift 3. I then cancel the lift request for lift 3, and reopened lanes to lift 1 and 2. I then call lift 2, which matches what rmf lift request wants, but the task then becomes an error and no path could be found to the destination goal on another floor. It seems like reopening the lanes is not working?
Edited by @MrOCW at 2024-09-30T10:13:41Z
Posted by @mxgrey:
The override schedule isnt actually doing anything as it doesnt send a command to go back to the lift lobby. I had to manually send the api call to the robot to go back.
This is the expected behavior. The schedule override API lets you set the robot’s traffic schedule to whatever you want, but it’s up to you to command the robot to follow that path. It’s meant for special cases, for example if the robot is performing a preprogrammed cleaning routine where it will be following a fixed path while it cleans. You would override the schedule with the cleaning path and then instruct the robot to begin cleaning.
It seems like reopening the lanes is not working?
It’s hard to say… You’re performing a lot of disruptive operations in a short time frame during a delicate procedure, so there are many possible reasons that RMF might think it can’t find a path. To debug reopening the lane, you can watch rviz. Rviz should give a visual indication when lanes are opened or closed. If you see the lane remain closed in rviz then yes, the lane is failing to reopen for some reason. If you do see the lane reopen in rviz then something else is going wrong.
Posted by @MrOCW:
@mxgrey
To debug reopening the lane, you can watch rviz. Rviz should give a visual indication when lanes are opened or closed. If you see the lane remain closed in rviz then yes, the lane is failing to reopen for some reason. If you do see the lane reopen in rviz then something else is going wrong.
I am running RMF on AWS EC2 so unfortunately I am unable to visualize using rviz. I recorded a rosbag2 instead and attempted to run it locally with visualization.launch.xml and ran the rosbag but the map doesnt load.
Instead, i checked the /lane_states topic and it seems that the closed_lanes: does reflect correctly when lane closure happens. Is checking this topic an accurate representation?
For clarity, here is the logic:
1st iteration
[EFC] Receive update that lift 3 is called although RMF is requesting lift 2
[EFC] use fleet_handle to close_lanes() to lift 1 and 2
[EFC] close_lanes() method immediately does a replan, which causes RMF to release lift 2 and request for lift 3 instead.
[EXTERNAL] purposefully cancel lift 3
[EFC] Receive update that lift 3 has been cancelled
[EFC] use update_handle’s update_current_waypoint(index of lift lobby, 0.0)
[EFC] use fleet_handle to open_lanes()
[EFC]
if self.execution
self.execution.override_schedule(
"floor name", [[lift_lobby_location[0],lift_lobby_location[1], 0]]
)
self.robot_api.<go to liftlobby>
self.execution = None
time.sleep(3)
update_handle's replan()
2nd iteration V1 (a different lift is called)
[EFC] Receive update that lift 1 is called although RMF is requesting lift 2
[EFC] use fleet_handle to close_lanes() to lift 2 and 3
[EFC] close_lanes() method immediately does a replan, but DOES NOT causes RMF to release lift 2 and request for lift 1 instead.
RMF task state returns error, and no path can be found to destination.
2nd iteration V2 (the same lift is called)
[EFC] Receive update that lift 3 is called although RMF is requesting lift 2
Works the same as 1st iteration.
Edited by @MrOCW at 2024-10-01T05:28:48Z
Posted by @MrOCW:
Update:
I tried closing lanes, and then re opening shortly after.
The lift request from RMF now changes to my requested lift. However, when the lift actually arrives, RMF does not tell my robot to enter that lift, while the lift request has now changed to request_type = 0 to end session.
Posted by @mxgrey:
Can you provide some context for the purpose behind these experiments that you’re conducting? Is this to test whether the system is robust to sudden closing and reopening of lifts or are you trying to implement a certain procedure for the robots to follow?
While we do want RMF to be robust to any circumstances that may theoretically come up in a deployment, the current implementation was aimed at satisfying a relatively limited scope of circumstances. Highly disruptive scenarios like you’re describing may be best to resolve with manual human intervention because you would need to understand many details about how RMF manages the interaction between robots and lifts to automate the recovery.
It may be possible to automate the recovery in these situations but it will be difficult, and we cannot necessarily spare maintainer time to support it. As the maintainers of the project, we need to focus on the project’s long-term development goals which will make your scenario (and many others) fully robust and easy to set up. If we focus too much on hardening the current code base against arbitrary specific use cases then it delays the roll out of the new code base that we’re working on which will be able to cover all use cases.
Posted by @MrOCW:
Our building’s lift system does not allow reservation of lifts indefinitely (which i understand is a constraint of RMF). The lifts times out after a specific duration of time to not cause any extended inconvenience to human passengers, hence the need for such a recovery behaviour and a customized lift adapter for multi lift management with a single node. This discussion is actually linked to #316
I understand that the focus is on the next generation RMF, but we have no other options besides the current RMF right now so our team is thankful for your assistance!
Regardless, I have done several replans and update_current_waypoint at different parts of the code. For some reason, it is working as intended (for now!)
Edited by @MrOCW at 2024-10-03T10:06:50Z