HeadIKUnit.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
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "HeadIKUnit.h"
25 
26 
29 
30 #include <VirtualRobot/XML/RobotIO.h>
31 #include <VirtualRobot/IK/GazeIK.h>
32 #include <VirtualRobot/LinkedCoordinate.h>
33 
34 #include <SimoxUtility/algorithm/string/string_tools.h>
35 
36 #include <memory>
37 
38 namespace armarx
39 {
40 
42  requested(false),
43  cycleTime(30),
44  newTargetSet(false)
45  {
46  targetPosition = new FramedPosition();
47  }
48 
49 
51  {
52  std::unique_lock lock(accessMutex);
53 
54  usingProxy(getProperty<std::string>("KinematicUnitName").getValue());
55  usingProxy(getProperty<std::string>("RobotStateComponentName").getValue());
56 
57 
58 
59  cycleTime = getProperty<int>("CycleTime").getValue();
60  offeringTopic("DebugDrawerUpdates");
61  offeringTopic(getProperty<std::string>("HeadIKUnitTopicName").getValue());
62  }
63 
64 
66  {
67  std::unique_lock lock(accessMutex);
68 
69  drawer = getTopic<DebugDrawerInterfacePrx>("DebugDrawerUpdates");
70 
71  kinematicUnitPrx = getProxy<KinematicUnitInterfacePrx>(getProperty<std::string>("KinematicUnitName").getValue());
72  robotStateComponentPrx = getProxy<RobotStateComponentInterfacePrx>(getProperty<std::string>("RobotStateComponentName").getValue());
73 
74 
75  //remoteRobotPrx = robotStateComponentPrx->getSynchronizedRobot();
76  localRobot = RemoteRobot::createLocalCloneFromFile(robotStateComponentPrx, VirtualRobot::RobotIO::RobotDescription::eStructure);
77  // localRobot = RemoteRobot::createLocalClone(robotStateComponentPrx);
78 
79 
80  headIKUnitListener = getTopic<armarx::HeadIKUnitListenerPrx>(getProperty<std::string>("HeadIKUnitTopicName").getValue());
81 
82  //std::string robotModelFile;
83  //ArmarXDataPath::getAbsolutePath("Armar3/robotmodel/ArmarIII.xml", robotModelFile);
84  //localRobot = VirtualRobot::RobotIO::loadRobot(robotModelFile.c_str(), VirtualRobot::RobotIO::eStructure);
85  //VirtualRobot::RobotPtr robotSnapshot(new RemoteRobot(remoteRobotPrx));
86  //localRobot->setConfig(robotSnapshot->getConfig());
87 
88  requested = false;
89 
90  if (execTask)
91  {
92  execTask->stop();
93  }
94 
95  execTask = new PeriodicTask<HeadIKUnit>(this, &HeadIKUnit::periodicExec, cycleTime, false, "HeadIKCalculator");
96  execTask->setDelayWarningTolerance(300);
97  execTask->start();
98 
99  }
100 
102  {
103  release();
104 
105  //std::unique_lock lock(accessMutex);
106  if (drawer)
107  {
108  drawer->removeSphereDebugLayerVisu("HeadViewTarget");
109  drawer->removeSphereDebugLayerVisu("HeadViewTargetSolution");
110  }
111 
112 
113 
114  if (execTask)
115  {
116  execTask->stop();
117  }
118  }
119 
121  {
122  }
123 
124 
125 
126  void HeadIKUnit::setCycleTime(Ice::Int milliseconds, const Ice::Current& c)
127  {
128  std::unique_lock lock(accessMutex);
129 
130  cycleTime = milliseconds;
131 
132  if (execTask)
133  {
134  execTask->changeInterval(cycleTime);
135  }
136  }
137 
138 
139  void HeadIKUnit::setHeadTarget(const std::string& robotNodeSetName, const FramedPositionBasePtr& targetPosition, const Ice::Current& c)
140  {
141  std::unique_lock lock(accessMutex);
142 
143  this->robotNodeSetNames = armarx::Split(robotNodeSetName, ",");
144  for (auto& setName : robotNodeSetNames)
145  {
146  simox::alg::trim(setName);
147  }
148  this->targetPosition->x = targetPosition->x;
149  this->targetPosition->y = targetPosition->y;
150  this->targetPosition->z = targetPosition->z;
151  this->targetPosition->frame = targetPosition->frame;
152 
153  FramedPositionPtr globalTarget = FramedPositionPtr::dynamicCast(targetPosition)->toGlobal(robotStateComponentPrx->getSynchronizedRobot());
154 
155  if (drawer && getProperty<bool>("VisualizeIKTarget").getValue())
156  {
157  drawer->setSphereDebugLayerVisu("HeadViewTarget",
158  globalTarget,
159  DrawColor {1, 0, 0, 0.7},
160  15);
161 
162 
163  }
164 
165  ARMARX_DEBUG << "new Head target set: " << *globalTarget << " for " << robotNodeSetName;
166 
167  newTargetSet = true;
168  }
169 
170 
171 
172 
173  void HeadIKUnit::init(const Ice::Current& c)
174  {
175  }
176 
177  void HeadIKUnit::start(const Ice::Current& c)
178  {
179  }
180 
181  void HeadIKUnit::stop(const Ice::Current& c)
182  {
183  }
184 
185  UnitExecutionState HeadIKUnit::getExecutionState(const Ice::Current& c)
186  {
187  switch (getState())
188  {
189  case eManagedIceObjectStarted:
190  return eUnitStarted;
191 
192  case eManagedIceObjectInitialized:
193  case eManagedIceObjectStarting:
194  return eUnitInitialized;
195 
196  case eManagedIceObjectExiting:
197  case eManagedIceObjectExited:
198  return eUnitStopped;
199 
200  default:
201  return eUnitConstructed;
202  }
203  }
204 
205 
206 
207 
208  void HeadIKUnit::request(const Ice::Current& c)
209  {
210  std::unique_lock lock(accessMutex);
211 
212  requested = true;
213  ARMARX_IMPORTANT << "Requesting HeadIKUnit";
214 
215  if (execTask)
216  {
217  execTask->stop();
218  }
219 
220  execTask = new PeriodicTask<HeadIKUnit>(this, &HeadIKUnit::periodicExec, cycleTime, false, "TCPVelocityCalculator");
221  execTask->start();
222  ARMARX_IMPORTANT << "Requested HeadIKUnit";
223  }
224 
225 
226 
227 
228  void HeadIKUnit::release(const Ice::Current& c)
229  {
230  std::unique_lock lock(accessMutex);
231 
232  ARMARX_INFO << "Releasing HeadIKUnit";
233  requested = false;
234 
235  if (drawer)
236  {
237  drawer->removeSphereDebugLayerVisu("HeadViewTarget");
238  drawer->removeSphereDebugLayerVisu("HeadViewTargetSolution");
239  }
240 
241  // why do we stop the kin unit?
242  /*try
243  {
244  if (kinematicUnitPrx)
245  kinematicUnitPrx->stop();
246  } catch (...)
247  {
248  ARMARX_IMPORTANT << "Released HeadIKUnit failed";
249  }*/
250 
251  ARMARX_INFO << "Released HeadIKUnit";
252  }
253 
254 
255 
256 
257  void HeadIKUnit::periodicExec()
258  {
259  bool doCalculation = false;
260 
261  {
262  std::unique_lock lock(accessMutex, std::defer_lock);
263 
264  if (lock.try_lock())
265  {
266  doCalculation = requested && newTargetSet;
267  newTargetSet = false;
268  }
269  else
270  {
271  return;
272  }
273  }
274 
275 
276  if (doCalculation)
277  {
278  std::unique_lock lock(accessMutex);
279 
280  VirtualRobot::RobotNodeSetPtr kinematicChain;
281  bool foundSolution = false;
282  NameValueMap targetJointAngles;
283  NameControlModeMap controlModes;
284  std::set<std::string> possiblyInvolvedJointNames;
285  // // set all involved joints initially to zero
286  for (auto robotNodeSetName : robotNodeSetNames)
287  {
288  kinematicChain = localRobot->getRobotNodeSet(robotNodeSetName);
289  for (unsigned int i = 0; i < kinematicChain->getSize(); i++)
290  {
291  possiblyInvolvedJointNames.insert(kinematicChain->getNode(i)->getName());
292  // kinematicChain->getNode(i)->setJointValue(0.0f);
293  // targetJointAngles[kinematicChain->getNode(i)->getName()] = 0.0f;
294  // controlModes[kinematicChain->getNode(i)->getName()] = ePositionControl;
295  }
296  }
297  FramedPositionPtr globalPos;
298  float error = -1;
299  //VirtualRobot::RobotPtr robotSnapshot(new RemoteRobot(remoteRobotPrx));
300  //localRobot->setConfig(robotSnapshot->getConfig());
301  std::string selectedRobotNodeSetName;
302  for (auto robotNodeSetName : robotNodeSetNames)
303  {
304  RemoteRobot::synchronizeLocalClone(localRobot, robotStateComponentPrx);
305 
306  kinematicChain = localRobot->getRobotNodeSet(robotNodeSetName);
307  auto tcpNode = kinematicChain->getTCP();
308  VirtualRobot::RobotNodePrismaticPtr virtualPrismaticJoint;
309 
310  virtualPrismaticJoint = std::dynamic_pointer_cast<VirtualRobot::RobotNodePrismatic>(tcpNode);
311  if (!virtualPrismaticJoint)
312  {
313  ARMARX_WARNING << deactivateSpam(10, robotNodeSetName) << "Head IK Kinematic Chain TCP is not a prismatic joint! skipping joint set";
314  continue;
315  }
316 
317  // set other not-used joints to 0
318  for (auto& nodeName : possiblyInvolvedJointNames)
319  {
320  if (!kinematicChain->hasRobotNode(nodeName))
321  {
322  localRobot->getRobotNode(nodeName)->setJointValue(0.0f);
323  targetJointAngles[nodeName] = 0.0f;
324  controlModes[nodeName] = ePositionControl;
325  }
326  }
327 
328  ARMARX_DEBUG << deactivateSpam(5) << VAROUT(virtualPrismaticJoint->getName()) << " " << VAROUT(kinematicChain->getName());
329  VirtualRobot::GazeIK ikSolver(kinematicChain, virtualPrismaticJoint);
330  ikSolver.enableJointLimitAvoidance(true);
331  ikSolver.setup(10, 30, 20);
332  //ikSolver.setVerbose(true);
333 
334  globalPos = targetPosition->toGlobal(localRobot);
335  ARMARX_DEBUG << "Calculating IK for target position " << globalPos->output();
336  auto start = IceUtil::Time::now();
337  bool solutionFound = ikSolver.solve(globalPos->toEigen());
338  auto duration = (IceUtil::Time::now() - start);
339 
340  if (duration.toMilliSeconds() > 500)
341  {
342  ARMARX_INFO << "Calculating Gaze IK took " << duration.toMilliSeconds() << " ms";
343  }
344  Eigen::Vector3f position = globalPos->toEigen() - kinematicChain->getTCP()->getGlobalPose().block(0, 3, 3, 1);
345  error = position.norm();
346  if (!solutionFound)
347  {
348 
349  if (error < 150)
350  {
351  foundSolution = true;
352  selectedRobotNodeSetName = robotNodeSetName;
353  ARMARX_INFO << "IKSolver found no solution! applying best solution with " << error << "mm error";
354  break;
355  }
356  }
357  else
358  {
359  foundSolution = true;
360  selectedRobotNodeSetName = robotNodeSetName;
361  break;
362  }
363  }
364  if (!foundSolution)
365  {
366  ARMARX_WARNING << "IKSolver found no solution! " << error << "mm error";
367  return;
368  }
369  ARMARX_DEBUG << "Solution found with " << selectedRobotNodeSetName << " - remaining error: " << error << " mm";
370 
371  if (drawer && localRobot->hasRobotNode("Cameras") && getProperty<bool>("VisualizeIKTarget").getValue())
372  {
373  Vector3Ptr startPos = new Vector3(localRobot->getRobotNode("Cameras")->getGlobalPose());
374  drawer->setSphereDebugLayerVisu("HeadViewTargetSolution",
375  startPos,
376  DrawColor {0, 1, 1, 0.2},
377  17);
378  }
379  auto tcpNode = kinematicChain->getTCP();
380  for (int i = 0; i < (signed int)kinematicChain->getSize(); i++)
381  {
382  if (kinematicChain->getNode(i) != tcpNode)
383  {
384  targetJointAngles[kinematicChain->getNode(i)->getName()] = kinematicChain->getNode(i)->getJointValue();
385  controlModes[kinematicChain->getNode(i)->getName()] = ePositionControl;
386  }
387 
388  ARMARX_DEBUG << kinematicChain->getNode(i)->getName() << ": " << kinematicChain->getNode(i)->getJointValue();
389  }
390 
391 
392 
393  if (headIKUnitListener)
394  {
395  headIKUnitListener->reportHeadTargetChanged(targetJointAngles, globalPos);
396  }
397 
398  try
399  {
400  kinematicUnitPrx->switchControlMode(controlModes);
401  ARMARX_DEBUG << "setting new joint angles" << targetJointAngles;
402  kinematicUnitPrx->setJointAngles(targetJointAngles);
403  }
404  catch (...)
405  {
406  ARMARX_IMPORTANT << "setJointAngles failed";
407  }
408 
409  }
410  }
411 
412 
413 
414 
416  {
418  }
419 
420 
421 
422 }
armarx::ManagedIceObject::setName
void setName(std::string name)
Override name of well-known object.
Definition: ManagedIceObject.cpp:426
armarx::HeadIKUnit::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: HeadIKUnit.cpp:101
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::RemoteRobot::synchronizeLocalClone
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
Definition: RemoteRobot.cpp:448
armarx::RemoteRobot::createLocalCloneFromFile
static VirtualRobot::RobotPtr createLocalCloneFromFile(RobotStateComponentInterfacePrx robotStatePrx, VirtualRobot::RobotIO::RobotDescription loadMode=VirtualRobot::RobotIO::eFull)
This is a convenience function for createLocalClone, which automatically gets the filename from the R...
Definition: RemoteRobot.cpp:441
armarx::HeadIKUnit::request
void request(const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:208
armarx::HeadIKUnit::release
void release(const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:228
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:35
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:725
armarx::HeadIKUnit::HeadIKUnit
HeadIKUnit()
Definition: HeadIKUnit.cpp:41
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::HeadIKUnit::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: HeadIKUnit.cpp:120
armarx::HeadIKUnit::setHeadTarget
void setHeadTarget(const std::string &robotNodeSetName, const FramedPositionBasePtr &targetPosition, const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:139
armarx::HeadIKUnit::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: HeadIKUnit.cpp:65
armarx::HeadIKUnit::stop
void stop(const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:181
StringHelpers.h
IceInternal::Handle< FramedPosition >
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::HeadIKUnitPropertyDefinitions
Definition: HeadIKUnit.h:43
armarx::FramedPositionPtr
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition: FramedPose.h:134
armarx::HeadIKUnit::init
void init(const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:173
armarx::HeadIKUnit::setCycleTime
void setCycleTime(Ice::Int milliseconds, const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:126
armarx::HeadIKUnit::getExecutionState
UnitExecutionState getExecutionState(const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:185
armarx::control::njoint_controller::platform::platform_follower_controller::NameValueMap
std::map< std::string, float > NameValueMap
Definition: PlatformFollowerController.h:91
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::ManagedIceObject::offeringTopic
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
Definition: ManagedIceObject.cpp:290
IceUtil::Handle< class PropertyDefinitionContainer >
memoryx::KBM::Vector3
Eigen::Vector3d Vector3
Definition: kbm.h:41
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:916
armarx::Vector3Ptr
IceInternal::Handle< Vector3 > Vector3Ptr
Definition: Pose.h:165
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:92
armarx::HeadIKUnit::start
void start(const Ice::Current &c=Ice::emptyCurrent) override
Definition: HeadIKUnit.cpp:177
armarx::PeriodicTask
Definition: ArmarXManager.h:70
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:34
armarx::HeadIKUnit::createPropertyDefinitions
PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: HeadIKUnit.cpp:415
ArmarXDataPath.h
HeadIKUnit.h
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:151
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::HeadIKUnit::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: HeadIKUnit.cpp:50