9#include <SimoxUtility/color/Color.h>
10#include <VirtualRobot/XML/RobotIO.h>
31 srv(srv), params(params)
42 VirtualRobot::RobotIO::RobotDescription::eStructure);
46 bool constexpr keepInQueue =
true;
48 _idleGazeTarget.
name =
"idle";
50 params.
defaultTarget, robot_->getRootNode()->getName(), robot_->getName());
59 resetRequestedTargets();
72 if (visualizationTask and visualizationTask->
isRunning())
74 visualizationTask->
stop();
79 visualizationTask->
start();
85 _clearGazeTargets.store(
true);
89 Scheduler::scheduleNextTarget()
91 bool constexpr debugQueue =
false;
93 auto debug = [&](std::string
const& step)
101 ARMARX_INFO <<
"Gaze target queue contents (" << step <<
"): ";
102 for (
auto const& targetInQueue : requestedTargets)
104 ARMARX_INFO <<
" #" << i++ <<
" " << targetInQueue;
108 if (requestedTargets.size() == 0)
110 ARMARX_WARNING <<
"No gaze targets in queue. At least the idle gaze target should be "
116 std::vector<gaze_targets::GazeTarget> newGazeTargets = [&]
118 std::scoped_lock<std::mutex> targetLock(_newGazeTargetsMutex);
119 std::vector<gaze_targets::GazeTarget> copy = _newGazeTargets;
120 _newGazeTargets.clear();
127 debug(
"before filter");
131 if (_clearGazeTargets.load())
133 resetRequestedTargets();
134 _clearGazeTargets.store(
false);
138 RequestedTargets newRequestedTargets;
140 for (
auto const& targetInQueue : requestedTargets)
142 if (not targetInQueue.isExpired(scheduleStep))
144 newRequestedTargets.emplace(targetInQueue);
148 ARMARX_INFO <<
"Gaze target " << targetInQueue.name <<
" expired.";
152 requestedTargets = newRequestedTargets;
155 debug(
"after filter, before insertion");
159 for (
auto const& target : newGazeTargets)
161 RequestedTargets newRequestedTargets;
162 newRequestedTargets.emplace(target);
164 for (
auto const& targetInQueue : requestedTargets)
166 if (targetInQueue.name ==
target.name)
171 else if (
target.priority.attentionType ==
173 targetInQueue.priority.attentionType ==
175 not targetInQueue.keepInQueue)
183 newRequestedTargets.emplace(targetInQueue);
187 requestedTargets = newRequestedTargets;
190 debug(
"after insertion, before selection");
194 std::optional<gaze_targets::GazeTarget>
const maybeNextTarget =
195 [&]() -> std::optional<gaze_targets::GazeTarget>
197 if (requestedTargets.empty())
202 return *requestedTargets.begin();
205 if (not maybeNextTarget.has_value())
207 ARMARX_WARNING <<
"Could not find any gaze targets after filtering. At least the idle "
208 "gaze target was expected. Trying to recover by resetting gaze "
210 _clearGazeTargets.store(
true);
214 auto const currentTarget = currentTargetBuffer.getUpToDateReadBuffer();
215 gaze_targets::GazeTarget
const nextTarget = maybeNextTarget.value();
217 if (not currentTarget.has_value() or currentTarget->isExpired() or
218 nextTarget != currentTarget)
220 submitControlTarget(nextTarget);
225 Scheduler::submitControlTarget(gaze_targets::GazeTarget
const& target)
228 currentTargetBuffer.getWriteBuffer() =
target;
229 currentTargetBuffer.commitWrite();
230 srv.controllerHandler->updateControllerTarget(target);
234 Scheduler::resetRequestedTargets()
236 ARMARX_INFO <<
"Resetting gaze targets queue, old requests are discarded.";
237 requestedTargets.clear();
239 ARMARX_INFO <<
"Adding idle target `" << params.defaultTarget.transpose() <<
"`.";
241 currentTargetBuffer.getWriteBuffer() = std::nullopt;
242 currentTargetBuffer.commitWrite();
244 requestedTargets.emplace(_idleGazeTarget);
248 Scheduler::visualizeActiveTarget()
250 if (not(params.visualizeTaskDrivenGazeTarget or params.visualizeStimulusDrivenTarget or
251 params.visualizeRandomEventTarget))
256 std::string
const activeTargetLayerName =
"active_target";
258 auto const currentTarget = currentTargetBuffer.getUpToDateReadBuffer();
262 bool visualize = currentTarget.has_value();
264 if (currentTarget.has_value())
266 switch (currentTarget->priority.attentionType)
269 visualize = params.visualizeTaskDrivenGazeTarget;
272 visualize = params.visualizeStimulusDrivenTarget;
275 visualize = params.visualizeRandomEventTarget;
284 srv.arviz->commitDeleteLayer(activeTargetLayerName);
290 ARMARX_VERBOSE <<
"Failed to synchronize robot. Cannot visualize targets.";
294 Eigen::Vector3f
const globalPosition = currentTarget->position.toGlobalEigen(robot_);
296 std::map<gaze_targets::AttentionType, simox::Color> attentionTypeColor{
298 simox::Color::gray(128, params.targetVizAlpha)},
300 simox::Color::orange(255, params.targetVizAlpha)},
302 simox::Color::red(255, params.targetVizAlpha)}};
304 auto const color = attentionTypeColor.at(currentTarget->priority.attentionType);
305 Eigen::Vector3f
const from =
306 robot_->getRobotNode(params.gazeOriginFrameName)->getGlobalPosition();
307 Eigen::Vector3f
const direction_vec = (globalPosition -
from).normalized();
308 Eigen::Vector3f
const to = (globalPosition -
from).
norm() > 750
309 ? Eigen::Vector3f(from + (direction_vec * 700))
310 : Eigen::Vector3f(globalPosition - (direction_vec * 50));
312 auto l = srv.arviz->layer(activeTargetLayerName);
313 l.add(armarx::viz::Sphere(
"target").position(globalPosition).radius(25).color(color));
314 l.add(armarx::viz::Arrow(
"gaze_direction")
315 .fromTo(from + (direction_vec * 50), to)
318 srv.arviz->commit(l);
324 std::scoped_lock<std::mutex> targetLock(_newGazeTargetsMutex);
326 _newGazeTargets.push_back(target);
332 if (task->isRunning())
338 if (visualizationTask->isRunning())
341 visualizationTask->stop();
static DateTime Now()
Current time on the virtual clock.
static void WaitFor(const Duration &duration)
Wait for a certain duration on the virtual clock.
static DateTime Invalid()
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
The FramedPosition class.
void start()
Starts the thread.
void stop()
Stops the thread.
bool isRunning() const
Retrieve running state of the thread.
void submitToQueue(gaze_targets::GazeTarget target)
Scheduler(const InjectedServices &srv, const Params ¶ms)
void resetPriorityQueue()
Business Object (BO) class of GazeTarget.
armarx::core::time::Duration duration
armarx::DateTime activationTimestamp
armarx::DateTime creationTimestamp
The Priority of a GazeTarget.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
void visualize(const algorithms::Costmap &costmap, viz::Layer &layer, const std::string &name, const float zOffset)
@ RandomEvent
Random Targets with lowest priority.
@ StimulusDriven
Stimulus-Driven attention is executed when there is no Task-Driven GazeTarget.
@ TaskDriven
Task-Driven attention has highest priority.
state::Type from(Eigen::Vector3f targetPosition)
SimplePeriodicTask(Ts...) -> SimplePeriodicTask< std::function< void(void)> >
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
double norm(const Point &a)
std::experimental::observer_ptr< ControllerHandlerInterface > controllerHandler
std::experimental::observer_ptr< armem::robot_state::VirtualRobotReader > virtualRobotReader
Eigen::Vector3f defaultTarget