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