From ece7c9fcb9e25e6f6eb7c8b003ed10aa2ef8c933 Mon Sep 17 00:00:00 2001 From: Armar6 <armar6@h2t.com> Date: Sun, 3 Mar 2019 13:17:35 +0100 Subject: [PATCH] added adaptive position control --- .../NJointTaskSpaceDMPController.ice | 3 + .../DMPController/TaskSpaceDMPController.cpp | 2 +- ...NJointPeriodicTSDMPCompliantController.cpp | 119 ++++++++++++------ .../NJointPeriodicTSDMPCompliantController.h | 6 + 4 files changed, 93 insertions(+), 37 deletions(-) diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice index 3c303ee6d..d2ba295d3 100644 --- a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice +++ b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice @@ -361,6 +361,9 @@ module armarx Ice::FloatSeq ws_y; Ice::FloatSeq ws_z; + float adaptCoeff; + float reactThreshold; + }; diff --git a/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp b/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp index e221ee7d4..ed5f720b5 100644 --- a/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp +++ b/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp @@ -81,7 +81,7 @@ double TaskSpaceDMPController::flow(double canVal, double deltaT, const Eigen::M } double timeDuration = config.motionTimeDuration; - canVal -= tau * deltaT * 1 / (1 + phaseStop) ; + canVal -= tau * deltaT * 1;// / (1 + phaseStop) ; DMP::Vec<DMP::DMPState > temporalState = dmpPtr->calculateDirectlyVelocity(currentState, canVal / timeDuration, deltaT / timeDuration, targetPoseVec); diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.cpp index d4ad2769f..3be08e9d7 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.cpp +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.cpp @@ -91,6 +91,9 @@ namespace armarx forceOffset.setZero(); filteredForce.setZero(); + reactForce.setZero(); + filteredForceInRoot.setZero(); + UserToRTData initUserData; initUserData.targetForce = 0; @@ -175,13 +178,13 @@ namespace armarx return; } - if (!rt2CtrlData.updateReadBuffer() || !dmpCtrl) + if (!dmpCtrl) { return; } Eigen::VectorXf targetVels(6); - bool isPhaseStop = rt2CtrlData.getReadBuffer().isPhaseStop; + bool isPhaseStop = rt2CtrlData.getUpToDateReadBuffer().isPhaseStop; if (isPhaseStop) { targetVels.setZero(); @@ -189,9 +192,9 @@ namespace armarx else { - double deltaT = rt2CtrlData.getReadBuffer().deltaT; - Eigen::Matrix4f currentPose = rt2CtrlData.getReadBuffer().currentPose; - Eigen::VectorXf currentTwist = rt2CtrlData.getReadBuffer().currentTwist; + double deltaT = rt2CtrlData.getUpToDateReadBuffer().deltaT; + Eigen::Matrix4f currentPose = rt2CtrlData.getUpToDateReadBuffer().currentPose; + Eigen::VectorXf currentTwist = rt2CtrlData.getUpToDateReadBuffer().currentTwist; LockGuardType guard {controllerMutex}; dmpCtrl->flow(deltaT, currentPose, currentTwist); @@ -291,12 +294,12 @@ namespace armarx } } Eigen::Matrix4f forceFrameInRoot = rtGetRobot()->getRobotNode(cfg->forceFrameName)->getPoseInRootFrame(); - Eigen::Vector3f filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) * filteredForce; + filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) * filteredForce; float targetForce = user2rtData.getUpToDateReadBuffer().targetForce; Eigen::Matrix3f currentHandOri = currentPose.block<3, 3>(0, 0); Eigen::Matrix3f currentToolOri = toolTransform * currentHandOri; - float desiredZVel = kpf * (targetForce - filteredForceInRoot.norm()); + float desiredZVel = kpf * (targetForce - filteredForceInRoot(2)); targetVel(2) -= desiredZVel; // targetVel.block<3, 1>(0, 0) = currentToolOri * targetVel.block<3, 1>(0, 0); @@ -347,23 +350,21 @@ namespace armarx } bool isPhaseStop = false; - - + Eigen::Vector3f adaptK = kpos; float diff = (targetPose.block<3, 1>(0, 3) - currentPose.block<3, 1>(0, 3)).norm(); if (diff > cfg->phaseDist0) { isPhaseStop = true; + adaptK = ((float)exp(-fabs(diff - cfg->phaseDist0) * cfg->adaptCoeff)) * adaptK; + adaptK(2) = kpos(2); } - rt2CtrlData.getWriteBuffer().currentPose = currentPose; - rt2CtrlData.getWriteBuffer().currentTwist = currentTwist; - rt2CtrlData.getWriteBuffer().deltaT = deltaT; - rt2CtrlData.getWriteBuffer().currentTime += deltaT; - rt2CtrlData.getWriteBuffer().isPhaseStop = isPhaseStop; - rt2CtrlData.commitWrite(); + // adaptive control with distance + + float dTf = (float)deltaT; @@ -378,14 +379,46 @@ namespace armarx targetPose(2, 3) = targetPose(2, 3) < cfg->ws_z[1] ? targetPose(2, 3) : cfg->ws_z[1]; debugRT.getWriteBuffer().targetPose = targetPose; + debugRT.getWriteBuffer().filteredForce = filteredForceInRoot; + debugRT.getWriteBuffer().reactForce = reactForce; + debugRT.getWriteBuffer().targetVel = targetVel; + debugRT.getWriteBuffer().adaptK = adaptK; + debugRT.commitWrite(); + if (isPhaseStop) + { + reactForce += filteredForceInRoot * dTf; + float xyforce = reactForce.block<2, 1>(0, 0).norm(); + if (xyforce > cfg->reactThreshold) + { + targetPose(0, 3) = currentPose(0, 3); + targetPose(1, 3) = currentPose(1, 3); + isPhaseStop = false; + reactForce << 0, 0, 0; + } + } + else + { + reactForce << 0, 0, 0; + } + + rt2CtrlData.getWriteBuffer().currentPose = currentPose; + rt2CtrlData.getWriteBuffer().currentTwist = currentTwist; + rt2CtrlData.getWriteBuffer().deltaT = deltaT; + rt2CtrlData.getWriteBuffer().currentTime += deltaT; + rt2CtrlData.getWriteBuffer().isPhaseStop = isPhaseStop; + rt2CtrlData.commitWrite(); + // Eigen::Matrix3f rotVel = VirtualRobot::MathTools::rpy2eigen3f(targetVel(3) * dTf, targetVel(4) * dTf, targetVel(5) * dTf); // targetPose.block<3, 3>(0, 0) = rotVel * targetPose.block<3, 3>(0, 0); // inverse dynamic controller jacobi.block<3, 8>(0, 0) = 0.001 * jacobi.block<3, 8>(0, 0); // convert mm to m + + + Eigen::Vector6f jointControlWrench; { Eigen::Vector3f targetTCPLinearVelocity; @@ -395,19 +428,19 @@ namespace armarx Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3); Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3); - Eigen::Vector3f linearVel ; - if (isPhaseStop) - { - linearVel = ((float)cfg->phaseKpPos) * (desiredPosition - currentTCPPosition); - for (size_t i = 0; i < 3; ++i) - { - linearVel(i) = fmin(cfg->maxLinearVel, linearVel(i)); - } - } - else - { - linearVel = kpos.cwiseProduct(desiredPosition - currentTCPPosition); - } + Eigen::Vector3f linearVel = adaptK.cwiseProduct(desiredPosition - currentTCPPosition);; + // if (isPhaseStop) + // { + // linearVel = ((float)cfg->phaseKpPos) * (desiredPosition - currentTCPPosition); + // for (size_t i = 0; i < 3; ++i) + // { + // linearVel(i) = fmin(cfg->maxLinearVel, linearVel(i)); + // } + // } + // else + // { + // linearVel = kpos.cwiseProduct(desiredPosition - currentTCPPosition); + // } Eigen::Vector3f tcpDesiredForce = 0.001 * linearVel + dpos.cwiseProduct(- currentTCPLinearVelocity); Eigen::Vector3f currentTCPAngularVelocity; @@ -527,15 +560,29 @@ namespace armarx datafields["target_y"] = new Variant(targetPoseDebug(1, 3)); datafields["target_z"] = new Variant(targetPoseDebug(2, 3)); - // Eigen::Vector3f filteredForce = debugRT.getUpToDateReadBuffer().filteredForce; - // datafields["filtered_force_x"] = new Variant(filteredForce(0)); - // datafields["filtered_force_y"] = new Variant(filteredForce(1)); - // datafields["filtered_force_z"] = new Variant(filteredForce(2)); + Eigen::Vector3f filteredForce = debugRT.getUpToDateReadBuffer().filteredForce; + datafields["filteredforce_x"] = new Variant(filteredForce(0)); + datafields["filteredforce_y"] = new Variant(filteredForce(1)); + datafields["filteredforce_z"] = new Variant(filteredForce(2)); + + + Eigen::Vector3f reactForce = debugRT.getUpToDateReadBuffer().reactForce; + datafields["reactForce_x"] = new Variant(reactForce(0)); + datafields["reactForce_y"] = new Variant(reactForce(1)); + datafields["reactForce_z"] = new Variant(reactForce(2)); + + Eigen::VectorXf targetVel = debugRT.getUpToDateReadBuffer().targetVel; + datafields["targetVel_x"] = new Variant(targetVel(0)); + datafields["targetVel_y"] = new Variant(targetVel(1)); + datafields["targetVel_z"] = new Variant(targetVel(2)); + + Eigen::Vector3f adaptK = debugRT.getUpToDateReadBuffer().adaptK; + datafields["adaptK_x"] = new Variant(adaptK(0)); + datafields["adaptK_y"] = new Variant(adaptK(1)); + + datafields["canVal"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal); + datafields["deltaT"] = new Variant(debugOutputData.getUpToDateReadBuffer().deltaT); - // Eigen::VectorXf targetVel = debugRT.getUpToDateReadBuffer().targetVel; - // datafields["targetVel_x"] = new Variant(targetVel(0)); - // datafields["targetVel_y"] = new Variant(targetVel(1)); - // datafields["targetVel_z"] = new Variant(targetVel(2)); // datafields["targetVel_rx"] = new Variant(targetVel(3)); // datafields["targetVel_ry"] = new Variant(targetVel(4)); // datafields["targetVel_rz"] = new Variant(targetVel(5)); diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.h index 634d20dd2..3c4d82ba3 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.h +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointPeriodicTSDMPCompliantController.h @@ -107,6 +107,10 @@ namespace armarx struct DebugRTData { Eigen::Matrix4f targetPose; + Eigen::Vector3f filteredForce; + Eigen::Vector3f reactForce; + Eigen::Vector3f adaptK; + Eigen::VectorXf targetVel; }; TripleBuffer<DebugRTData> debugRT; @@ -168,6 +172,8 @@ namespace armarx Eigen::Vector3f filteredForce; Eigen::Vector3f forceOffset; + Eigen::Vector3f reactForce; + Eigen::Vector3f filteredForceInRoot; Eigen::Matrix3f toolTransform; Eigen::Vector3f oriToolDir; -- GitLab