Task.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package RobotComponents
19  * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
20  * @date 2015
21  * @copyright http://www.gnu.org/licenses/gpl.txt
22  * GNU General Public License
23  */
24 
25 #include "Task.h"
26 
27 #include "../../util/PlanningUtil.h"
28 
30 {
31  Task::Task(const CSpaceBasePtr& cspace, const VectorXf& startCfg, const VectorXf& goalCfg, const std::string& taskName, Ice::Long maximalPlanningTimeInSeconds, float dcdStep, Ice::Long workerCount)
32  {
33  this->cspace = cspace;
34  this->startCfg = startCfg;
35  this->goalCfg = goalCfg;
36  this->dcdStep = dcdStep;
37  this->maximalPlanningTimeInSeconds = maximalPlanningTimeInSeconds;
38  this->workerCount = workerCount;
39  this->taskName = taskName;
40  }
41 
42  void Task::abortTask(const Ice::Current&)
43  {
44  std::lock_guard<std::mutex> lock {mtx};
45  setTaskStatus((getTaskStatus() != TaskStatus::eDone) ? TaskStatus::ePlanningAborted : TaskStatus::eDone);
46  //worker will be aborted in run()
47  doneCV.notify_all();
48  }
49 
50  Path Task::getPath(const Ice::Current&) const
51  {
52  std::lock_guard<std::mutex> lock {mtx};
53  return solution;
54  }
55 
56  void Task::workerHasAborted(Ice::Long workerId, const Ice::Current&)
57  {
58  std::lock_guard<std::mutex> lock {mtx};
59  ARMARX_CHECK_EXPRESSION(static_cast<std::size_t>(workerId) < workerAbortedFlags.size());
60  workerAbortedFlags.at(workerId) = true;
61  }
62 
63  void Task::run(const RemoteObjectNodePrxList& remoteNodes, const Ice::Current&)
64  {
66  ARMARX_CHECK_EXPRESSION(std::all_of(remoteNodes.begin(), remoteNodes.end(), [](const RemoteObjectNodeInterfacePrx & n)
67  {
68  return n;
69  }));
70  //init
71  workerAbortedFlags.assign(workerCount, false);
72  setTaskStatus(TaskStatus::ePlanning);
73  const std::string topicName = "RRTConnectUpdateTopic:" + getProxy()->ice_getIdentity().name;
74  //check trivial cases
75 
76  const auto startIsCollisionFree = cspace->isCollisionFree(std::pair<const Ice::Float*, const Ice::Float*> {startCfg.data(), startCfg.data() + startCfg.size()});
77  if (!startIsCollisionFree)
78  {
79  setTaskStatus(TaskStatus::ePlanningFailed);
80  ARMARX_WARNING << "MotionPlanningTask " << taskName << " trivially failed! start cfg in collision. start:\n" << startCfg;
81  return;
82  }
83 
84  const auto goalIscollisionFree = cspace->isCollisionFree(std::pair<const Ice::Float*, const Ice::Float*> { goalCfg.data(), goalCfg.data() + goalCfg.size()});
85  if (!goalIscollisionFree)
86  {
87  setTaskStatus(TaskStatus::ePlanningFailed);
88  ARMARX_WARNING << "MotionPlanningTask " << taskName << " trivially failed! goal cfg in collision. goal:\n" << goalCfg;
89  return;
90  }
91 
92  if (euclideanDistance(startCfg.begin(), startCfg.end(), goalCfg.begin()) <= dcdStep)
93  {
94  solution.nodes.emplace_back(startCfg);
95  solution.nodes.emplace_back(goalCfg);
96  solution.pathName = taskName + "_trivialPath_" + ice_staticId();
97  ARMARX_WARNING << "MotionPlanningTask " << taskName << " trivially succeeded! (start and goal less than dcd step size apart!)";
98  setTaskStatus(TaskStatus::eDone);
99  return;
100  }
101 
102  //start workers
103  std::unique_lock<std::mutex> lock {mtx};
104  std::vector<RemoteHandle<WorkerNodeBasePrx>> workers;
105  WorkerNodeBasePrxList workerProxies;
106 
107  workers.reserve(workerCount);
108  auto workerToStart = workerCount;
109  const auto taskName = getProxy()->ice_getIdentity().name;
110  for (auto& ron : remoteNodes)
111  {
112  auto maxWorkerForNode = ron->getNumberOfCores();
113  for (Ice::Long i = 0; i < maxWorkerForNode && workerToStart; ++i)
114  {
115  WorkerNodeBasePtr worker {new WorkerNode{
116  cspace->clone(),
117  startCfg,
118  goalCfg,
119  dcdStep,
120  TaskBasePrx::uncheckedCast(getProxy()),
121  topicName,
122  static_cast<Ice::Long>(workers.size()),
123  workerCount
124  }
125  };
126  const std::string workerName = ManagedIceObject::generateSubObjectName(taskName, "RRTConnectWorker:" + to_string(workers.size()));
127  workers.emplace_back(ron->registerRemoteHandledObject(workerName, worker));
128  workerProxies.emplace_back(*(workers.back()));
129  --workerToStart;
130  }
131  if (!workerToStart)
132  {
133  break;
134  }
135  }
136 
137  //distribute worker proxy
138  for (auto& w : workers)
139  {
140  w->setWorkerNodes(workerProxies);
141  }
142 
143  //wait for done or timeout
144  const auto endTime = std::chrono::system_clock::now() + std::chrono::seconds {maximalPlanningTimeInSeconds};
145 
146  while (true)
147  {
148  doneCV.wait_for(lock, std::chrono::milliseconds {10});
149  if (endTime < std::chrono::system_clock::now())
150  {
151  setTaskStatus(TaskStatus::ePlanningFailed);
152  break;
153  }
154  if (getTaskStatus() != TaskStatus::ePlanning)
155  {
156  break;
157  }
158  }
159 
160  //wait for all stopped
161  while (std::any_of(workerAbortedFlags.begin(), workerAbortedFlags.end(), [](bool b)
162  {
163  return !b;
164  }))
165  {
166  for (auto& w : workers)
167  {
168  w->abort();
169  }
170  doneCV.wait_for(lock, std::chrono::milliseconds {10});
171  }
172  }
173 
174  void Task::setPath(const Path& path, const Ice::Current&)
175  {
176  std::lock_guard<std::mutex> lock {mtx};
177  solution = path;
178  solution.pathName = taskName + "_path_" + ice_staticId();
179  setTaskStatus(TaskStatus::eDone);
180  doneCV.notify_all();
181  }
182 
184  {
186  cspace->initCollisionTest();
187  }
188 }
189 
armarx::rrtconnect::Task::mtx
std::mutex mtx
Definition: Task.h:109
armarx::rrtconnect::Task::setPath
void setPath(const Path &path, const Ice::Current &=Ice::emptyCurrent) override
Definition: Task.cpp:174
armarx::rrtconnect::Task::abortTask
void abortTask(const Ice::Current &=Ice::emptyCurrent) override
Aborts planning.
Definition: Task.cpp:42
armarx::MotionPlanningTask::getProxy
MotionPlanningTaskBasePrx & getProxy()
Definition: MotionPlanningTask.h:78
armarx::MotionPlanningTask::postEnqueueing
virtual void postEnqueueing()
Called by the planning server after the task was enqueued.
Definition: MotionPlanningTask.h:70
armarx::MotionPlanningTask::getTaskStatus
TaskStatus::Status getTaskStatus(const Ice::Current &=Ice::emptyCurrent) const override
Definition: MotionPlanningTask.h:85
armarx::rrtconnect::Task::workerHasAborted
void workerHasAborted(Ice::Long workerId, const Ice::Current &=Ice::emptyCurrent) override
Definition: Task.cpp:56
armarx::rrtconnect::Task::Task
Task()=default
Ctor used by object factories.
armarx::rrtconnect::Task::postEnqueueing
void postEnqueueing() override
Called by the planning server after the task was enqueued.
Definition: Task.cpp:183
armarx::rrtconnect::Task::solution
Path solution
Definition: Task.h:112
armarx::rrtconnect
Definition: Task.cpp:29
armarx::ManagedIceObject::generateSubObjectName
static std::string generateSubObjectName(const std::string &superObjectName, const std::string &subObjectName)
Generates a unique name for a sub object from a general name and unique name.
Definition: ManagedIceObject.cpp:117
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:917
Task.h
armarx::rrtconnect::WorkerNode
Definition: WorkerNode.h:53
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::rrtconnect::Task::getPath
Path getPath(const Ice::Current &=Ice::emptyCurrent) const override
Definition: Task.cpp:50
armarx::euclideanDistance
float euclideanDistance(IteratorType1 first1, IteratorType1 last1, IteratorType2 first2)
Returns the euclidean distance.
Definition: Metrics.h:94
armarx::rrtconnect::Task::workerAbortedFlags
std::vector< bool > workerAbortedFlags
Definition: Task.h:114
armarx::rrtconnect::Task::run
void run(const RemoteObjectNodePrxList &remoteNodes, const Ice::Current &=Ice::emptyCurrent) override
Runs the task.
Definition: Task.cpp:63
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::MotionPlanningTask::setTaskStatus
bool setTaskStatus(TaskStatus::Status newTaskStatus, const Ice::Current &=Ice::emptyCurrent) override
Definition: MotionPlanningTask.cpp:30
armarx::armem::server::ltm::detail::mixin::Path
std::filesystem::path Path
Definition: DiskStorageMixin.h:17
armarx::rrtconnect::Task::doneCV
std::condition_variable doneCV
Definition: Task.h:110
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186