CollisionAvoidanceImpedanceController.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 Jianfeng Gao ( jianfeng dot gao at kit dot edu )
17  * @date 2023
18  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19  * GNU General Public License
20  */
21 
23 
25 #include <RobotAPI/components/units/RobotUnit/RobotUnit.h> // FIXME avoid this
26 
28 
30 {
31  NJointControllerRegistration<NJointTSCollisionAvoidanceImpedanceMPController>
33  "NJointTSCollisionAvoidanceImpedanceMPController");
34 
37  const NJointControllerConfigPtr& config,
38  const VirtualRobot::RobotPtr& robot) :
39  NJointTaskspaceImpedanceController(robotUnit, config, robot),
41  {
42  ARMARX_IMPORTANT << getClassName() + " construction done";
43  }
44 
45  std::string
47  {
48  return "NJointTSCollisionAvoidanceImpedanceMPController";
49  }
50 
51  void
54  const Ice::Current& iceCurrent)
55  {
57  {
58  for (auto& pair : limb)
59  {
60  pair.second->rtFirstRun.store(true);
61  }
62  }
63  }
64 
65  void
67  {
68  std::lock_guard<std::recursive_mutex> lock(mtx_mps);
69  bool rtSafe = additionalTaskUpdateStatus();
70 
71  // when ft guard is enabled and rt is not safe due to ft trigger, then we stop the corresponding mp
72  std::map<std::string, bool> flagMPToStop;
73  for (auto& pair : limb)
74  {
75  flagMPToStop[pair.first] = not limb.at(pair.first)->controller.ftsensor.ftSafe.load();
76  pair.second->nonRTDeltaT =
77  pair.second->rtStatusInNonRT.accumulateTime - pair.second->nonRTAccumulateTime;
78  pair.second->nonRTAccumulateTime = pair.second->rtStatusInNonRT.accumulateTime;
79  }
80  if (hands)
81  {
82  for (auto& pair : hands->hands)
83  {
84  pair.second->nonRTDeltaT =
85  pair.second->rtsInNonRT.accumulateTime - pair.second->nonRTAccumulateTime;
86  pair.second->nonRTAccumulateTime = pair.second->rtsInNonRT.accumulateTime;
87  }
88  }
89 
90  std::map<std::string, bool> mpRunning;
91  for (auto& _mp : mps)
92  {
93  const auto mpNodeSet = _mp.second.mp->getNodeSetName();
94  mpRunning[_mp.second.mp->getMPName()] = _mp.second.mp->isRunning();
95 
96  auto search = flagMPToStop.find(mpNodeSet);
97  if (search != flagMPToStop.end() and flagMPToStop.at(mpNodeSet) and
98  _mp.second.mp->isRunning() and
99  (limb.at(mpNodeSet)->controller.ftsensor.isForceGuardEnabled() or
100  limb.at(mpNodeSet)->controller.ftsensor.isTorqueGuardEnabled()))
101  {
102  _mp.second.mp->stop();
103  ARMARX_INFO << "Due to force/torque safe guard, MP " << _mp.second.mp->getMPName()
104  << " is stopped at " << _mp.second.mp->getCanonicalValue();
105  }
106 
107  if (_mp.second.mp->isFinished())
108  {
109  continue;
110  }
111  if (_mp.second.mp->getRole() == "taskspace")
112  {
113  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
114  if (_mp.second.mp->isFirstRun())
115  {
116  ARMARX_INFO << "checking TSMP initial status ...";
117  /// Here we check if the TSMP start pose is too far away from the current pose, if so, we would
118  /// prefer to reset the mp start from the current pose.
119  const std::vector<double> mpStart = _mp.second.mp->getStartVec();
120  const auto mpStartPose = common::dVecToMat4(mpStart);
121  if (_mp.second.mp->getStartFromPrevTarget() or
123  arm->rtStatusInNonRT.currentPose,
124  mpStartPose,
125  "current pose",
126  "TSMP initial start pose",
127  arm->nonRtConfig.safeDistanceMMToGoal,
128  arm->nonRtConfig.safeRotAngleDegreeToGoal,
129  _mp.second.mp->getMPName() + "mp_set_target"))
130  {
131  if (_mp.second.mp->getStartFromPrevTarget())
132  {
133  ARMARX_INFO << "User requested to start the current TS MP from the "
134  "previous target pose";
135  }
136  else
137  {
139  << "deviation from current pose too large, reset MP start pose";
140  }
141  _mp.second.mp->validateInitialState(
142  common::mat4ToDVec(arm->rtStatusInNonRT.desiredPose));
143  }
144  ARMARX_INFO << "done";
145  }
146  mp::TSMPInputPtr in = std::dynamic_pointer_cast<mp::TSMPInput>(_mp.second.input);
147  in->pose = arm->rtStatusInNonRT.currentPose;
148  in->vel = arm->rtStatusInNonRT.currentTwist;
149  // in->deltaT = arm->rtStatusInNonRT.deltaT;
150  in->deltaT = arm->nonRTDeltaT;
151  }
152  else if (_mp.second.mp->getRole() == "nullspace")
153  {
154  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
155  mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
156  ARMARX_CHECK_EQUAL(arm->rtStatusInNonRT.numJoints,
157  arm->rtStatusInNonRT.jointPos.size());
158  in->angleRadian = arm->rtStatusInNonRT.jointPos;
159  in->angularVel = arm->rtStatusInNonRT.qvelFiltered;
160  in->deltaT = arm->nonRTDeltaT;
161  }
162  else if (_mp.second.mp->getRole() == "hand")
163  {
164  auto& hand = hands->hands.at(_mp.second.mp->getNodeSetName());
165  mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
166  in->angleRadian = hand->rtsInNonRT.jointPosition.value();
167  in->deltaT = hand->nonRTDeltaT;
168  }
169  }
170  if (not rtSafe)
171  {
173 
174  // return;
175  // Make sure that you do not call additionalTaskSetTarget before return;
176  // since we overwrite the arm->nonRtConfig in additionalTaskUpdateStatus() with user config, which does not
177  // align with the up-to-date mp status. userConfig is only updated to align with MP status everytime a MP
178  // finishes execution. Only then, user can use this controller as if no mp is there.
179  }
180  runMPs(rtSafe);
181 
182  /// set mp target to nonRT config data structure
183  for (auto& _mp : mps)
184  {
185  if (not mpRunning.at(_mp.second.mp->getMPName()))
186  {
187  continue;
188  }
189  for (auto& ftGuard : mpConfig.ftGuard)
190  {
191  if (ftGuard.mpName == _mp.second.mp->getMPName())
192  {
193  bool const forceGuard =
194  (ftGuard.force.has_value() and
195  ftGuard.force.value() >= _mp.second.mp->getCanonicalValue());
196  bool const torqueGuard =
197  (ftGuard.torque.has_value() and
198  ftGuard.torque.value() >= _mp.second.mp->getCanonicalValue());
199 
200  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
201  bool const resetForce =
202  not arm->controller.ftsensor.isForceGuardEnabled() and forceGuard;
203  bool const resetTorque =
204  not arm->controller.ftsensor.isTorqueGuardEnabled() and torqueGuard;
205  if (resetForce or resetTorque)
206  {
207  ARMARX_INFO << "Triggering force torque safety guard for "
208  << arm->kinematicChainName << " at can value "
209  << _mp.second.mp->getCanonicalValue();
210  }
211 
212  arm->nonRtConfig.ftConfig.enableSafeGuardForce = forceGuard;
213  arm->nonRtConfig.ftConfig.enableSafeGuardTorque = torqueGuard;
214  arm->controller.ftsensor.enableSafeGuard(resetForce, resetTorque);
215  }
216  }
217 
218  if (_mp.second.mp->getRole() == "taskspace")
219  {
220  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
221  mp::TSMPOutputPtr out =
222  std::dynamic_pointer_cast<mp::TSMPOutput>(_mp.second.output);
223 
224  /// Note that here we only report warning but still set target to RT, we rely on MP phase stop and
225  /// RT safety mechanism to stop or pause the action if needed
227  arm->rtStatusInNonRT.currentPose,
228  out->pose,
229  "current pose",
230  "TSMP pose",
231  arm->nonRtConfig.safeDistanceMMToGoal,
232  arm->nonRtConfig.safeRotAngleDegreeToGoal,
233  _mp.second.mp->getMPName() + "mp_set_target");
234  arm->nonRtConfig.desiredPose = out->pose;
235  arm->nonRtConfig.desiredTwist = out->vel;
236  }
237  else if (_mp.second.mp->getRole() == "nullspace")
238  {
239  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
240  mp::JSMPOutputPtr out =
241  std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
242  ARMARX_CHECK_EQUAL(arm->rtStatusInNonRT.numJoints, out->angleRadian.size());
243  arm->nonRtConfig.desiredNullspaceJointAngles.value() = out->angleRadian;
244  }
245  else if (_mp.second.mp->getRole() == "hand")
246  {
247  mp::JSMPOutputPtr out =
248  std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
249  auto& hand = hands->hands.at(_mp.second.mp->getNodeSetName());
250  mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
251  ARMARX_CHECK_EQUAL(hand->targetNonRT.jointPosition.value().size(),
252  out->angleRadian.size());
253  hand->targetNonRT.jointPosition.value() = out->angleRadian;
254  }
255  if (mpRunning.at(_mp.second.mp->getMPName()) and _mp.second.mp->isFinished())
256  {
257  ARMARX_INFO << "reset buffer for nonRtConfig of " << _mp.second.mp->getMPName();
258  for (auto& pair : limb)
259  {
260  auto& arm = pair.second;
261  arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->nonRtConfig);
262  }
263  for (auto& pair : limb)
264  {
265  userConfig.limbs.at(pair.first) = pair.second->nonRtConfig;
266  }
267  if (hands)
268  {
269  hands->reinitBuffer(userConfig.hands);
270  }
271  }
272  }
274  }
275 } // namespace armarx::control::njoint_mp_controller::task_space
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController
Brief description of class NJointTaskspaceImpedanceController.
Definition: ImpedanceController.h:49
armarx::control::njoint_mp_controller::task_space::registrationControllerNJointTSCollisionAvoidanceImpedanceMPController
NJointControllerRegistration< NJointTSCollisionAvoidanceImpedanceMPController > registrationControllerNJointTSCollisionAvoidanceImpedanceMPController("NJointTSCollisionAvoidanceImpedanceMPController")
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::handleRTNotSafeInNonRT
void handleRTNotSafeInNonRT()
Definition: ImpedanceController.cpp:216
armarx::control::common::mp::JSMPInputPtr
std::shared_ptr< JSMPInput > JSMPInputPtr
Definition: JSMP.h:47
RobotUnit.h
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::hands
core::HandControlPtr hands
Definition: ImpedanceController.h:165
armarx::control::common::detectAndReportPoseDeviationWarning
bool detectAndReportPoseDeviationWarning(const Eigen::Matrix4f &pose1, const Eigen::Matrix4f &pose2, const std::string &namePose1, const std::string &namePose2, float positionThrMM, float angleThrDeg, const std::string &who)
Definition: utils.cpp:646
armarx::control::njoint_mp_controller::task_space::NJointTSCollisionAvoidanceImpedanceMPController::getClassName
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
Definition: CollisionAvoidanceImpedanceController.cpp:46
armarx::control::common::mp::MPPool::runMPs
void runMPs(const bool rtSafe)
Definition: MPPool.cpp:87
armarx::control::njoint_mp_controller::task_space::NJointTSCollisionAvoidanceImpedanceMPController::NJointTSCollisionAvoidanceImpedanceMPController
NJointTSCollisionAvoidanceImpedanceMPController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
Definition: CollisionAvoidanceImpedanceController.cpp:36
armarx::control::common::mp::JSMPOutputPtr
std::shared_ptr< JSMPOutput > JSMPOutputPtr
Definition: JSMP.h:48
armarx::control::common::mp::MPPool::resetMPs
bool resetMPs(const ::armarx::aron::data::dto::DictPtr &dto, const std::map< std::string, VirtualRobot::RobotNodeSetPtr > &rnsMap)
Definition: MPPool.cpp:503
CollisionAvoidanceImpedanceController.h
armarx::control::common::mp::TSMPOutputPtr
std::shared_ptr< TSMPOutput > TSMPOutputPtr
Definition: TSMP.h:47
armarx::control::common::mp::MPPool::mtx_mps
std::recursive_mutex mtx_mps
Definition: MPPool.h:128
armarx::control::common::dVecToMat4
Eigen::Matrix4f dVecToMat4(const mplib::core::DVec &dvec)
create Eigen:Matrix4f from 7D double vector.
Definition: utils.cpp:230
armarx::control::njoint_controller::task_space::NJointTaskspaceCollisionAvoidanceImpedanceController
Brief description of class NJointTaskspaceCollisionAvoidanceImpedanceController.
Definition: CollisionAvoidanceImpedanceController.h:54
armarx::control::njoint_mp_controller::task_space::NJointTSCollisionAvoidanceImpedanceMPController::additionalTask
void additionalTask() override
Definition: CollisionAvoidanceImpedanceController.cpp:66
utils.h
armarx::control::njoint_mp_controller::task_space
This file is part of ArmarX.
Definition: AdmittanceController.cpp:29
armarx::control::njoint_mp_controller::task_space::NJointTSCollisionAvoidanceImpedanceMPController::updateMPConfig
void updateMPConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition: CollisionAvoidanceImpedanceController.cpp:52
armarx::control::common::MPType::hand
@ hand
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::controllableNodeSets
std::map< std::string, VirtualRobot::RobotNodeSetPtr > controllableNodeSets
Definition: ImpedanceController.h:166
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
IceUtil::Handle< class RobotUnit >
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::additionalTaskSetTarget
void additionalTaskSetTarget()
Definition: ImpedanceController.cpp:203
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::limb
std::map< std::string, ArmPtr > limb
Definition: ImpedanceController.h:161
armarx::control::common::mat4ToDVec
mplib::core::DVec mat4ToDVec(const Eigen::Matrix4f &mat)
convert Eigen:Matrix4f to 7D double vector.
Definition: utils.cpp:252
armarx::control::common::mp::MPPool::mps
std::map< std::string, MPInputOutput > mps
Definition: MPPool.h:127
armarx::control::common::mp::TSMPInputPtr
std::shared_ptr< TSMPInput > TSMPInputPtr
Definition: TSMP.h:46
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::additionalTaskUpdateStatus
bool additionalTaskUpdateStatus()
Definition: ImpedanceController.cpp:184
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::userConfig
ConfigDict userConfig
Definition: ImpedanceController.h:164
armarx::control::njoint_controller::task_space::NJointTaskspaceImpedanceController::robotUnit
RobotUnitPtr robotUnit
Definition: ImpedanceController.h:163
NJointControllerRegistry.h
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:19
armarx::control::common::mp::MPPool::mpConfig
MPListConfig mpConfig
this variable is only needed when constructing the MP instances, therefore you don't need to use trip...
Definition: MPPool.h:134