32#include <VirtualRobot/MathTools.h>
33#include <VirtualRobot/Nodes/RobotNode.h>
34#include <VirtualRobot/RobotNodeSet.h>
35#include <VirtualRobot/math/Helpers.h>
43 const std::string& controllerName,
44 NJointCartesianNaturalPositionControllerConfigPtr config) :
45 _ik(ik), _robotUnit(robotUnit), _controllerName(controllerName), _config(config), _arm(arm)
47 _runCfg = _config->runCfg;
48 _velocityBaseSettings.basePosVel = _runCfg.maxTcpPosVel;
49 _velocityBaseSettings.baseOriVel = _runCfg.maxTcpOriVel;
50 _velocityBaseSettings.baseJointVelocity =
52 _userNullspaceTargets = std::vector<float>(arm.
rns->getSize(), std::nanf(
""));
53 _naturalNullspaceTargets = std::vector<float>(arm.
rns->getSize(), std::nanf(
""));
55 VirtualRobot::RobotNodeSetPtr rns = arm.
rns;
56 for (
size_t i = 0; i < rns->getSize(); i++)
58 VirtualRobot::RobotNodePtr rn = rns->getNode(i);
63 _rnsToElb.emplace_back(rn);
70 _defaultWaypointConfigs[
"default"] = wpc;
72 _ftOffset.force = Eigen::Vector3f::Zero();
73 _ftOffset.torque = Eigen::Vector3f::Zero();
76NJointCartesianNaturalPositionControllerConfigPtr
78 const std::string& elbowNode)
80 NJointCartesianNaturalPositionControllerConfigPtr cfg =
81 new NJointCartesianNaturalPositionControllerConfig();
83 cfg->elbowNode = elbowNode;
90 NJointControllerInterfacePrx ctrl = _robotUnit->getNJointController(_controllerName);
93 _controllerCreated =
false;
94 _controller = NJointCartesianNaturalPositionControllerInterfacePrx::checkedCast(ctrl);
95 _controller->setConfig(_runCfg);
99 ctrl = _robotUnit->createNJointController(
100 "NJointCartesianNaturalPositionController", _controllerName, _config);
101 _controller = NJointCartesianNaturalPositionControllerInterfacePrx::checkedCast(ctrl);
102 _controllerCreated =
true;
104 if (_activateControllerOnInit)
106 _controller->activateController();
113 std::optional<float> minElbowHeight)
116 _tcpTarget = tcpTarget;
118 _fwd = _ik.solveSoechtingIK(math::Helpers::Position(tcpTarget), minElbowHeight);
121 tcpTarget, _fwd.elbow, _arm.rns, _arm.tcp, _arm.elbow, setOri, _natikParams.diffIKparams);
124 ARMARX_ERROR <<
"could not solve natural IK for target: " << tcpTarget;
127 _elbTarget = _arm.elbow->getPoseInRootFrame();
128 _controller->setTarget(
130 if (_setJointNullspaceFromNaturalIK)
132 for (
size_t i = 0; i < _rnsToElb.size(); i++)
134 _naturalNullspaceTargets.at(i) = ikResult.
jointValues(i);
137 updateNullspaceTargets();
144 const std::vector<float>& nullspaceTargets)
146 ARMARX_CHECK(_arm.rns->getSize() == nullspaceTargets.size());
147 _userNullspaceTargets = nullspaceTargets;
148 updateNullspaceTargets();
154 return math::Helpers::Position(_tcpTarget);
160 return math::Helpers::Position(_elbTarget);
194 _ftOffset = _controller->getAverageFTValue();
195 _controller->setFTOffset(_ftOffset);
207 _controller->setFTLimit(force, torque);
213 _controller->clearFTLimit();
220 FTSensorValue ft = _controller->getCurrentFTValue();
223 ft.force = ft.force - _ftOffset.force;
224 ft.torque = ft.torque - _ftOffset.torque;
232 FTSensorValue ft = _controller->getAverageFTValue();
235 ft.force = ft.force - _ftOffset.force;
236 ft.torque = ft.torque - _ftOffset.torque;
244 _controller->stopMovement();
245 _controller->clearFTLimit();
246 _controller->setNullspaceControlEnabled(
true);
251CartesianNaturalPositionControllerProxy::updateDynamicKp()
255 float error = (math::Helpers::Position(_tcpTarget) - _fwd.
wrist).
norm();
258 _dynamicKp.
calculate(error, KpElb, KpJla);
260 _runCfg.elbowKp = KpElb;
261 _runCfg.jointLimitAvoidanceKp = KpJla;
262 _controller->setConfig(_runCfg);
268CartesianNaturalPositionControllerProxy::updateNullspaceTargets()
270 std::vector<float> nsTargets = _userNullspaceTargets;
271 for (
size_t i = 0; i < _naturalNullspaceTargets.size(); i++)
273 if (std::isnan(nsTargets.at(i)))
275 nsTargets.at(i) = _naturalNullspaceTargets.at(i);
278 _controller->setNullspaceTarget(nsTargets);
286 float f = std::exp(-0.5f * (error * error) / (
sigmaMM *
sigmaMM));
288 KpJla = (1 - f) *
maxKp;
293 CartesianNaturalPositionControllerConfig runCfg)
295 _controller->setConfig(runCfg);
296 this->_runCfg = runCfg;
299CartesianNaturalPositionControllerConfig
309 if (_waypoints.size() == 0)
311 _waypointChanged =
true;
313 _waypoints.emplace_back(waypoint);
318 const Eigen::Vector3f& tcpTarget,
319 const std::vector<float>& userNullspaceTargets,
320 std::optional<float> minElbowHeight)
327 std::optional<float> minElbowHeight)
330 w.
config = _defaultWaypointConfigs[
"default"];
331 w.
targets.
tcpTarget = math::Helpers::CreatePose(tcpTarget, Eigen::Matrix3f::Identity());
340 std::optional<float> minElbowHeight)
343 w.
config = _defaultWaypointConfigs[
"default"];
355 _currentWaypointIndex = 0;
362 _defaultWaypointConfigs[
"default"] = config;
368 std::stringstream ss;
370 ss << std::fixed <<
"Waypoint: " << (_currentWaypointIndex + 1) <<
"/" << _waypoints.size()
378 const VirtualRobot::RobotNodeSetPtr& rns,
381 size_t len = rns->getSize();
382 std::vector<Eigen::Vector3f> positions;
383 for (
size_t i = 0; i < len; i++)
385 positions.push_back(rns->getNode(i)->getPositionInRootFrame());
387 positions.push_back(rns->getTCP()->getPositionInRootFrame());
389 std::vector<float> dists;
390 for (
size_t i = 0; i < len; i++)
392 dists.push_back((positions.at(i) - positions.at(i + 1)).norm());
395 std::vector<float> result(len, 0);
397 for (
int i = len - 1; i >= 0; i--)
400 result.at(i) = maxPosVel / dist;
408 std::vector<float> result(vec.size(), 0);
409 for (
size_t i = 0; i < vec.size(); i++)
411 result.at(i) = vec.at(i) * scale;
419 _activateControllerOnInit = value;
427 float scale = referencePosVel / v.basePosVel;
428 _runCfg.maxTcpPosVel = v.basePosVel * v.scaleTcpPosVel * scale;
429 _runCfg.maxTcpOriVel = v.baseOriVel * v.scaleTcpOriVel * scale;
430 _runCfg.maxElbPosVel = v.basePosVel * v.scaleElbPosVel * scale;
431 _runCfg.maxJointVelocity =
ScaleVec(v.baseJointVelocity, v.scaleJointVelocities * scale);
432 _runCfg.maxNullspaceVelocity =
433 ScaleVec(v.baseJointVelocity, v.scaleNullspaceVelocities * scale);
437 _runCfg.jointLimitAvoidanceKp = k.
baseKpJla;
438 _runCfg.nullspaceTargetKp = k.
baseKpNs;
443 _controller->setConfig(_runCfg);
448 const CartesianNaturalPositionControllerConfig& runCfg)
450 _kpBaseSettings.baseKpTcpPos = _runCfg.KpPos;
451 _kpBaseSettings.baseKpTcpOri = _runCfg.KpOri;
452 _kpBaseSettings.baseKpElbPos = _runCfg.elbowKp;
453 _kpBaseSettings.baseKpJla = _runCfg.jointLimitAvoidanceKp;
454 _kpBaseSettings.baseKpNs = _runCfg.nullspaceTargetKp;
455 _kpBaseSettings.maxNullspaceAcceleration = _runCfg.maxNullspaceAcceleration;
456 _kpBaseSettings.maxPositionAcceleration = _runCfg.maxPositionAcceleration;
457 _kpBaseSettings.maxOrientationAcceleration = _runCfg.maxOrientationAcceleration;
463 if (_controllerCreated)
466 _controller->deactivateAndDeleteController();
471 _controller->deactivateController();
473 _controllerCreated =
false;
479 if (_waypoints.size() == 0)
487 _currentWaypointIndex++;
488 _waypointChanged =
true;
490 if (_waypointChanged)
492 _waypointChanged =
false;
494 return onWaypointChanged();
500CartesianNaturalPositionControllerProxy::onWaypointChanged()
504 _userNullspaceTargets = w.targets.userNullspaceTargets;
506 << math::Helpers::GetPosition(w.targets.tcpTarget).transpose();
507 return setTarget(w.targets.tcpTarget, w.targets.setOri, w.targets.minElbowHeight);
514 return _waypoints.at(_currentWaypointIndex);
520 return _waypoints.size() == 0 || _currentWaypointIndex == _waypoints.size() - 1;
523NJointCartesianNaturalPositionControllerInterfacePrx
532 _dynamicKp = dynamicKp;
548 config.thresholdTcpPosReached,
549 config.thresholdTcpPosReached /
563 const std::vector<float>& userNullspaceTargets)
566 this->
targets.userNullspaceTargets = userNullspaceTargets;
607 const VirtualRobot::RobotNodeSetPtr& rns) :
608 jointValues(rns->getJointValues()), rns(rns)
615 rns->setJointValues(jointValues);
~ScopedJointValueRestore()
ScopedJointValueRestore(const VirtualRobot::RobotNodeSetPtr &rns)
Waypoint & setNullspaceTargets(const std::vector< float > &userNullspaceTargets)
bool reached(const VirtualRobot::RobotNodePtr &tcp)
Waypoint & setConfig(const WaypointConfig &config)
void setDefaultWaypointConfig(const WaypointConfig &config)
void addWaypoint(const Waypoint &waypoint)
static NJointCartesianNaturalPositionControllerConfigPtr MakeConfig(const std::string &rns, const std::string &elbowNode)
void setRuntimeConfig(CartesianNaturalPositionControllerConfig runCfg)
static std::vector< float > CalculateMaxJointVelocity(const VirtualRobot::RobotNodeSetPtr &rns, float maxPosVel)
FTSensorValue getCurrentFTValue(bool substactOffset)
Eigen::Vector3f getCurrentTargetPosition()
Waypoint & currentWaypoint()
void useCurrentFTasOffset()
float getTcpOrientationError()
void setDynamicKp(DynamicKp dynamicKp)
void updateBaseKpValues(const CartesianNaturalPositionControllerConfig &runCfg)
void setMaxVelocities(float referencePosVel)
void enableFTLimit(float force, float torque, bool useCurrentFTasOffset)
FTSensorValue getAverageFTValue(bool substactOffset)
bool isFinalWaypointReached()
static std::vector< float > ScaleVec(const std::vector< float > &vec, float scale)
bool setTarget(const Eigen::Matrix4f &tcpTarget, NaturalDiffIK::Mode setOri, std::optional< float > minElbowHeight=std::nullopt)
void setNullspaceTarget(const std::vector< float > &nullspaceTargets)
CartesianNaturalPositionControllerProxy(const NaturalIK &_ik, const NaturalIK::ArmJoints &arm, const RobotUnitInterfacePrx &_robotUnit, const std::string &_controllerName, NJointCartesianNaturalPositionControllerConfigPtr _config)
float getTcpPositionError()
void setActivateControllerOnInit(bool value)
Eigen::Vector3f getCurrentElbowTargetPosition()
std::string getStatusText()
CartesianNaturalPositionControllerConfig getRuntimeConfig()
NJointCartesianNaturalPositionControllerInterfacePrx getInternalController()
Waypoint createWaypoint(const Eigen::Vector3f &tcpTarget, const std::vector< float > &userNullspaceTargets, std::optional< float > minElbowHeight=std::nullopt)
float getElbPositionError()
static float GetOrientationError(const Eigen::Matrix4f &targetPose, const VirtualRobot::RobotNodePtr &tcp, const VirtualRobot::RobotNodePtr &referenceFrame=nullptr)
static bool Reached(const Eigen::Matrix4f &targetPose, const VirtualRobot::RobotNodePtr &tcp, bool checkOri, float thresholdPosReached, float thresholdOriReached, const VirtualRobot::RobotNodePtr &referenceFrame=nullptr)
static float GetPositionError(const Eigen::Matrix4f &targetPose, const VirtualRobot::RobotNodePtr &tcp, const VirtualRobot::RobotNodePtr &referenceFrame=nullptr)
static Result CalculateDiffIK(const Eigen::Matrix4f &targetPose, const Eigen::Vector3f &elbowTarget, VirtualRobot::RobotNodeSetPtr rns, VirtualRobot::RobotNodePtr tcp, VirtualRobot::RobotNodePtr elbow, Mode setOri, Parameters params=Parameters())
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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.
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface > RobotUnitInterfacePrx
double norm(const Point &a)
void calculate(float error, float &KpElb, float &KpJla)
float maxPositionAcceleration
float maxNullspaceAcceleration
float maxOrientationAcceleration
float thresholdTcpPosReached
NaturalDiffIK::Mode setOri
std::optional< float > minElbowHeight
Eigen::Matrix4f tcpTarget
std::vector< float > userNullspaceTargets
Eigen::VectorXf jointValues
VirtualRobot::RobotNodePtr elbow
VirtualRobot::RobotNodeSetPtr rns