Posted by @cihattalat:
Hello. When a task message is sent in the Open RMF system, I want a robot that first goes to point a and then to point b to wait for a while after reaching point a, and especially for this robot that comes to point a, to go specifically to point b. The reason for this is that the product loaded on the robot arriving at point a must go from point a to point b. Which task message should I use to achieve this? The robot going to point A must wait for a while to load the load before the robot goes to point B. How can I perform this hold?
Posted by @xiyuoh:
Hello! For this use case, you can take advantage of RMF’s custom task feature to get your robot to move to the intended waypoints, then wait there indefinitely until it receives a signal to move off. We have a similar implementation available on rmf_demos
, specifically the teleop
PerformAction. In this example, we signal the move off by subscribing to the action_execution_notice
topic, then call execution.finished()
to let RMF know that the robot is done with its custom action and is ready to work on the next phase of the task (if any).
This is a 2-step implementation. For example, if you name your custom action wait_until
:
1. Write the logic for your wait_until
action inside the fleet adapter’s execute_action
callback.
From this callback, upon checking that the category
passed is indeed your custom action wait_until
, you may choose to do nothing (if your robot is simply waiting there) or trigger some custom logic as necessary. It is recommended to store the execution
object (like here) so that it can be accessed from anywhere within the class as we will need this object to mark the end of the waiting action.
There are a couple of ways to end the action.
- If this signal to move off is received from an external source, e.g. you subscribe to a certain topic that publishes a message whenever the loading is complete, then in the subscription callback you’ll want to call
self.execution.finished()
to end the action.
- If you’d like your waiting action to be time-based, e.g. move off after waiting for 10 minutes, you can do that within the fleet adapter. For example, check how much time has passed in the
update
callback, or any other method you may prefer. If the time has exceed a configured waiting time, call self.execution.finished()
to end the action. You may want to configure this waiting time in your task JSON, using the description
field.
- You may even do both, if you’d like to signal the move off from an external source but also have a default timeout so that the robot won’t be stuck at Point A for too long if no one published the move off signal.
2. Design a task that contains the following phases:
- GoToPlace to Point A
- PerformAction
wait_until
- GoToPlace to Point B
You are definitely welcome to rearrange these phases as you like.
You may take the teleop
task script as a starting point. Here we have a GoToPlace phase followed by a teleop
action.
Hope this helps, let me know if you have further questions.
Posted by @cihattalat:
Thank you for the information you provided. But my system communicates with free fleet and I use full_control fleet adapter. So, I use the full_control structure in rmf_ros2. That’s why the information you provided didn’t exactly help me. For a system using free fleet; Do I need to make any manipulations in the full control fleet adapter? With Perform action, I created a task message inside the action as follows and tried it on robots. However, when it enters the 2nd action, that is, perform_action, the connection with the robot is disconnected and it remains like this indefinitely. What can I do so that after doing the first action, it waits for a while and takes the 3rd action? How can I edit it?
{
"type": "dispatch_task_request",
"request": {
"category": "compose",
"description": {
"phases": [{
"activity": {
"category": "sequence",
"description": {
"activities": [
{
"category": "go_to_place",
"description": {"waypoint": "way_0"}
},
{
"category": "perform_action",
"description": {
"unix_millis_action_duration_estimate": 20000,
"category": "teleop",
"description": {}
}
},
{ "category": "go_to_place",
"description": {"waypoint": "way_1"}
}
]
}
}
}]
}
}
}
Edited by @cihattalat at 2024-07-23T06:56:20Z
Posted by @aaronchongth:
hi @cihattalat, thanks for the additional information. free_fleet
still uses the legacy full control fleet adapter, hence it is unable to take advantage of the newer features which involve perform actions. An easy full control fleet adapter implemented to work with the ROS 1 or ROS 2 navigation stack will be the ideal direction for your use-case. But for your current setup, what you intend to achieve with a single task is not possible.
One workaround would be to splitting this into 2 different tasks, while the finishing task is nothing
, which will allow the robot to stay at Point A indefinitely, until the second task is sent out to it to head to Point B.
On a side note, we acknowledge that free_fleet
is terribly out-of-date with the rest of the Open-RMF features and development. We have started regular project management meetings for Open-RMF, where we align priorities, discuss progress and technical challenges. The requirements of the community, any new integrations, or contributions from the public can be discussed there.
Posted by @cihattalat:
Thank you. I will solve this problem on the backend side of the web.
Posted by @cihattalat:
One workaround would be to splitting this into 2 different tasks, while the finishing task is nothing, which will allow the robot to stay at Point A indefinitely, until the second task is sent out to it to head to Point B.
I tried what you said. I entered the Finishing task as nothing and it waits indefinitely at point A until it is sent to point B. However, there is a logic error. Because when the robot is at point A and another task comes from another user, although it has not been sent to point B yet, the robot with the load on it goes to the wrong place because its task has changed. How can I solve this logic error?
Posted by @aaronchongth:
See this answer regarding the same topic, Interrupting the separation of the rmf core process for a period of time in a spread of the RMF robot system. · open-rmf/rmf · Discussion #504 · GitHub
You should be able to send out a single composed task with support for wait_until
configured in the full control fleet adapter. Let me know how it goes
Posted by @cihattalat:
I tried that too. But even after the time_out period I gave with wait until expired, the robot did not become active again. I tried publishing the following command to activate it.
ros2 topic pub /action_execution_notice rmf_fleet_msgs/msg/ModeRequest ‘{fleet_name: ‘tinyRobot’, robot_name: ‘tinyRobot1’, mode: {mode: 0}}’
But when I did this, even though I entered the robot name correctly, all the passive and waiting robots became active at the same time. Specifically, the robot whose name I entered and published should have been active, but all of them became active. How can I solve this problem?
Posted by @aaronchongth:
Apologies I am finding it a little hard to follow the steps you have taken. Can you provide logs in gist.github.com, and also each of the commands you tried in sequence?
With the composed task with wait_until
, there should be nothing related to robot mode that is required, with everything running normally, just the task itself should be suffice.
Posted by @cihattalat:
{
"type": "dispatch_task_request",
"request": {
"unix_millis_earliest_start_time": 0,
"category": "compose",
"description": {
"category": "teleop",
"phases": [
{
"activity": {
"category": "sequence",
"description": {
"activities": [
{
"category": "go_to_place",
"description": "way_1"
}
]
}
}
},
{
"activity": {
"category": "sequence",
"description": {
"activities": [
{
"category": "perform_action",
"description": {
"unix_millis_action_duration_estimate": 60000,
"category": "wait_until",
"description": {
"timeout": 10,
"location": "way_1"
}
}
}
]
}
}
},
{
"activity": {
"category": "sequence",
"description": {
"activities": [
{
"category": "go_to_place",
"description": "ent_1"
}
]
}
}
}
]
}
}
}
Sorry, I’ll explain it in more detail.
I am trying this command. With this command, it first goes to way_1 point. Then perform_action becomes active and the robot goes into waiting state. In other words, if I need to explain it via rviz, the yellow light is removed from the robot. As far as I understood later, the yellow light should come back after 10 seconds and the robot should go to ent_1 point, but this never happens. It stays in perform action all the time.
To solve this problem, I published the action_execution_notice topic that I mentioned above. However, as I explained above, this causes all robots to be active (i.e. the yellow light comes on rviz) even though I enter the name of the robot. How can I solve this problem?
Posted by @aaronchongth:
There should be no need for the action execution notice as well, but I believe it is due to your compose task category as teleop, can you just use gist:d8bf7ba0d0cc6692f65f2cc11a03ce7b · GitHub that I shared instead? It could be arbitrary as long as it is not teleop
. With this gist that I just shared I was able to have the desired behavior in simulation
Posted by @cihattalat:
I did exactly as you said. But it still got stuck indefinitely and did not go to the 2nd point. I am sending you the version I tried below. I just changed the waypoint names.
{
"type": "dispatch_task_request",
"request": {
"unix_millis_earliest_start_time": 0,
"category": "compose",
"description": {
"category": "rmf_milkrun_delivery",
"phases": [
{
"activity": {
"category": "sequence",
"description": {
"activities": [
{
"category": "go_to_place",
"description": "way_1"
}
]
}
}
},
{
"activity": {
"category": "sequence",
"description": {
"activities": [
{
"category": "perform_action",
"description": {
"unix_millis_action_duration_estimate": 60000,
"category": "wait_until",
"description": {
"timeout": 30,
"location": "way_1"
}
}
}
]
}
}
},
{
"activity": {
"category": "sequence",
"description": {
"activities": [
{
"category": "go_to_place",
"description": "way_2"
}
]
}
}
}
]
}
}
}
Why might this problem occur? Although it does not give any error, it is not forwarded to the 2nd point and remains as in the photo below.
We are using the main branch of all RMF packages. Here we are using the full_control adapter in rmf_ros2. We are communicating with Free Fleet.
Edited by @cihattalat at 2024-07-26T08:19:58Z