Creating Multiple Perform Action Behaviors (#145)

Posted by @lkw303:

Hi! The “Perform Action” hook has been really helpful for creating a new task with our specified behavior. However, may I know how it may be implemented in the case where I would want several actions that would perform different behaviors?

I attempted to created a new perform action on top of the existing teleop action by:

  1. Creating a new consider lambda function similar to this
  2. Adding a new performable action by calling add_performable_action with a differents category similar to this
  3. Creating another ActionExecutor lambda function which contains the logic of my new action behavior.

However I realised a that if I were to simply pass my newly defined ActionExecutor into RobotUpdateHandle::add_action_executor() , it will overwrite the teleop’s ActionExecutor, and would ultimately replace the RobotContext’s _action_executor which will be passed to the rxcpp::scheduler::worker to be scheduled.

I am wondering how I should go about this and if I should create a new RobotUpdateHandle::ActionExecutor in addition to the existing one in RobotContext. However, I think it seems like I might be overseeing something.

Chosen answer

Answer chosen by @lkw303 at 2022-03-18T09:52:21Z.
Answered by @mxgrey:

It’s intentionally left up to the system integrators (in this case you) to decide how to structure your implementation when you might receive different types of perform_action requests. There definitely is no need to modify the rmf_fleet_adapter source code. I can offer a simple strategy here:

using ActionExecutor = rmf_fleet_adapter::agv::RobotUpdateHnadle::ActionExecutor;
std::shared_ptr<std::unordered_map<std::string, std::function<ActionExecutor>>> executor_map;
ActionExecutor dispatching_executor = [executor_map](
    const std::string& category,
    const nlohmann::json& description,
    ActionExecution execution)
  {
    executor_map->at(category)(category, description, std::move(execution));
  };
robot_update_handle->set_action_executor(dispatching_executor);

Now you can hang onto executor_map and give it a different executor for each perform_action category that you’re expecting.

Posted by @mxgrey:

It’s intentionally left up to the system integrators (in this case you) to decide how to structure your implementation when you might receive different types of perform_action requests. There definitely is no need to modify the rmf_fleet_adapter source code. I can offer a simple strategy here:

using ActionExecutor = rmf_fleet_adapter::agv::RobotUpdateHnadle::ActionExecutor;
std::shared_ptr<std::unordered_map<std::string, std::function<ActionExecutor>>> executor_map;
ActionExecutor dispatching_executor = [executor_map](
    const std::string& category,
    const nlohmann::json& description,
    ActionExecution execution)
  {
    executor_map->at(category)(category, description, std::move(execution));
  };
robot_update_handle->set_action_executor(dispatching_executor);

Now you can hang onto executor_map and give it a different executor for each perform_action category that you’re expecting.


This is the chosen answer.