24#include <SimoxUtility/math/compare/is_equal.h>
25#include <SimoxUtility/math/convert/mat4f_to_pos.h>
26#include <SimoxUtility/math/convert/mat4f_to_quat.h>
27#include <VirtualRobot/MathTools.h>
34 NJointControllerRegistration<KeypointMPController>
38 const NJointControllerConfigPtr& config,
41 ARMARX_INFO <<
"creating task-space admittance controller";
42 KeypointMPControllerConfigPtr cfg = KeypointMPControllerConfigPtr::dynamicCast(config);
48 kinematicChainName = cfg->nodeSetName;
50 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
54 for (
size_t i = 0; i < rns->getSize(); ++i)
56 std::string jointName = rns->getNode(i)->getName();
57 jointNames.push_back(jointName);
62 auto casted_ct = ct->
asA<ControlTarget1DoFActuatorTorque>();
64 targets.push_back(casted_ct);
66 const SensorValue1DoFActuatorTorque* torqueSensor =
67 sv->
asA<SensorValue1DoFActuatorTorque>();
68 const SensorValue1DoFActuatorVelocity* velocitySensor =
69 sv->
asA<SensorValue1DoFActuatorVelocity>();
70 const SensorValue1DoFActuatorPosition* positionSensor =
71 sv->
asA<SensorValue1DoFActuatorPosition>();
78 ARMARX_WARNING <<
"No velocity sensor available for " << jointName;
82 ARMARX_WARNING <<
"No position sensor available for " << jointName;
85 torqueSensors.push_back(torqueSensor);
86 velocitySensors.push_back(velocitySensor);
87 positionSensors.push_back(positionSensor);
91 ftsensor.initialize(rns, robotUnit, cfg->controlParamJsonFile);
96 mplib::factories::VMPFactory mpfactory;
97 mpfactory.addConfig(
"kernelSize", 100);
98 mplib::representation::VMPType vmp_type =
99 mplib::representation::VMPType::PrincipalComponent;
100 std::shared_ptr<mplib::representation::AbstractMovementPrimitive> vmp =
101 mpfactory.createMP(vmp_type);
103 std::dynamic_pointer_cast<mplib::representation::vmp::PrincipalComponentVMP>(vmp);
106 common::FTSensor::FTBufferData ftData;
107 ftData.forceBaseline.setZero();
108 ftData.torqueBaseline.setZero();
109 ftData.enableTCPGravityCompensation = cfg->enableTCPGravityCompensation;
110 ftData.tcpMass = cfg->tcpMass;
111 ftData.tcpCoMInFTSensorFrame = cfg->tcpCoMInForceSensorFrame;
112 ftSensorBuffer.reinitAllBuffers(ftData);
114 law::TaskspaceKeypointsAdmittanceController::Config configData;
115 configData.kpImpedance = cfg->kpImpedance;
116 configData.kdImpedance = cfg->kdImpedance;
117 configData.kpAdmittance = cfg->kpAdmittance;
118 configData.kdAdmittance = cfg->kdAdmittance;
119 configData.kmAdmittance = cfg->kmAdmittance;
121 configData.kpNullspaceTorque = cfg->kpNullspaceTorque;
122 configData.kdNullspaceTorque = cfg->kdNullspaceTorque;
124 configData.currentForceTorque.setZero();
125 configData.desiredTCPPose = Eigen::Matrix4f::Identity();
126 configData.desiredTCPTwist.setZero();
127 configData.desiredNullspaceJointAngles = cfg->desiredNullspaceJointAngles;
129 configData.torqueLimit = cfg->torqueLimit;
130 configData.qvelFilter = cfg->qvelFilter;
135 configData.numPoints = cfg->numKeypoints;
137 configData.keypointKp = cfg->keypointKp;
138 configData.keypointKi = cfg->keypointKi;
139 configData.keypointKd = cfg->keypointKd;
140 configData.maxControlValue = cfg->maxControlValue;
141 configData.maxDerivation = cfg->maxDerivation;
143 configData.pointCtrlMask = cfg->pointCtrlMask;
144 configData.currentKeypointPosition = cfg->initialKeypointPosition;
145 configData.filteredKeypointPosition = cfg->initialKeypointPosition;
146 configData.desiredKeypointPosition = cfg->initialKeypointPosition;
147 configData.isRigid = cfg->isRigid;
148 configData.fixedTranslation.setZero(cfg->numKeypoints * 3);
151 numPoints = cfg->numKeypoints;
152 initialStateEigen = cfg->initialKeypointPosition;
154 controller.s.filteredKeypointPosition = cfg->initialKeypointPosition;
156 controller.s.fixedTranslation.setZero(cfg->numKeypoints * 3);
157 controller.s.currentKeypointPosition = cfg->initialKeypointPosition;
162 cfg->maxControlValue,
170 for (
int i = 0; i < cfg->numKeypoints * 3; i++)
172 mplib::core::DVec state;
173 state.push_back(cfg->initialKeypointPosition[i]);
174 state.push_back(0.0);
175 rt2mp.currentState.push_back(state);
178 rt2mpBuffer.reinitAllBuffers(rt2mp);
184 return "KeypointMPController";
190 return kinematicChainName;
195 const IceUtil::Time& timeSinceLastIteration)
200 timeSinceLastIteration,
207 for (
size_t i = 0; i < (unsigned)
controller.s.numPoints * 3; i++)
209 mplib::core::DVec state;
210 state.push_back(
controller.s.currentKeypointPosition[i]);
211 state.push_back(0.0);
212 rt2mpBuffer.getWriteBuffer().currentState[i] = state;
214 rt2mpBuffer.getWriteBuffer().deltaT =
controller.s.deltaT;
215 rt2mpBuffer.commitWrite();
217 controlStatusBuffer.getWriteBuffer().currentPose =
controller.s.currentPose;
218 controlStatusBuffer.getWriteBuffer().currentTwist =
controller.s.currentTwist * 1000.0f;
219 controlStatusBuffer.getWriteBuffer().deltaT =
controller.s.deltaT;
220 controlStatusBuffer.getWriteBuffer().currentKeypointPosition =
222 controlStatusBuffer.getWriteBuffer().desiredKeypointPosition =
224 controlStatusBuffer.commitWrite();
227 if (rtFirstRun.load())
229 rtFirstRun.store(
false);
230 rtReady.store(
false);
238 ftsensor.compensateTCPGravity(ftSensorBuffer.getReadBuffer());
251 ftsensor.getFilteredForceTorque(ftSensorBuffer.getReadBuffer());
256 const auto& desiredJointTorques =
controller.run(rtReady.load());
260 for (
size_t i = 0; i < targets.size(); ++i)
262 targets.at(i)->torque = desiredJointTorques(i);
263 if (!targets.at(i)->isValid())
265 targets.at(i)->torque = 0;
271 controlStatusBuffer.getWriteBuffer().kpImpedance =
controller.s.kpImpedance;
272 controlStatusBuffer.getWriteBuffer().kdImpedance =
controller.s.kdImpedance;
273 controlStatusBuffer.getWriteBuffer().forceImpedance =
controller.s.forceImpedance;
274 controlStatusBuffer.getWriteBuffer().currentForceTorque =
277 controlStatusBuffer.getWriteBuffer().virtualPose =
controller.s.virtualPose;
278 controlStatusBuffer.getWriteBuffer().desiredTCPPose =
controller.s.desiredTCPPose;
279 controlStatusBuffer.getWriteBuffer().virtualVel =
controller.s.virtualVel;
280 controlStatusBuffer.getWriteBuffer().virtualAcc =
controller.s.virtualAcc;
281 controlStatusBuffer.getWriteBuffer().currentKeypointPosition =
283 controlStatusBuffer.getWriteBuffer().desiredKeypointPosition =
285 controlStatusBuffer.getWriteBuffer().filteredKeypointPosition =
287 controlStatusBuffer.getWriteBuffer().pointTrackingForce =
289 controlStatusBuffer.commitWrite();
296 mpEnabled.store(enableMP);
303 return mpEnabled.load();
307 KeypointMPController::runMP()
309 if (!rtReady.load() && !mpEnabled.load())
319 if (canVal > 1e-8 && mpRunning.load())
321 double phaseStop = 0;
324 canVal -= tau * deltaT * 1 / ((1 + phaseStop) * timeDuration);
325 currentState = pointVMP->calculateDesiredState(canVal, currentState);
327 Eigen::VectorXf desiredPosition;
328 desiredPosition.setZero(currentState.size());
329 for (
size_t i = 0; i < currentState.size(); i++)
331 desiredPosition[i] = currentState[i][0];
351 const std::string& name,
352 const Eigen::Matrix4f& pose)
355 vec.head<3>() = pose.block<3, 1>(0, 3);
356 vec.tail<3>() = VirtualRobot::MathTools::eigen4f2rpy(pose);
362 const std::string& name,
365 datafields[name +
"_x"] =
new Variant(vec(0));
366 datafields[name +
"_y"] =
new Variant(vec(1));
367 datafields[name +
"_z"] =
new Variant(vec(2));
368 datafields[name +
"_rx"] =
new Variant(vec(3));
369 datafields[name +
"_ry"] =
new Variant(vec(4));
370 datafields[name +
"_rz"] =
new Variant(vec(5));
375 const std::string& name,
378 for (
int i = 0; i < vec.size(); i++)
380 datafields[name +
"_" + std::to_string(i)] =
new Variant(vec(i));
390 auto values = debugRTBuffer.getUpToDateReadBuffer().desired_torques;
391 for (
auto& pair : values)
393 datafields[pair.first] =
new Variant(pair.second);
468 datafields[
"currentKeypointPosition_x"] =
469 new Variant(controlStatusBuffer.getUpToDateReadBuffer().currentKeypointPosition(0));
470 datafields[
"currentKeypointPosition_y"] =
471 new Variant(controlStatusBuffer.getUpToDateReadBuffer().currentKeypointPosition(1));
472 datafields[
"currentKeypointPosition_z"] =
473 new Variant(controlStatusBuffer.getUpToDateReadBuffer().currentKeypointPosition(2));
478 datafields[
"desiredKeypointPosition_x"] =
479 new Variant(controlStatusBuffer.getUpToDateReadBuffer().desiredKeypointPosition(0));
480 datafields[
"desiredKeypointPosition_y"] =
481 new Variant(controlStatusBuffer.getUpToDateReadBuffer().desiredKeypointPosition(1));
482 datafields[
"desiredKeypointPosition_z"] =
483 new Variant(controlStatusBuffer.getUpToDateReadBuffer().desiredKeypointPosition(2));
488 datafields[
"filteredKeypointPosition_x"] =
489 new Variant(controlStatusBuffer.getUpToDateReadBuffer().filteredKeypointPosition(0));
490 datafields[
"filteredKeypointPosition_y"] =
491 new Variant(controlStatusBuffer.getUpToDateReadBuffer().filteredKeypointPosition(1));
492 datafields[
"filteredKeypointPosition_z"] =
493 new Variant(controlStatusBuffer.getUpToDateReadBuffer().filteredKeypointPosition(2));
495 datafields[
"track_force_x"] =
496 new Variant(controlStatusBuffer.getUpToDateReadBuffer().pointTrackingForce(0));
497 datafields[
"track_force_y"] =
498 new Variant(controlStatusBuffer.getUpToDateReadBuffer().pointTrackingForce(1));
499 datafields[
"track_force_z"] =
500 new Variant(controlStatusBuffer.getUpToDateReadBuffer().pointTrackingForce(2));
501 datafields[
"track_force_rx"] =
502 new Variant(controlStatusBuffer.getUpToDateReadBuffer().pointTrackingForce(3));
503 datafields[
"track_force_ry"] =
504 new Variant(controlStatusBuffer.getUpToDateReadBuffer().pointTrackingForce(4));
505 datafields[
"track_force_rz"] =
506 new Variant(controlStatusBuffer.getUpToDateReadBuffer().pointTrackingForce(5));
508 debugObs->setDebugChannel(
"KeypointMPController", datafields);
528 const Eigen::VectorXf& value,
532 if (name ==
"kpImpedance")
537 else if (name ==
"kdImpedance")
542 else if (name ==
"kpAdmittance")
547 else if (name ==
"kdAdmittance")
552 else if (name ==
"kmAdmittance")
557 else if (name ==
"kpNullspaceTorque")
562 else if (name ==
"kdNullspaceTorque")
569 ARMARX_ERROR << name <<
" is not supported by TaskSpaceAdmittanceController";
576 const Eigen::Vector3f& torqueBaseline,
579 ftSensorBuffer.getWriteBuffer().forceBaseline = forceBaseline;
580 ftSensorBuffer.getWriteBuffer().torqueBaseline = torqueBaseline;
581 ftSensorBuffer.commitWrite();
587 ftSensorBuffer.getWriteBuffer().enableTCPGravityCompensation =
true;
588 ftSensorBuffer.getWriteBuffer().tcpMass = mass;
589 ftSensorBuffer.commitWrite();
596 ftSensorBuffer.getWriteBuffer().enableTCPGravityCompensation =
true;
597 ftSensorBuffer.getWriteBuffer().tcpCoMInFTSensorFrame = tcpCoMInFTSensorFrame;
598 ftSensorBuffer.commitWrite();
604 rtReady.store(
false);
616 pointVMP->prepareExecution(goal, initialState, 1.0);
617 mplib::representation::MPStateVec initState =
618 mplib::core::SystemState::convert2DArrayToStates<mplib::representation::MPState>(
624 Ice::Double duration,
627 timeDuration = duration;
628 pointVMP->prepareExecution(goal, initialState, 1.0);
629 mplib::representation::MPStateVec initState =
630 mplib::core::SystemState::convert2DArrayToStates<mplib::representation::MPState>(
632 mpRunning.store(
true);
638 pointVMP->prepareExecution(goal, initialState, 1.0);
639 mplib::representation::MPStateVec initState =
640 mplib::core::SystemState::convert2DArrayToStates<mplib::representation::MPState>(
652 mpRunning.store(
false);
658 mpRunning.store(
false);
664 mpRunning.store(
true);
670 if (mpRunning.load())
680 return !mpRunning.load();
686 std::vector<mplib::core::SampledTrajectory> trajs;
687 for (
auto& file : fileList)
689 mplib::core::SampledTrajectory traj;
690 traj.readFromCSVFile(file);
691 trajs.push_back(traj);
693 pointVMP->learnFromTrajectories(trajs);
696 initialState.clear();
699 for (
size_t i = 0; i < trajs[0].dim(); i++)
701 mplib::core::DVec state;
704 state.push_back(initialStateEigen[i]);
705 state.push_back(0.0);
706 initialState.push_back(state);
707 goal.push_back(trajs[0].rbegin()->getPosition(i));
718 const Ice::DoubleSeq&,
740 return "notImplemented";
754 std::vector<double> dummy;
755 dummy.push_back(0.0);
768 ftSensorBuffer.getWriteBuffer().enableTCPGravityCompensation = toggle;
769 ftSensorBuffer.commitWrite();
770 rtReady.store(
false);
776 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(kinematicChainName);
777 Eigen::Matrix4f currentPose = rns->getTCP()->getPoseInRootFrame();
778 ARMARX_IMPORTANT <<
"rt preactivate controller with target pose\n\n" << currentPose;
781 controller.s.previousTargetPose = currentPose;
786 Eigen::VectorXf fixedTranslation;
787 fixedTranslation.setZero(
controller.s.currentKeypointPosition.size());
792 for (
int i = 0; i < numPoints; i++)
794 fixedTranslation.segment(3 * i, 3) =
795 controller.s.currentKeypointPosition.segment(3 * i, 3) -
796 currentPose.block<3, 1>(0, 3);
800 controller.s.fixedTranslation = fixedTranslation;
810 runTask(
"KeypointMPController",
816 while (
getState() == eManagedIceObjectStarted)
822 c.waitForCycleDuration();
832 keypointPosition.size());
839 const float keypoint_stiffness,
841 const Eigen::VectorXf& ctrl_mask,
842 const Eigen::VectorXf& init_keypoints_position,
845 numPoints = n_points;
Brief description of class JointControlTargetBase.
This util class helps with keeping a cycle time during a control cycle.
ArmarXObjectSchedulerPtr getObjectScheduler() const
int getState() const
Retrieve current state of the ManagedIceObject.
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
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...
const law::TaskspaceKeypointsAdmittanceController::Config & rtGetControlStruct() const
MutexType controlDataMutex
std::lock_guard< std::recursive_mutex > LockGuardType
void writeControlStruct()
bool rtUpdateControlStruct()
law::TaskspaceKeypointsAdmittanceController::Config & getWriterControlStruct()
void reinitTripleBuffer(const law::TaskspaceKeypointsAdmittanceController::Config &initial)
The SensorValueBase class.
const T & getUpToDateReadBuffer() const
The Variant class is described here: Variants.
void resume(const Ice::Current &) override
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
void setGoal(const Ice::DoubleSeq &, const Ice::Current &) override
void onInitNJointController() override
Ice::Double getCanVal(const Ice::Current &) override
void stop(const Ice::Current &) override
void reconfigureController(const std::string &, const Ice::Current &) override
std::string getNames(const Ice::Current &) override
void start(const Ice::DoubleSeq &, const Ice::Current &) override
bool isFinished(const Ice::Current &) override
void learnFromCSV(const Ice::StringSeq &, const Ice::Current &) override
KeypointMPController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void reset(const Ice::Current &) override
void resetKeypoints(const int n_points, const float keypoint_stiffness, const bool is_rigid, const Eigen::VectorXf &ctrl_mask, const Eigen::VectorXf &init_keypoints_position, const Ice::Current &) override
void setKeypoints(const Eigen::VectorXf &, const Ice::Current &) override
void pause(const Ice::Current &) override
void removeAllViaPoint(const Ice::Current &) override
void startAsTraj(const Ice::Current &) override
void toggleMP(const bool enableMP, const Ice::Current &) override
void setStartAndGoal(const Ice::DoubleSeq &, const Ice::DoubleSeq &, const Ice::Current &) override
void setForceTorqueBaseline(const Eigen::Vector3f &, const Eigen::Vector3f &, const Ice::Current &) override
bool getMPEnabled(const Ice::Current &) override
Ice::DoubleSeq deserialize(const std::string &mpAsString, const Ice::Current &) override
std::string getKinematicChainName(const Ice::Current &) override
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void setTCPCoMInFTFrame(const Eigen::Vector3f &, const Ice::Current &) override
void publishPose(StringVariantBaseMap &datafields, const std::string &name, const Eigen::Matrix4f &pose)
std::string serialize(const Ice::Current &) override
void setViaPoint(Ice::Double, const Ice::DoubleSeq &, const Ice::Current &) override
void setTCPMass(Ice::Float, const Ice::Current &) override
void startAsTrajWithTime(Ice::Double, const Ice::Current &) override
void calibrateFTSensor(const Ice::Current &) override
void setTCPPose(const Eigen::Matrix4f &, const Ice::Current &) override
void startWithTime(const Ice::DoubleSeq &, Ice::Double, const Ice::Current &) override
void publishVec6f(StringVariantBaseMap &datafields, const std::string &name, const Eigen::Vector6f &vec)
void setControlParameters(const std::string &, const Eigen::VectorXf &, const Ice::Current &) override
set control parameter
std::string getClassName(const Ice::Current &) const override
void publishVecXf(StringVariantBaseMap &datafields, const std::string &name, const Eigen::Vector6f &vec)
void rtPreActivateController() override
This function is called before the controller is activated.
void toggleGravityCompensation(const bool toggle, const Ice::Current &) override
ft sensor
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#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...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Matrix< float, 6, 1 > Vector6f
std::shared_ptr< class Robot > RobotPtr
This file is part of ArmarX.
NJointControllerRegistration< KeypointMPController > registrationControllerKeypointMPController("KeypointMPController")
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceUtil::Handle< class RobotUnit > RobotUnitPtr
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl