Scheduler.cpp
Go to the documentation of this file.
1 /**
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @author VS_CODE_USER_NAME ( VS_CODE_USER_EMAIL )
17  * @date 2023
18  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19  * GNU General Public License
20  */
21 
22 
23 #include "Scheduler.h"
24 
26 
28 {
29 
30  void
31  Scheduler::init()
32  {
33  robot_ = srv.virtualRobotReader->getRobotWaiting(
34  params.robotName,
36  VirtualRobot::RobotIO::RobotDescription::eStructure);
37  ARMARX_CHECK_NOT_NULL(robot_) << params.robotName;
38 
39  srv.controllerHandler->createController();
40  submitIdleTarget();
41 
43 
44  srv.controllerHandler->activateController();
45 
47 
48  task = new armarx::SimplePeriodicTask<>([&]() { runPeriodically(); }, 100);
49  task->start();
50  }
51 
52  Scheduler::Scheduler(const InjectedServices& srv, const Params& params) :
53  srv(srv), params(params)
54  {
55  init();
56  }
57 
58  void
60  {
61  ARMARX_VERBOSE << "Resetting PriorityQueue, old requests are discarded";
62  {
63  std::scoped_lock<std::mutex> targetLock(targetMutex);
64  requestedTargets.clear();
65  }
66 
67  ARMARX_VERBOSE << "Removing current target";
68  currentTargetBuffer.getWriteBuffer() = std::nullopt;
69  currentTargetBuffer.commitWrite();
70 
71  ARMARX_INFO << "Adding idle target.";
72  submitIdleTarget();
73  }
74 
75  void
76  Scheduler::checkTargetDeadline()
77  {
78  bool deadlineViolation = false;
79  {
80  std::scoped_lock<std::mutex> targetLock(targetMutex);
81  if (currentDeadline.isValid() && currentDeadline <= armarx::Clock::Now())
82  {
83  deadlineViolation = true;
84  ARMARX_VERBOSE << "Deadline reached, deactivating target.";
85  currentDeadline = DateTime::Invalid();
86 
87  currentTargetBuffer.getWriteBuffer() = std::nullopt;
88  currentTargetBuffer.commitWrite();
89  }
90  }
91  if (deadlineViolation)
92  {
94  }
95  }
96 
97  void
98  Scheduler::submitIdleTarget()
99  {
100  ARMARX_INFO << "Default target is " << params.defaultTarget;
101 
102  const FramedPosition viewCenter(
103  params.defaultTarget, robot_->getRootNode()->getName(), robot_->getName());
104 
105  const auto infinite = armarx::Duration::MilliSeconds(-1);
106  const gaze_targets::TargetPriority priority(gaze_targets::AttentionType::RandomEvent, 0.0);
107 
108  // this target has lowest priority and will never be removed from the queue
109  {
110  std::scoped_lock<std::mutex> targetLock(targetMutex);
111  requestedTargets.emplace(
112  gaze_targets::GazeTarget("idle", viewCenter, priority, infinite, true));
113  }
114 
116  }
117 
118  void
119  Scheduler::visualizeActiveTarget()
120  {
121  if (not params.visuEnabled)
122  {
123  return;
124  }
125 
126  const std::string activeTargetLayerName = "active_target";
127 
128  const auto currentTarget = currentTargetBuffer.getUpToDateReadBuffer();
129 
130  if (not currentTarget.has_value()) // disable visu if target is not active
131  {
133  srv.arviz->commitDeleteLayer(activeTargetLayerName);
134  return;
135  }
136 
137  if (not srv.virtualRobotReader->synchronizeRobot(*robot_, armarx::Clock::Now()))
138  {
139  ARMARX_VERBOSE << "Failed to synchronize robot. Cannot visualize targets.";
140  return;
141  }
142 
143  const Eigen::Vector3f globalPosition = currentTarget->position.toGlobalEigen(robot_);
144 
145  std::map<gaze_targets::AttentionType, simox::Color> attentionTypeColor{
147  simox::Color::gray(128, params.targetVizAlpha)},
149  simox::Color::blue(255, params.targetVizAlpha)},
151  simox::Color::red(255, params.targetVizAlpha)}};
152 
153  // TODO include priority into coloring
154 
155  auto l = srv.arviz->layer(activeTargetLayerName);
156  l.add(armarx::viz::Sphere("target")
157  .position(globalPosition)
158  .radius(100)
159  .color(attentionTypeColor.at(currentTarget->priority.attentionType)));
160  srv.arviz->commit(l);
161  }
162 
163  void
164  Scheduler::runPeriodically()
165  {
166  checkTargetDeadline();
167  visualizeActiveTarget();
168  }
169 
170  void
172  {
173  {
174  std::scoped_lock<std::mutex> targetLock(targetMutex);
175 
176  // remove target if found in queue
177  // (otherwise, two targets with the same name but different priorities will be in the queue)
178  for (auto it = requestedTargets.cbegin(); it != requestedTargets.cend(); it++)
179  {
180  if (it->name == target.name)
181  {
182  ARMARX_VERBOSE << "Updating targetRequest: " << target.name;
183  requestedTargets.erase(it);
184  break;
185  }
186  }
187  // multiset automatically ensures order
188  requestedTargets.emplace(target);
189  }
190  }
191 
192  void
194  {
195  std::scoped_lock<std::mutex> targetLock(targetMutex);
196  if (requestedTargets.empty())
197  {
198  ARMARX_VERBOSE << "No requests, nothing to do.";
199  return;
200  }
201 
202  // reference to targetRequest with highest priority
203  // this will be only used in one of the if-else cases so that they do not
204  // influence each other
205  auto nextTarget = requestedTargets.cbegin();
206  ARMARX_VERBOSE << "Next target is " << nextTarget->name;
207 
208  ARMARX_DEBUG << "Targets in queue";
209  for (const auto& target : requestedTargets)
210  {
211  ARMARX_DEBUG << target;
212  }
213 
214  const auto currentTarget = currentTargetBuffer.getUpToDateReadBuffer();
215 
216  if (not currentTarget.has_value())
217  {
218  ARMARX_VERBOSE << "No currently active Targets, submitting new target: " << *nextTarget;
219 
220  submitControlTarget(*nextTarget);
221 
222  // keep or erase target after submission based on keepInQueue
223  if (nextTarget->keepInQueue)
224  {
225  ARMARX_VERBOSE << "The target is kept in the queue.";
226  }
227  else
228  {
229  requestedTargets.erase(nextTarget);
230  ARMARX_VERBOSE << "The target has been removed from the queue.";
231  }
232  }
233  else
234  {
235  if (nextTarget->priority >= currentTarget->priority)
236  {
237  ARMARX_VERBOSE << "requested Target priority > current Target priority ("
238  << nextTarget->priority << " > " << currentTarget->priority << ")";
239  // replaced target needs to be stopped properly, then next target will be
240  // scheduled automatically
241  submitControlTarget(*nextTarget);
242  }
243  else
244  {
245  ARMARX_VERBOSE << "current Target has higher priority (" << nextTarget->priority
246  << " <= " << currentTarget->priority
247  << ") waiting until it is reached";
248  }
249  }
250  }
251 
252  void
253  Scheduler::submitControlTarget(const gaze_targets::GazeTarget& target)
254  {
255  if (target.duration.toMicroSeconds() < 0)
256  {
257  // infinite duration
258  currentDeadline = armarx::DateTime::Invalid();
259  }
260  else
261  {
262  currentDeadline = armarx::Clock::Now() + target.duration;
263  }
264 
265  currentTargetBuffer.getWriteBuffer() = target;
266  currentTargetBuffer.commitWrite();
267 
268  srv.controllerHandler->updateControllerTarget(target);
269  }
270 
271 
272 } // namespace armarx::view_selection::gaze_scheduler
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::core::time::DateTime::isValid
bool isValid() const
Definition: DateTime.cpp:123
armarx::view_selection::gaze_scheduler::Scheduler::resetPriorityQueue
void resetPriorityQueue()
Definition: Scheduler.cpp:59
armarx::core::time::Clock::WaitFor
static void WaitFor(const Duration &duration)
Wait for a certain duration on the virtual clock.
Definition: Clock.cpp:99
ARMARX_CHECK_NOT_NULL
#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...
Definition: ExpressionException.h:206
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:668
armarx::view_selection::gaze_targets::GazeTarget
Business Object (BO) class of GazeTarget.
Definition: GazeTarget.h:39
armarx::viz::Sphere
Definition: Elements.h:133
armarx::view_selection::gaze_targets::AttentionType::TaskDriven
@ TaskDriven
Task-Driven attention has highest priority.
armarx::view_selection::gaze_scheduler::Scheduler::scheduleNextTarget
void scheduleNextTarget()
Definition: Scheduler.cpp:193
armarx::view_selection::gaze_scheduler::Scheduler::Params
Definition: Scheduler.h:56
armarx::view_selection::gaze_scheduler::Scheduler::InjectedServices::controllerHandler
std::experimental::observer_ptr< ControllerHandlerInterface > controllerHandler
Definition: Scheduler.h:53
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::view_selection::gaze_scheduler::Scheduler::Params::targetVizAlpha
int targetVizAlpha
Definition: Scheduler.h:62
armarx::view_selection::gaze_targets::AttentionType::RandomEvent
@ RandomEvent
Random Targets with lowest priority.
armarx::view_selection::gaze_scheduler::Scheduler::Scheduler
Scheduler(const InjectedServices &srv, const Params &params)
Definition: Scheduler.cpp:52
armarx::view_selection::gaze_scheduler::Scheduler::InjectedServices::arviz
std::experimental::observer_ptr< viz::Client > arviz
Definition: Scheduler.h:51
Scheduler.h
armarx::view_selection::gaze_targets::AttentionType::StimulusDriven
@ StimulusDriven
Stimulus-Driven attention is executed when there is no Task-Driven GazeTarget.
armarx::red
QColor red()
Definition: StyleSheets.h:78
armarx::view_selection::gaze_scheduler::Scheduler::Params::defaultTarget
Eigen::Vector3f defaultTarget
Definition: Scheduler.h:59
armarx::view_selection::gaze_scheduler::Scheduler::Params::robotName
std::string robotName
Definition: Scheduler.h:58
armarx::view_selection::gaze_scheduler
This file is part of ArmarX.
Definition: Component.cpp:57
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::view_selection::gaze_scheduler::Scheduler::Params::visuEnabled
bool visuEnabled
Definition: Scheduler.h:61
armarx::view_selection::gaze_scheduler::Scheduler::InjectedServices
Definition: Scheduler.h:47
armarx::view_selection::gaze_scheduler::Scheduler::InjectedServices::virtualRobotReader
std::experimental::observer_ptr< armem::robot_state::VirtualRobotReader > virtualRobotReader
Definition: Scheduler.h:50
armarx::core::time::Clock::Now
static DateTime Now()
Current time on the virtual clock.
Definition: Clock.cpp:93
Logging.h
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:38
armarx::core::time::DateTime::Invalid
static DateTime Invalid()
Definition: DateTime.cpp:57
armarx::core::time::Duration::MilliSeconds
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
Definition: Duration.cpp:48
armarx::SimplePeriodicTask
Usage:
Definition: ApplicationNetworkStats.h:32
armarx::view_selection::gaze_scheduler::Scheduler::submitToQueue
void submitToQueue(const gaze_targets::GazeTarget &target)
Definition: Scheduler.cpp:171