User-defined Custom Tasks (#155)

Posted by @dionesiusap:

Hi, this question might come across as a beginner question, but I really can’t figure this out.

I’m currently trying RMF for a project. I’m mostly learning RMF from this tutorial. I’ve tried out the demos and the task types provided out of the box (cleaning, delivery, loop, etc). and it works well.

So I would like to add some custom tasks of my own. My custom tasks would be similar to cleaning, so the robot will go to a certain vertex or node in the graph. On that vertex, whereas during “cleaning” task the robot will do a cleaning over a certain region, during my custom task it will do something else, for example executing a FlexBE behaviour. Is this possible with RMF?

I’ve read the documentation here. I’ve also taken a look at some codes related to tasks, mainly those in the rmf_task package. But still I can’t figure out how to exactly achieve this (which class I can extend, APIs, etc). I have a feeling that it’s achievable with RMF but can’t figure out how.

Any help would be greatly appreciated, thanks!

Posted by @mxgrey:

If it is okay for your robot to not participate in traffic negotiation while doing its custom behavior, then you could implement it as a perform_action. When I say “not participant in traffic negotiation” that means you’ll be able to report your robot’s trajectory to the traffic schedule which allows other robots to avoid yours, but your robot will not be able to accommodate others until your custom behavior is finished. This is how the cleaning task behaves once the robot begins its cleaning activity.

This limitation was an intentional design choice to keep the rmf_fleet_adapter API simple enough that it doesn’t overwhelm users while still being able to cover the vast majority of use cases. I hope to have a more comprehensive API in the future that would allow a robot to have a custom behavior tree while still participating in traffic negotiation, but we have no estimated timeline for that yet.

In the meantime, this other discussion points out which parts of the rmf_fleet_adapter API need to be used to create a custom perform_action. To additionally report your robot’s trajectory to the traffic schedule (allowing other robots to move out of its way) you’ll need to use the “unstable” traffic schedule participant API. Python bindings for the traffic schedule participant can be found here.

Posted by @dionesiusap:

Great, thanks for showing me the right direction. Yes, for now I’m fine with the robot behaving like this.

I plan to use free_fleet for the fleet manager, but after digging a bit more I see that support for perform_action is yet to be completed. So is it more advisable to implement my own fleet adapter? I suppose I can use this fleet_adapter_template and implement custom perform_action?

Posted by @mxgrey:

That’s right, I’d recommend writing a custom fleet adapter, and the fleet_adapter_template should be a helpful reference for that.

Posted by @harshp1509:

Hi @dionesiusap , I am trying to perform custom task but i am not able to figure out that what should come in url. and where to write the code of what should robot have to perform?

    def start_activity(
        self,
        robot_name: str,
        activity: str,
        label: str
    ):
        ''' Request the robot to begin a process. This is specific to the robot
            and the use case. For example, load/unload a cart for Deliverybot
            or begin cleaning a zone for a cleaning robot.'''
        url = (
            self.prefix +
            f"/open-rmf/rmf_demos_fm/start_activity?robot_name={robot_name}"
        )
        # data fields: task, map_name, destination{}, data{}
        data = {'activity': activity, 'label': label}
        try:
            response = requests.post(url, timeout=self.timeout, json=data)
            response.raise_for_status()
            if self.debug:
                print(f'Response: {response.json()}')

            if response.json()['success']:
                return True

            # If we get a response with success=False, then
            return False
        except HTTPError as http_err:
            print(f'HTTP error for {robot_name} in start_activity: {http_err}')
        except Exception as err:
            print(f'Other error {robot_name} in start_activity: {err}')
        return False

Posted by @xiyuoh:

Hi @harshp1509 , may I check whether you are trying to perform a custom task within RMF demos (simulation), or are you writing a fleet adapter for a separate simulation/hardware integration? It will affect where your custom action logic would go.

If you are purely experimenting within RMF demos, the simulation-specific custom actions supported right now are teleop, clean, delivery_pickup and delivery_dropoff (triggered here in the fleet adapter). Their respective robot logic can be found in the demos fleet_manager, as the fleet manager is what we use to coordinate robot navigation and actions in RMF demos. Feel free to look through the fleet manager code and add on your own custom actions there if you’d like.

If you are looking to write your own fleet adapter, be it with simulation or hardware, you can use the fleet adapter template as suggested above, follow the instructions in the README and fill in your robot API in wherever applicable inside RobotClientAPI. To add custom robot actions inside the fleet adapter template, you may consider implementing your robot logic in RobotAPI’s start_activity, and trigger it accordingly from execute_action. For example:

def execute_action(self, category: str, description: dict, execution):
    self.execution = execution
    label = description['some_key']
    self.api.start_activity(self.name, category, label)
    return

Lastly, to create and submit custom tasks with your own robot actions, you may refer to this dispatch_teleop task script as an example. We build RMF tasks in sequence of phases, so you can build your custom blocks accordingly and insert your robot action wherever suitable. In the teleop example, the task is made up of two phases: 1) GoToPlace (robot moves to a specified waypoint), and 2) PerformAction (RMF triggers the specified action to be performed via the category parameter, which in this case is teleop). If your robot action requires more info to be performed, you may add them as a dictionary under description. Do create your own task script that generates your desired task description for RMF.


Edited by @xiyuoh at 2024-11-14T03:56:48Z

Posted by @pvg6:

I want to achieve object detection by robot. When we send the robot to particular place. When it reach the destination then custom task should do detection of that place.. After finishing the custom task it will continue to RMF task..

I am Using rmf_demos_fleet_adapter and using turtlebot3..
I did RMF on my single real turtlebot3 without zenoh bridge. We compulsory need zenoh bridge? Because some time I am getting Extraplotation error…
Link
Please help me

Posted by @xiyuoh:

Hi @pvg6 , I’ve provided some steps to writing a custom RMF task above, feel free to take a look and see if it helps you. If you need more clarification, please provide details to what you’ve integrated so far for us to better understand your use case and how to help you.

Posted by @pvg6:

Thank you I will try to explore @xiyuoh @aaronchongth

Posted by @pvg6:

Hi @xiyuoh

In rmf_demos which simulation is using the custom task [teleop]
and i will try to exent to my use case and when it will terminate…?

Posted by @xiyuoh:

The teleop action is enabled for tinyRobots in the Office world demo. You can refer to instructions under dispatch_action here. The steps listed run dispatch_action instead of dispatch_teleop, but they essentially achieve the same teleop task if you follow the steps. The action is terminated by publishing a message on /action_execution_notice (example also available in the instructions).

To play around with the teleop task, do scroll down to the bottom of the instructions page for more details, specifically office_teleop_robot under Additional Scripts.

Posted by @pvg6:

@xiyuoh

hi can you explain the work flow, how can i add my x, y velocity commands when it reach destination. I am assuming like i am using the already implemented task [teleop] no need to create the task sequence or any thing..


Edited by @pvg6 at 2024-11-14T13:19:57Z

Posted by @xiyuoh:

@pvg6 as mentioned in the comment above, you can use the office_teleop_robot launch file to teleop the robot around a few pre-defined coordinates in the Office world simulation once the robot reaches the coe waypoint and begins the teleop custom action portion of the task. You don’t have to add any x, y velocity commands within this simulated world. I highly encourage you to read through the entire README and follow the instructions provided to ensure that you understand how the custom tasks work in rmf_demos before you attempt to implement them on your TB3s.