MixedImpedanceVelocityController.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 2024
18  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19  * GNU General Public License
20  */
21 
23 
24 #include <VirtualRobot/MathTools.h>
25 #include <VirtualRobot/Nodes/RobotNode.h>
26 #include <VirtualRobot/RobotNodeSet.h>
27 
29 #include <RobotAPI/components/units/RobotUnit/RobotUnit.h> // FIXME avoid this
30 
32 
34 {
35  NJointControllerRegistration<NJointTSMixedImpedanceVelocityMPController>
37  "NJointTSMixedImpedanceVelocityMPController");
38 
40  const RobotUnitPtr& robotUnit,
41  const NJointControllerConfigPtr& config,
42  const VirtualRobot::RobotPtr& robot) :
44  {
45  ARMARX_IMPORTANT << getClassName() + " construction done";
46  }
47 
48  std::string
50  {
51  return "NJointTSMixedImpedanceVelocityMPController";
52  }
53 
54  void
57  const Ice::Current& iceCurrent)
58  {
60  {
61  for (auto& pair : limb)
62  {
63  pair.second->rtFirstRun.store(true);
64  }
65  }
66  }
67 
68  void
70  {
71  std::lock_guard<std::recursive_mutex> lock(mtx_mps);
72  // bool rtSafe = additionalTaskUpdateStatus();
73  auto [rtTargetSafe, ftSafe] = additionalTaskUpdateStatus();
74 
75  std::map<std::string, bool> mpRunning;
76  for (auto& _mp : mps)
77  {
78  mpRunning[_mp.second.mp->getMPName()] = _mp.second.mp->isRunning();
79  if (_mp.second.mp->isFinished())
80  {
81  continue;
82  }
83  if (_mp.second.mp->getRole() == "taskspace")
84  {
85  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
86  if (_mp.second.mp->isFirstRun())
87  {
88  ARMARX_INFO << "checking TSMP initial status ...";
89  /// Here we check if the TSMP start pose is too far away from the current pose, if so, we would
90  /// prefer to reset the mp start from the current pose.
91  const std::vector<double> mpStart = _mp.second.mp->getStartVec();
92  const auto mpStartPose = common::dVecToMat4(mpStart);
94  arm->rtStatusInNonRT.currentPose,
95  mpStartPose,
96  "current pose",
97  "TSMP initial start pose",
98  arm->nonRtConfig.safeDistanceMMToGoal,
99  arm->nonRtConfig.safeRotAngleDegreeToGoal,
100  _mp.second.mp->getMPName() + "mp_set_target"))
101  {
102  ARMARX_INFO << "deviation from current pose too large, reset MP start pose";
103  _mp.second.mp->validateInitialState(
104  common::mat4ToDVec(arm->rtStatusInNonRT.currentPose));
105  }
106  ARMARX_INFO << "done";
107  }
108  mp::TSMPInputPtr in = std::dynamic_pointer_cast<mp::TSMPInput>(_mp.second.input);
109  in->pose = arm->rtStatusInNonRT.currentPose;
110  in->vel = arm->rtStatusInNonRT.currentTwist;
111  in->deltaT = arm->rtStatusInNonRT.deltaT;
112  }
113  else if (_mp.second.mp->getRole() == "nullspace")
114  {
115  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
116  mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
117  ARMARX_CHECK_EQUAL(arm->rtStatusInNonRT.numJoints,
118  arm->rtStatusInNonRT.jointPos.size());
119  in->angleRadian = arm->rtStatusInNonRT.jointPos;
120  in->angularVel = arm->rtStatusInNonRT.qvelFiltered;
121  in->deltaT = arm->rtStatusInNonRT.deltaT;
122  }
123  else if (_mp.second.mp->getRole() == "hand")
124  {
125  auto& hand = hands->hands.at(_mp.second.mp->getNodeSetName());
126  mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
127  in->angleRadian =
128  hand->bufferRTToNonRT.getUpToDateReadBuffer().jointPosition.value();
129  in->deltaT = hand->bufferRTToNonRT.getReadBuffer().deltaT;
130  }
131  }
132  if (not rtTargetSafe)
133  {
135 
136  // return;
137  // Make sure that you do not call additionalTaskSetTarget before return;
138  // since we overwrite the arm->nonRtConfig in additionalTaskUpdateStatus() with user config, which does not
139  // align with the up-to-date mp status. userConfig is only updated to align with MP status everytime a MP
140  // finishes execution. Only then, user can use this controller as if no mp is there.
141  }
142  runMPs(rtTargetSafe);
143 
144  /// set mp target to nonRT config data structure
145  for (auto& _mp : mps)
146  {
147  if (not mpRunning.at(_mp.second.mp->getMPName()))
148  {
149  continue;
150  }
151  for (auto& ftGuard : mpConfig.ftGuard)
152  {
153  if (ftGuard.mpName == _mp.second.mp->getMPName())
154  {
155  bool const forceGuard =
156  (ftGuard.force.has_value() and
157  ftGuard.force.value() >= _mp.second.mp->getCanonicalValue());
158  bool const torqueGuard =
159  (ftGuard.torque.has_value() and
160  ftGuard.torque.value() >= _mp.second.mp->getCanonicalValue());
161 
162  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
163  bool const resetForce =
164  not arm->controller.ftsensor.isForceGuardEnabled() and forceGuard;
165  bool const resetTorque =
166  not arm->controller.ftsensor.isTorqueGuardEnabled() and torqueGuard;
167  if (resetForce or resetTorque)
168  {
169  ARMARX_INFO << "Triggering force torque safety guard for "
170  << arm->kinematicChainName << " at can value "
171  << _mp.second.mp->getCanonicalValue();
172  }
173 
174  arm->nonRtConfig.ftConfig.enableSafeGuardForce = forceGuard;
175  arm->nonRtConfig.ftConfig.enableSafeGuardTorque = torqueGuard;
176  arm->controller.ftsensor.enableSafeGuard(resetForce, resetTorque);
177  }
178  }
179 
180  if (_mp.second.mp->getRole() == "taskspace")
181  {
182  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
183  mp::TSMPOutputPtr out =
184  std::dynamic_pointer_cast<mp::TSMPOutput>(_mp.second.output);
185 
186  /// Note that here we only report warning but still set target to RT, we rely on MP phase stop and
187  /// RT safety mechanism to stop or pause the action if needed
189  arm->rtStatusInNonRT.currentPose,
190  out->pose,
191  "current pose",
192  "TSMP pose",
193  arm->nonRtConfig.safeDistanceMMToGoal,
194  arm->nonRtConfig.safeRotAngleDegreeToGoal,
195  _mp.second.mp->getMPName() + "mp_set_target");
196  arm->nonRtConfig.desiredPose = out->pose;
197  arm->nonRtConfig.desiredTwist = out->vel;
198  }
199  else if (_mp.second.mp->getRole() == "nullspace")
200  {
201  auto& arm = limb.at(_mp.second.mp->getNodeSetName());
202  mp::JSMPOutputPtr out =
203  std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
204  ARMARX_CHECK_EQUAL(arm->rtStatusInNonRT.numJoints, out->angleRadian.size());
205  arm->nonRtConfig.desiredNullspaceJointAngles.value() = out->angleRadian;
206  }
207  else if (_mp.second.mp->getRole() == "hand")
208  {
209  mp::JSMPOutputPtr out =
210  std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
211  auto& hand = hands->hands.at(_mp.second.mp->getNodeSetName());
212  mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
213  ARMARX_CHECK_EQUAL(hand->targetNonRT.jointPosition.value().size(),
214  out->angleRadian.size());
215  hand->targetNonRT.jointPosition.value() = out->angleRadian;
216  }
217  if (mpRunning.at(_mp.second.mp->getMPName()) and _mp.second.mp->isFinished())
218  {
219  ARMARX_INFO << "reset buffer for nonRtConfig of " << _mp.second.mp->getMPName();
220  for (auto& pair : limb)
221  {
222  auto& arm = pair.second;
223  arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->nonRtConfig);
224  }
225  for (auto& pair : limb)
226  {
227  userConfig.limbs.at(pair.first) = pair.second->nonRtConfig;
228  }
229  if (hands)
230  {
231  hands->reinitBuffer(userConfig.hands);
232  }
233  }
234  }
236  }
237 } // namespace armarx::control::njoint_mp_controller::task_space
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController::userConfig
ConfigDict userConfig
Definition: MixedImpedanceVelocityController.h:182
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController::limb
std::map< std::string, ArmPtr > limb
Definition: MixedImpedanceVelocityController.h:179
armarx::control::njoint_mp_controller::task_space::registrationControllerNJointTSMixedImpedanceVelocityMPController
NJointControllerRegistration< NJointTSMixedImpedanceVelocityMPController > registrationControllerNJointTSMixedImpedanceVelocityMPController("NJointTSMixedImpedanceVelocityMPController")
armarx::control::common::mp::JSMPInputPtr
std::shared_ptr< JSMPInput > JSMPInputPtr
Definition: JSMP.h:47
RobotUnit.h
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController::handleRTNotSafeInNonRT
void handleRTNotSafeInNonRT()
Definition: MixedImpedanceVelocityController.cpp:260
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController::controllableNodeSets
std::map< std::string, VirtualRobot::RobotNodeSetPtr > controllableNodeSets
Definition: MixedImpedanceVelocityController.h:184
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::NJointTSMixedImpedanceVelocityMPController::additionalTask
void additionalTask() override
Definition: MixedImpedanceVelocityController.cpp:69
armarx::control::common::mp::MPPool::runMPs
void runMPs(const bool rtSafe)
Definition: MPPool.cpp:87
armarx::control::njoint_mp_controller::task_space::NJointTSMixedImpedanceVelocityMPController::getClassName
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
Definition: MixedImpedanceVelocityController.cpp:49
armarx::control::common::mp::JSMPOutputPtr
std::shared_ptr< JSMPOutput > JSMPOutputPtr
Definition: JSMP.h:48
MixedImpedanceVelocityController.h
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:528
armarx::control::common::mp::TSMPOutputPtr
std::shared_ptr< TSMPOutput > TSMPOutputPtr
Definition: TSMP.h:47
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController
Brief description of class NJointTaskspaceMixedImpedanceVelocityController.
Definition: MixedImpedanceVelocityController.h:50
armarx::control::common::mp::MPPool::mtx_mps
std::recursive_mutex mtx_mps
Definition: MPPool.h:130
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController::additionalTaskUpdateStatus
std::tuple< bool, bool > additionalTaskUpdateStatus()
Definition: MixedImpedanceVelocityController.cpp:224
armarx::control::common::dVecToMat4
Eigen::Matrix4f dVecToMat4(const mplib::core::DVec &dvec)
create Eigen:Matrix4f from 7D double vector.
Definition: utils.cpp:230
utils.h
armarx::control::njoint_mp_controller::task_space
This file is part of ArmarX.
Definition: AdmittanceController.cpp:29
armarx::control::common::MPType::hand
@ hand
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
IceUtil::Handle< class RobotUnit >
armarx::control::njoint_mp_controller::task_space::NJointTSMixedImpedanceVelocityMPController::NJointTSMixedImpedanceVelocityMPController
NJointTSMixedImpedanceVelocityMPController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
Definition: MixedImpedanceVelocityController.cpp:39
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController::hands
core::HandControlPtr hands
Definition: MixedImpedanceVelocityController.h:183
armarx::control::common::mp::MPPool
Definition: MPPool.h:47
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:129
armarx::control::njoint_controller::task_space::NJointTaskspaceMixedImpedanceVelocityController::additionalTaskSetTarget
void additionalTaskSetTarget()
Definition: MixedImpedanceVelocityController.cpp:247
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::NJointTaskspaceMixedImpedanceVelocityController::robotUnit
RobotUnitPtr robotUnit
Definition: MixedImpedanceVelocityController.h:181
armarx::control::njoint_mp_controller::task_space::NJointTSMixedImpedanceVelocityMPController::updateMPConfig
void updateMPConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition: MixedImpedanceVelocityController.cpp:55
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:136