BimanualImpedanceController.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  * @package ...
17  * @author Jianfeng Gao ( jianfeng dot gao at kit dot edu )
18  * @date 2023
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "ImpedanceController.h"
24 
25 #include <VirtualRobot/MathTools.h>
26 
29 
31 #include <armarx/control/common/control_law/aron/TaskspaceImpedanceControllerConfig.aron.generated.h>
33 
34 
36 {
37  NJointControllerRegistration<NJointTaskspaceBimanualImpedanceController>
39  "NJointTaskspaceBimanualImpedanceController");
40 
41  NJointTaskspaceBimanualImpedanceController::NJointTaskspaceBimanualImpedanceController(
42  const RobotUnitPtr& robotUnit,
43  const NJointControllerConfigPtr& config,
44  const VirtualRobot::RobotPtr&) :
45  robotUnit(robotUnit)
46  {
47  ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
48 
51  ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
53  kinematicChainName = cfg->nodeSetName;
54  VirtualRobot::RobotNodeSetPtr rtRns = rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
55 
56  nonRtRobot = robotUnit->cloneRobot();
57  VirtualRobot::RobotNodeSetPtr nonRtRns = nonRtRobot->getRobotNodeSet(cfg->nodeSetName);
58  robotUnit->updateVirtualRobot(nonRtRobot);
59 
60  ARMARX_CHECK_EXPRESSION(rtRns) << cfg->nodeSetName;
61  ARMARX_CHECK_EXPRESSION(nonRtRns) << cfg->nodeSetName;
62 
63  controller.initialize(nonRtRns);
64 
65  jointNames.clear();
66  for (size_t i = 0; i < rtRns->getSize(); ++i)
67  {
68  std::string jointName = rtRns->getNode(i)->getName();
69  jointNames.push_back(jointName);
70  ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Torque1DoF);
72  const SensorValueBase* sv = useSensorValue(jointName);
74  auto* casted_ct = ct->asA<ControlTarget1DoFActuatorTorque>();
75  ARMARX_CHECK_EXPRESSION(casted_ct);
76  targets.push_back(casted_ct);
77 
78  const auto* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>();
79  const auto* velocitySensor = sv->asA<SensorValue1DoFActuatorVelocity>();
80  const auto* positionSensor = sv->asA<SensorValue1DoFActuatorPosition>();
81 
82  if (torqueSensor == nullptr)
83  {
84  ARMARX_WARNING << "No Torque sensor available for " << jointName;
85  }
86  if (velocitySensor == nullptr)
87  {
88  ARMARX_WARNING << "No velocity sensor available for " << jointName;
89  }
90  if (positionSensor == nullptr)
91  {
92  ARMARX_WARNING << "No position sensor available for " << jointName;
93  }
94 
95  sensorDevices.torqueSensors.push_back(torqueSensor);
96  sensorDevices.velocitySensors.push_back(velocitySensor);
97  sensorDevices.positionSensors.push_back(positionSensor);
98  };
99 
100  {
101  auto configData = ::armarx::fromAron<AronDTO, BO>(cfg->config);
102 
103  validateConfigData(configData);
104 
105  ARMARX_INFO << VAROUT(configData.kpImpedance);
106  ARMARX_INFO << VAROUT(configData.kdImpedance);
107  ARMARX_INFO << VAROUT(configData.kpNullspace);
108  ARMARX_INFO << VAROUT(configData.kdNullspace);
109  ARMARX_INFO << VAROUT(configData.desiredPose);
110  ARMARX_INFO << VAROUT(configData.desiredTwist);
111  if (configData.desiredNullspaceJointAngles.has_value())
112  ARMARX_INFO << VAROUT(configData.desiredNullspaceJointAngles.value());
113  ARMARX_INFO << VAROUT(configData.torqueLimit);
114  ARMARX_INFO << VAROUT(configData.qvelFilter);
115 
117  bufferUserToRt.reinitAllBuffers(configData);
118  }
119 
120  controlTargets.targets.resize(rtRns->getSize(), 0.);
121  }
122 
123  std::string
125  {
126  return "NJointTaskspaceBimanualImpedanceController";
127  }
128 
129  // std::string NJointTaskspaceBimanualImpedanceController::getKinematicChainName(const Ice::Current&)
130  // {
131  // return kinematicChainName;
132  // }
133 
134  void
136  {
137  runTask("NJointTaskspaceAdmittanceAdditionalTask",
138  [&]
139  {
140  CycleUtil c(1);
141  getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
143  << "Create a new thread alone NJointTaskspaceAdmittanceController";
144  while (getState() == eManagedIceObjectStarted)
145  {
146  if (isControllerActive())
147  {
148  additionalTask();
149  }
150  c.waitForCycleDuration();
151  }
152  });
153  }
154 
155  void
157  {
158  robotUnit->updateVirtualRobot(nonRtRobot);
159 
160  controller.updateControlStatus(
162  bufferRtToAdditionalTask.getUpToDateReadBuffer());
163  }
164 
165  void
167  const IceUtil::Time& /*sensorValuesTimestamp*/,
168  const IceUtil::Time& timeSinceLastIteration)
169  {
170  double deltaT = timeSinceLastIteration.toSecondsDouble();
171  auto& userConfig = bufferUserToRt.getUpToDateReadBuffer();
172 
173  if (rtFirstRun.load())
174  {
175  rtFirstRun.store(false);
176  rtReady.store(true);
177  }
178 
179  auto& s = bufferRtToAdditionalTask.getWriteBuffer();
180  size_t nDoF = sensorDevices.positionSensors.size();
181  for (size_t i = 0; i < nDoF; ++i)
182  {
183  s.jointPosition[i] = sensorDevices.positionSensors[i]->position;
184  s.jointVelocity[i] = sensorDevices.velocitySensors[i]->velocity;
185  s.jointTorque[i] = sensorDevices.torqueSensors[i]->torque;
186  }
187  s.deltaT = deltaT;
188  bufferRtToAdditionalTask.commitWrite();
189 
190  controller.run(userConfig, controlTargets);
191 
192  for (unsigned int i = 0; i < controlTargets.targets.size(); i++)
193  {
194  targets.at(i)->torque = controlTargets.targets.at(i);
195  if (!targets.at(i)->isValid())
196  {
197  targets.at(i)->torque = 0;
198  }
199  }
200  }
201 
202  void
204  const Ice::Current& iceCurrent)
205  {
206  auto configData = ::armarx::fromAron<AronDTO, BO>(dto);
207 
208  validateConfigData(configData);
209 
212 
213  bufferUserToRt.getWriteBuffer() = configData;
215  }
216 
217  void
219  {
220  const auto nDoF = jointNames.size();
221 
222  const auto checkSize = [nDoF](const auto& v) { ARMARX_CHECK_EQUAL((unsigned)v.rows(), nDoF); };
223  const auto checkNonNegative = [](const auto& v) { ARMARX_CHECK((v.array() >= 0).all()); };
224 
225  if (!configData.desiredNullspaceJointAngles.has_value() and !isControllerActive())
226  {
227  ARMARX_INFO << "No user defined nullspace target, reset to zero with " << VAROUT(nDoF);
228  configData.desiredNullspaceJointAngles = Eigen::VectorXf::Zero(nDoF);
229  reInitPreActivate.store(true);
230  }
231  checkSize(configData.desiredNullspaceJointAngles.value());
232  checkSize(configData.kdNullspace);
233  checkSize(configData.kpNullspace);
234 
235  checkNonNegative(configData.kdNullspace);
236  checkNonNegative(configData.kpNullspace);
237  checkNonNegative(configData.kdImpedance);
238  checkNonNegative(configData.kpImpedance);
239  }
240 
241  void
244  const DebugObserverInterfacePrx& debugObs)
245  {
246  StringVariantBaseMap datafields;
247 
248  auto nonRtData = controller.bufferNonRtToOnPublish.getUpToDateReadBuffer();
249  auto rtData = controller.bufferRtToOnPublish.getUpToDateReadBuffer();
251 
252 
253  common::debugEigenPose(datafields, "current_pose", nonRtData.currentPose);
254  common::debugEigenPose(datafields, "desired_pose", configData.desiredPose);
255  common::debugEigenVec(datafields, "kpImpedance", configData.kpImpedance);
256  common::debugEigenVec(datafields, "kdImpedance", configData.kdImpedance);
257  common::debugEigenVec(datafields, "forceImpedance", rtData.forceImpedance);
258  common::debugEigenVec(datafields, "desiredJointTorques", rtData.desiredJointTorques);
259 
260  debugObs->setDebugChannel("NJointTaskspaceBimanualImpedanceController", datafields);
261  }
262 
263 
264  void
266  {
267  VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(kinematicChainName);
268  Eigen::Matrix4f currentPose = rns->getTCP()->getPoseInRootFrame();
269  ARMARX_IMPORTANT << "rt preactivate controller with target pose\n\n" << currentPose;
270  controller.preactivateInit(rns);
271  if (reInitPreActivate.load())
272  {
274  c.desiredNullspaceJointAngles.value() = rns->getJointValuesEigen();
275  c.desiredPose = currentPose;
276 
279 
280  reInitPreActivate.store(false);
281  }
282 
283  const auto nDoF = rns->getSize();
284 
285  {
286  law::RobotStatus rtToNonRtStatus;
287  rtToNonRtStatus.jointPosition.resize(nDoF, 0.);
288  rtToNonRtStatus.jointVelocity.resize(nDoF, 0.);
289  rtToNonRtStatus.jointTorque.resize(nDoF, 0.);
290  for (size_t i = 0; i < nDoF; ++i)
291  {
292  rtToNonRtStatus.jointPosition[i] = sensorDevices.positionSensors[i]->position;
293  rtToNonRtStatus.jointVelocity[i] = sensorDevices.velocitySensors[i]->velocity;
294  rtToNonRtStatus.jointTorque[i] = sensorDevices.torqueSensors[i]->torque;
295  }
296  bufferRtToAdditionalTask.reinitAllBuffers(rtToNonRtStatus);
297  }
298  }
299 
300  void
302  {
303  controller.isInitialized.store(false);
304  }
305 } /// namespace armarx::control::njoint_controller::task_space
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::controlTargets
common::control_law::ControlTarget controlTargets
Definition: AdmittanceController.h:117
armarx::control::njoint_mp_controller::task_space::NJointTSAdmittanceMPController::bufferUserToAdditionalTask
TripleBuffer< BO > bufferUserToAdditionalTask
Definition: AdmittanceController.h:72
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::rtPreActivateController
void rtPreActivateController() override
This function is called before the controller is activated.
Definition: BimanualImpedanceController.cpp:265
armarx::control::common::debugEigenPose
void debugEigenPose(StringVariantBaseMap &datafields, const std::string &name, Eigen::Matrix4f pose)
Definition: utils.cpp:84
armarx::control::common::control_law::ControlTarget::targets
std::vector< float > targets
Definition: common.h:46
armarx::TripleBuffer::getWriteBuffer
T & getWriteBuffer()
Definition: TripleBuffer.h:90
armarx::NJointControllerBase::useSynchronizedRtRobot
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
Definition: NJointController.cpp:293
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:111
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::updateConfig
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface.
Definition: BimanualImpedanceController.cpp:203
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::robotUnit
RobotUnitPtr robotUnit
Definition: AdmittanceController.h:119
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::SensorDevices::velocitySensors
std::vector< const SensorValue1DoFActuatorVelocity * > velocitySensors
Definition: AdmittanceController.h:93
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::SensorDevices::torqueSensors
std::vector< const SensorValue1DoFActuatorTorque * > torqueSensors
Definition: AdmittanceController.h:92
armarx::TripleBuffer::commitWrite
void commitWrite()
Definition: TripleBuffer.h:146
armarx::control::common::control_law::RobotStatus::jointTorque
std::vector< float > jointTorque
Definition: common.h:34
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::rtFirstRun
std::atomic_bool rtFirstRun
Definition: BimanualImpedanceController.h:120
armarx::NJointControllerBase::useControlTarget
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
Definition: NJointController.cpp:410
armarx::control::njoint_controller::task_space
Definition: AdmittanceController.cpp:35
armarx::control::njoint_mp_controller::task_space::NJointTSAdmittanceMPController::bufferUserToRt
TripleBuffer< BO > bufferUserToRt
Definition: AdmittanceController.h:73
armarx::CycleUtil
This util class helps with keeping a cycle time during a control cycle.
Definition: CycleUtil.h:40
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:725
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::BO
law::TaskspaceImpedanceController::Config BO
Definition: BimanualImpedanceController.h:67
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::nonRtRobot
VirtualRobot::RobotPtr nonRtRobot
Definition: AdmittanceController.h:115
armarx::control::common::control_law::RobotStatus::jointVelocity
std::vector< float > jointVelocity
Definition: common.h:33
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::onInitNJointController
void onInitNJointController() override
NJointControllerBase interface.
Definition: BimanualImpedanceController.cpp:135
aron_conversions.h
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::targets
std::vector< ControlTarget1DoFActuatorTorque * > targets
Definition: AdmittanceController.h:98
armarx::NJointControllerBase::rtGetRobot
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
Definition: NJointControllerBase.h:845
armarx::control::njoint_controller::task_space::registrationControllerNJointTaskspaceBimanualImpedanceController
NJointControllerRegistration< NJointTaskspaceBimanualImpedanceController > registrationControllerNJointTaskspaceBimanualImpedanceController("NJointTaskspaceBimanualImpedanceController")
armarx::detail::ControlThreadOutputBufferEntry
Definition: ControlThreadOutputBuffer.h:177
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::bufferRtToAdditionalTask
TripleBuffer< law::RobotStatus > bufferRtToAdditionalTask
Definition: BimanualImpedanceController.h:118
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::nonRtRobot
VirtualRobot::RobotPtr nonRtRobot
Definition: BimanualImpedanceController.h:125
controller
Definition: AddOperation.h:39
armarx::NJointControllerBase::isControllerActive
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
Definition: NJointControllerBase.h:777
armarx::control::common::control_law::RobotStatus
Definition: common.h:30
armarx::NJointControllerBase::runTask
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
Definition: NJointControllerBase.h:753
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::ConfigPtrT
ConfigurableNJointControllerConfigPtr ConfigPtrT
Definition: AdmittanceController.h:57
ArmarXObjectScheduler.h
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::control::common::control_law::RobotStatus::jointPosition
std::vector< float > jointPosition
Definition: common.h:32
armarx::control::common::debugEigenVec
void debugEigenVec(StringVariantBaseMap &datafields, const std::string &name, Eigen::VectorXf vec)
Definition: utils.cpp:95
utils.h
CycleUtil.h
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::onPublish
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
Definition: BimanualImpedanceController.cpp:242
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:601
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::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::validateConfigData
void validateConfigData(BO &config)
Definition: BimanualImpedanceController.cpp:218
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::rtReady
std::atomic_bool rtReady
Definition: BimanualImpedanceController.h:121
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::validateConfigData
void validateConfigData(BO &config)
Definition: AdmittanceController.cpp:211
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::bufferUserToAdditionalTask
TripleBuffer< BO > bufferUserToAdditionalTask
set buffers
Definition: BimanualImpedanceController.h:116
IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface >
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::sensorDevices
SensorDevices sensorDevices
Definition: AdmittanceController.h:96
ImpedanceController.h
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::rtPostDeactivateController
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
Definition: BimanualImpedanceController.cpp:301
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::robotUnit
RobotUnitPtr robotUnit
Definition: BimanualImpedanceController.h:130
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::additionalTask
virtual void additionalTask()
Definition: BimanualImpedanceController.cpp:156
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::kinematicChainName
std::string kinematicChainName
variables
Definition: AdmittanceController.h:102
armarx::TripleBuffer::getUpToDateReadBuffer
const T & getUpToDateReadBuffer() const
Definition: TripleBuffer.h:108
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_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::SensorDevices::positionSensors
std::vector< const SensorValue1DoFActuatorPosition * > positionSensors
Definition: AdmittanceController.h:94
armarx::control::njoint_controller::task_space::NJointTaskspaceAdmittanceController::jointNames
std::vector< std::string > jointNames
Definition: AdmittanceController.h:103
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::bufferUserToRt
TripleBuffer< BO > bufferUserToRt
Definition: BimanualImpedanceController.h:117
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::getClassName
std::string getClassName(const Ice::Current &) const override
Definition: BimanualImpedanceController.cpp:124
armarx::TripleBuffer::reinitAllBuffers
std::enable_if< std::is_copy_constructible< U >::value >::type reinitAllBuffers(const T &init)
Definition: TripleBuffer.h:153
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::control::njoint_controller::task_space::NJointTaskspaceBimanualImpedanceController::rtRun
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
Definition: BimanualImpedanceController.cpp:166
armarx::ManagedIceObject::getObjectScheduler
ArmarXObjectSchedulerPtr getObjectScheduler() const
Definition: ManagedIceObject.cpp:731
armarx::NJointControllerBase::useSensorValue
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
Definition: NJointController.cpp:383
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:18