EasyFleet
A simple-by-default framework for multi-robot, multi-capability fleets built on ROS 2
Loading...
Searching...
No Matches
robot_handle_impl.hpp
1// Copyright 2026 Intelligent Robotics Lab
2//
3// This file is part of the project EasyFleet
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#ifndef EASYFLEET_MISSION_MANAGER__DETAIL__ROBOT_HANDLE_IMPL_HPP_
17#define EASYFLEET_MISSION_MANAGER__DETAIL__ROBOT_HANDLE_IMPL_HPP_
18
19// Out-of-line definition of RobotHandle::run_capability<ActionT>(),
20// deliberately *not* included from robot_handle.hpp itself: the template
21// body needs FleetSession as a complete type (session_->node()/
22// status_marker_publisher()), and robot_handle.hpp only forward-declares
23// FleetSession to break the circular include the other way round
24// (fleet_session.hpp already includes robot_handle.hpp in full). This
25// header is instead included from the bottom of fleet_session.hpp, the
26// one place both classes are simultaneously complete -- so any
27// translation unit that wants to call run_capability<ActionT>() needs
28// fleet_session.hpp (or simple_controller.hpp, which already pulls it in)
29// in scope, same as it already needs a real FleetSession/SimpleController
30// to make the call meaningful in the first place.
31
32#include <algorithm>
33#include <chrono>
34#include <memory>
35#include <stdexcept>
36#include <string>
37
38#include "easyfleet_mission_manager/fleet_session.hpp"
39#include "easyfleet_mission_manager/robot_handle.hpp"
40
41namespace easyfleet
42{
43
44template<typename ActionT>
46 const std::string & capability_type,
47 const typename ActionT::Goal & goal,
48 std::chrono::seconds timeout)
49{
50 if (!session_) {
51 // Never add_robot()-ed to a FleetSession -- capabilities_ is
52 // unconditionally empty in that case too (only FleetSession::add_robot()
53 // can populate it, and it always attach()es first), so this would
54 // otherwise be silently swallowed by the "not active" branch below,
55 // indistinguishable from a real, already-attached robot that simply
56 // hasn't announced this capability yet. A caller bug, not a runtime
57 // condition to tolerate quietly.
58 throw std::logic_error(
59 "RobotHandle::run_capability(\"" + capability_type + "\", ...): this handle was "
60 "never added to a FleetSession (call FleetSession::add_robot()/"
61 "SimpleController::add_robot() first).");
62 }
63
64 const auto it = std::find_if(
65 capabilities_.begin(), capabilities_.end(),
67 return info.capability == capability_type && info.active;
68 });
69 if (it == capabilities_.end()) {
70 easyfleet_mission_manager::safe_print(
71 std::string(easyfleet_mission_manager::ansi::yellow) + "[" + name_ + "/" +
72 capability_type + "] not active, skipping." + easyfleet_mission_manager::ansi::reset);
73 return;
74 }
75
77
78 auto running_it = running_.find(capability_type);
79 if (running_it == running_.end()) {
80 auto running = std::make_unique<Running>(
81 *session_->node(), it->action_name, name_, capability_type,
82 session_->status_marker_publisher());
83 running_it = running_.emplace(capability_type, std::move(running)).first;
84 }
85
86 auto * running = dynamic_cast<Running *>(running_it->second.get());
87 if (!running) {
88 throw std::logic_error(
89 "RobotHandle::run_capability(\"" + capability_type + "\", ...): this capability "
90 "type was already run with a different action type on this handle -- a "
91 "capability_type must mean the same ActionT for the life of a RobotHandle.");
92 }
93
94 running->run(goal, timeout);
95}
96
97} // namespace easyfleet
98
99#endif // EASYFLEET_MISSION_MANAGER__DETAIL__ROBOT_HANDLE_IMPL_HPP_
void run_capability(const std::string &capability_type, const typename ActionT::Goal &goal=typename ActionT::Goal(), std::chrono::seconds timeout=easyfleet_mission_manager::kRunTimeout)
Sends goal to capability_type and returns immediately – the counterpart to today's blocking easyfleet...
Definition robot_handle_impl.hpp:45
The one concrete RunningCapabilityBase implementation, parameterized by the actual action type a give...
Definition running_capability.hpp:86
void run(const typename ActionT::Goal &goal, std::chrono::seconds timeout)
Sends goal and starts tracking it.
Definition running_capability.hpp:114
Everything known about one running capability instance, gathered from its /capabilities (easyfleet_in...
Definition capability_info.hpp:33