diff --git a/source/RobotAPI/interface/units/DMPController/NJointJointSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.ice similarity index 100% rename from source/RobotAPI/interface/units/DMPController/NJointJointSpaceDMPController.ice rename to source/RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.ice diff --git a/source/RobotAPI/interface/units/DMPController/NJointTaskSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice similarity index 96% rename from source/RobotAPI/interface/units/DMPController/NJointTaskSpaceDMPController.ice rename to source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice index 1ea4be9012b590015af944a8e71ecfd708413297..850ab231f12ca392810c78c0af412454c8a4a28f 100644 --- a/source/RobotAPI/interface/units/DMPController/NJointTaskSpaceDMPController.ice +++ b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice @@ -86,6 +86,7 @@ module armarx { // dmp configuration + float DMPKd = 20; int kernelSize = 100; double tau = 1; int baseMode = 1; @@ -100,7 +101,8 @@ module armarx double phaseKpOri = 0.1; // misc - double timeDuration = 10; + Ice::DoubleSeq timeDurations; + Ice::StringSeq dmpTypes; double posToOriRatio = 100; // velocity controller configuration @@ -116,7 +118,7 @@ module armarx bool isFinished(); void runDMP(); - void setTemporalFactor(double tau); + void setTemporalFactor(int dmpId, double tau); void setViaPoints(int dmpId, double canVal, Ice::DoubleSeq point); void setGoals(int dmpId, Ice::DoubleSeq goals); diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt b/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt index 76755149a0b2879963a7faaff337d778e495ced9..ef4b0ffffec80572ab5e6b23a380a61e24e28c84 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt @@ -40,12 +40,17 @@ if (DMP_FOUND) DMPController/NJointJointSpaceDMPController.h DMPController/NJointTaskSpaceDMPController.h DMPController/NJointJSDMPController.h + DMPController/NJointTSDMPController.h + DMPController/NJointCCDMPController.h ) list(APPEND LIB_FILES DMPController/NJointJointSpaceDMPController.cpp DMPController/NJointTaskSpaceDMPController.cpp DMPController/NJointJSDMPController.cpp + DMPController/NJointTSDMPController.cpp + DMPController/NJointCCDMPController.cpp + ) list(APPEND LIBS ${DMP_LIBRARIES}) diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34c384badfbc7b1a56d372a4216a84b40aedffcd --- /dev/null +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.cpp @@ -0,0 +1,562 @@ +#include "NJointCCDMPController.h" + +namespace armarx +{ + NJointControllerRegistration<NJointCCDMPController> registrationControllerNJointCCDMPController("NJointCCDMPController"); + + NJointCCDMPController::NJointCCDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&) + { + cfg = NJointCCDMPControllerConfigPtr::dynamicCast(config); + ARMARX_CHECK_EXPRESSION(prov); + RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov); + ARMARX_CHECK_EXPRESSION(robotUnit); + ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty()); + VirtualRobot::RobotNodeSetPtr rns = robotUnit->getRtRobot()->getRobotNodeSet(cfg->nodeSetName); + + ARMARX_CHECK_EXPRESSION_W_HINT(rns, cfg->nodeSetName); + for (size_t i = 0; i < rns->getSize(); ++i) + { + std::string jointName = rns->getNode(i)->getName(); + ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF); + const SensorValueBase* sv = prov->getSensorValue(jointName); + targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>()); + + const SensorValue1DoFActuatorTorque* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>(); + const SensorValue1DoFGravityTorque* gravityTorqueSensor = sv->asA<SensorValue1DoFGravityTorque>(); + if (!torqueSensor) + { + ARMARX_WARNING << "No Torque sensor available for " << jointName; + } + if (!gravityTorqueSensor) + { + ARMARX_WARNING << "No Gravity Torque sensor available for " << jointName; + } + + torqueSensors.push_back(torqueSensor); + gravityTorqueSensors.push_back(gravityTorqueSensor); + }; + + tcp = (cfg->tcpName.empty()) ? rns->getTCP() : robotUnit->getRtRobot()->getRobotNode(cfg->tcpName); + ARMARX_CHECK_EXPRESSION_W_HINT(tcp, cfg->tcpName); + + // set tcp controller + tcpController.reset(new CartesianVelocityController(rns, tcp)); + nodeSetName = cfg->nodeSetName; + torquePIDs.resize(tcpController->rns->getSize(), pidController()); + + + + // set DMP + isDisturbance = false; + + dmpPtrList.resize(cfg->dmpNum); + canVals.resize(cfg->dmpNum); + timeDurations = cfg->timeDurations; + dmpTypes = cfg->dmpTypes; + for (size_t i = 0; i < dmpPtrList.size(); ++i) + { + dmpPtrList[i].reset(new UMIDMP(cfg->kernelSize, cfg->DMPKd, cfg->baseMode, cfg->tau)); + canVals[i] = timeDurations[i]; + } + finished = false; + + phaseL = cfg->phaseL; + phaseK = cfg->phaseK; + phaseDist0 = cfg->phaseDist0; + phaseDist1 = cfg->phaseDist1; + phaseKpPos = cfg->phaseKpPos; + phaseKpOri = cfg->phaseKpOri; + + posToOriRatio = cfg->posToOriRatio; + + // initialize tcp position and orientation + Eigen::Matrix4f pose = tcp->getPoseInRootFrame(); + tcpPosition(0) = pose(0, 3); + tcpPosition(1) = pose(1, 3); + tcpPosition(2) = pose(2, 3); + tcpOrientation = VirtualRobot::MathTools::eigen4f2rpy(pose); + + + NJointCCDMPControllerSensorData initSensorData; + initSensorData.deltaT = 0; + initSensorData.currentTime = 0; + initSensorData.currentPose = pose; + controllerSensorData.reinitAllBuffers(initSensorData); + + + currentStates.resize(cfg->dmpNum); + targetSubStates.resize(cfg->dmpNum); + targetState.resize(6); + + targetVels.resize(6); + NJointCCDMPControllerControlData initData; + initData.targetTSVel.resize(6); + for (size_t i = 0; i < 6; ++i) + { + initData.targetTSVel[i] = 0; + } + initData.nullspaceJointVelocities.resize(tcpController->rns->getSize(), 0); + initData.torqueKp.resize(tcpController->rns->getSize(), 0); + initData.torqueKd.resize(tcpController->rns->getSize(), 0); + initData.mode = ModeFromIce(cfg->mode); + reinitTripleBuffer(initData); + } + + std::string NJointCCDMPController::getClassName(const Ice::Current&) const + { + return "NJointCCDMPController"; + } + + void NJointCCDMPController::controllerRun() + { + if (!controllerSensorData.updateReadBuffer()) + { + return; + } + double deltaT = controllerSensorData.getReadBuffer().deltaT; + Eigen::Matrix4f currentPose = controllerSensorData.getReadBuffer().currentPose; + Eigen::Vector3f currentPosition; + currentPosition << currentPose(0, 3), currentPose(1, 3), currentPose(2, 3); + Eigen::Vector3f currentRPY = VirtualRobot::MathTools::eigen4f2rpy(currentPose); + + double posError = 0; + double oriError = 0; + for (size_t i = 0; i < 3; ++i) + { + posError += pow(currentPosition(i) - targetState[i], 2); + } + for (size_t i = 0; i < 3; ++i) + { + oriError += pow(currentRPY(i) - targetState[i + 3], 2); + } + + posError = sqrt(posError); + oriError = sqrt(oriError); + double error = posError + posToOriRatio * oriError; + + double phaseDist; + if (isDisturbance) + { + phaseDist = phaseDist1; + } + else + { + phaseDist = phaseDist0; + } + + double phaseStop = 0;//phaseL / (1 + exp(-phaseK * (error - phaseDist))); + double mpcFactor = 1 - (phaseStop / phaseL); + + + if (mpcFactor < 0.1) + { + isDisturbance = true; + } + + if (mpcFactor > 0.9) + { + isDisturbance = false; + } + + // run DMP one after another + Eigen::Matrix4f targetPose = Eigen::Matrix4f::Identity(); + std::vector<double> vel0; + vel0.resize(6); + for (size_t i = 0; i < vel0.size(); ++i) + { + vel0[i] = 0; + } + + bool finished = true; + for (size_t i = 0; i < cfg->dmpNum; ++i) + { + double timeDuration = timeDurations[i]; + std::string dmpType = dmpTypes[i]; + + if (dmpType == "Periodic") + { + if (canVals[i] <= 1e-8) + { + canVals[i] = timeDuration; + } + } + + if (canVals[i] > 1e-8) + { + DMP::UMIDMPPtr dmpPtr = dmpPtrList[i]; + double dmpDeltaT = deltaT / timeDuration; + double tau = dmpPtr->getTemporalFactor(); + canVals[i] -= 1 / tau * deltaT * 1 / (1 + phaseStop) ; + + + currentStates[i] = dmpPtr->calculateDirectlyVelocity + (currentStates[i], canVals[i] / timeDurations[i], dmpDeltaT, targetSubStates[i]); + + for (size_t j = 0; j < vel0.size(); ++j) + { + vel0[j] += currentStates[i][j].vel / timeDuration; + } + + + Eigen::Matrix4f targetSubMat = VirtualRobot::MathTools::rpy2eigen4f(targetSubStates[i][3], targetSubStates[i][4], targetSubStates[i][5]); + targetSubMat(0, 3) = targetSubStates[i][0]; + targetSubMat(1, 3) = targetSubStates[i][1]; + targetSubMat(2, 3) = targetSubStates[i][2]; + + targetPose = targetPose * targetSubMat; + + finished = false; + } + else + { + for (size_t j = 0; j < vel0.size(); ++j) + { + vel0[j] += 0; + } + + Eigen::Matrix4f targetSubMat = VirtualRobot::MathTools::rpy2eigen4f(targetSubStates[i][3], targetSubStates[i][4], targetSubStates[i][5]); + targetSubMat(0, 3) = targetSubStates[i][0]; + targetSubMat(1, 3) = targetSubStates[i][1]; + targetSubMat(2, 3) = targetSubStates[i][2]; + targetPose = targetPose * targetSubMat; + } + + } + + Eigen::Vector3f targetRPY = VirtualRobot::MathTools::eigen4f2rpy(targetPose); + targetState[0] = targetPose(0, 3); + targetState[1] = targetPose(1, 3); + targetState[2] = targetPose(2, 3); + targetState[3] = targetRPY(0); + targetState[4] = targetRPY(1); + targetState[5] = targetRPY(2); + + for (size_t i = 0; i < 3; i++) + { + double vel1 = phaseKpPos * (targetState[i] - currentPose(i, 3)); + targetVels[i] = mpcFactor * vel0[i] + (1 - mpcFactor) * vel1; + } + + for (size_t i = 0; i < 3; i++) + { + double vel1 = phaseKpOri * (targetState[i + 3] - currentRPY(i)); + targetVels[i + 3] = mpcFactor * vel0[i + 3] + (1 - mpcFactor) * vel1; + } + + + debugOutputData.getWriteBuffer().latestTargetVelocities["x_vel"] = targetVels[0]; + debugOutputData.getWriteBuffer().latestTargetVelocities["y_vel"] = targetVels[1]; + debugOutputData.getWriteBuffer().latestTargetVelocities["z_vel"] = targetVels[2]; + debugOutputData.getWriteBuffer().latestTargetVelocities["roll_vel"] = targetVels[3]; + debugOutputData.getWriteBuffer().latestTargetVelocities["pitch_vel"] = targetVels[4]; + debugOutputData.getWriteBuffer().latestTargetVelocities["yaw_vel"] = targetVels[5]; + debugOutputData.getWriteBuffer().dmpTargets["dmp_x"] = targetState[0]; + debugOutputData.getWriteBuffer().dmpTargets["dmp_y"] = targetState[1]; + debugOutputData.getWriteBuffer().dmpTargets["dmp_z"] = targetState[2]; + debugOutputData.getWriteBuffer().dmpTargets["dmp_roll"] = targetState[3]; + debugOutputData.getWriteBuffer().dmpTargets["dmp_pitch"] = targetState[4]; + debugOutputData.getWriteBuffer().dmpTargets["dmp_yaw"] = targetState[5]; + + debugOutputData.getWriteBuffer().mpcFactor = mpcFactor; + debugOutputData.getWriteBuffer().error = error; + debugOutputData.getWriteBuffer().phaseStop = phaseStop; + debugOutputData.getWriteBuffer().posError = posError; + debugOutputData.getWriteBuffer().oriError = oriError; + debugOutputData.getWriteBuffer().deltaT = deltaT; + + debugOutputData.getWriteBuffer().canVal0 = canVals[0]; + + + debugOutputData.commitWrite(); + + LockGuardType guard {controlDataMutex}; + getWriterControlStruct().targetTSVel = targetVels; + writeControlStruct(); + } + + + void NJointCCDMPController::rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) + { + double deltaT = sensorValuesTimestamp.toSecondsDouble(); + controllerSensorData.getWriteBuffer().currentPose = tcp->getPoseInRootFrame(); + controllerSensorData.getWriteBuffer().deltaT = deltaT; + controllerSensorData.getWriteBuffer().currentTime += deltaT; + + controllerSensorData.commitWrite(); + + + // cartesian vel controller + Eigen::VectorXf x; + auto mode = rtGetControlStruct().mode; + + if (mode == VirtualRobot::IKSolver::All) + { + x.resize(6); + for (size_t i = 0; i < 6; i++) + { + x(i) = rtGetControlStruct().targetTSVel[i]; + } + } + else if (mode == VirtualRobot::IKSolver::Position) + { + x.resize(3); + for (size_t i = 0; i < 3; i++) + { + x(i) = rtGetControlStruct().targetTSVel[i]; + } + + } + else if (mode == VirtualRobot::IKSolver::Orientation) + { + x.resize(3); + for (size_t i = 0; i < 3; i++) + { + x(i) = rtGetControlStruct().targetTSVel[i + 3]; + } + } + else + { + // No mode has been set + return; + } + + Eigen::VectorXf jnv = Eigen::VectorXf::Zero(tcpController->rns->getSize()); + float jointLimitAvoidanceKp = rtGetControlStruct().avoidJointLimitsKp; + if (jointLimitAvoidanceKp > 0) + { + jnv += jointLimitAvoidanceKp * tcpController->calculateJointLimitAvoidance(); + } + for (size_t i = 0; i < tcpController->rns->getSize(); i++) + { + jnv(i) += rtGetControlStruct().nullspaceJointVelocities.at(i); + if (torqueSensors.at(i) && gravityTorqueSensors.at(i) && rtGetControlStruct().torqueKp.at(i) != 0) + { + torquePIDs.at(i).Kp = rtGetControlStruct().torqueKp.at(i); + torquePIDs.at(i).Kd = rtGetControlStruct().torqueKd.at(i); + jnv(i) += torquePIDs.at(i).update(deltaT, torqueSensors.at(i)->torque - gravityTorqueSensors.at(i)->gravityTorque); + } + else + { + torquePIDs.at(i).lastError = 0; + } + } + + Eigen::VectorXf jointTargetVelocities = tcpController->calculate(x, jnv, mode); + for (size_t i = 0; i < targets.size(); ++i) + { + targets.at(i)->velocity = jointTargetVelocities(i); + } + } + + + void NJointCCDMPController::learnDMPFromFiles(int dmpId, const Ice::StringSeq& fileNames, const Ice::Current&) + { + DMP::Vec<DMP::SampledTrajectoryV2 > trajs; + + DMP::DVec ratios; + DMP::DVec goals; + DMP::Vec<DMP::DMPState > starts; + + for (size_t i = 0; i < fileNames.size(); ++i) + { + DMP::SampledTrajectoryV2 traj; + traj.readFromCSVFile(fileNames.at(i)); + traj = DMP::SampledTrajectoryV2::normalizeTimestamps(traj, 0, 1); + trajs.push_back(traj); + + if (i == 0) + { + goals.resize(traj.dim()); + starts.resize(traj.dim()); + for (size_t j = 0; j < goals.size(); ++j) + { + goals[j] = traj.rbegin()->getPosition(j); + starts[j].pos = traj.begin()->getPosition(j); + starts[j].vel = traj.begin()->getDeriv(j, 1) * timeDurations[dmpId]; + } + } + + if (i == 0) + { + ratios.push_back(1.0); + } + else + { + ratios.push_back(0.0); + } + + + } + + dmpPtrList[dmpId]->learnFromTrajectories(trajs); + dmpPtrList[dmpId]->setOneStepMPC(true); + dmpPtrList[dmpId]->styleParas = dmpPtrList[dmpId]->getStyleParasWithRatio(ratios); + + + DMP::Vec<DMP::DMPState > currentState; + if (dmpId == 0) + { + for (size_t i = 0; i < 3; i++) + { + DMP::DMPState currentPos; + currentPos.pos = tcpPosition(i); + currentPos.vel = 0; + currentState.push_back(currentPos); + } + for (size_t i = 0; i < 3; i++) + { + DMP::DMPState currentPos; + currentPos.pos = tcpOrientation(i); + currentPos.vel = 0; + currentState.push_back(currentPos); + } + } + else + { + currentState = starts; + + + } + for (size_t i = 0; i < 3; i++) + { + targetState[i] = tcpPosition(i); + } + for (size_t i = 0; i < 3; i++) + { + targetState[i + 3] = tcpOrientation(i); + } + + currentStates[dmpId] = currentState; + + dmpPtrList[dmpId]->prepareExecution(goals, currentState, 1, tau); + dmpPtrList[dmpId]->setTemporalFactor(tau); + ARMARX_INFO << "Learned DMP ... "; + } + + void NJointCCDMPController::setViaPoints(int dmpId, Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&) + { + ViaPoint viaPoint(u, viapoint); + + LockGuardType guard(controllerMutex); + dmpPtrList[dmpId]->setViaPoint(viaPoint); + } + + void NJointCCDMPController::setGoals(int dmpId, const Ice::DoubleSeq& goals, const Ice::Current& ice) + { + setViaPoints(dmpId, dmpPtrList[dmpId]->getUMin(), goals, ice); + } + + void NJointCCDMPController::setControllerTarget(Ice::Float avoidJointLimitsKp, NJointTaskSpaceDMPControllerMode::CartesianSelection mode, const Ice::Current&) + { + LockGuardType guard {controlDataMutex}; + getWriterControlStruct().avoidJointLimitsKp = avoidJointLimitsKp; + getWriterControlStruct().mode = ModeFromIce(mode); + writeControlStruct(); + } + + VirtualRobot::IKSolver::CartesianSelection NJointCCDMPController::ModeFromIce(const NJointTaskSpaceDMPControllerMode::CartesianSelection mode) + { + if (mode == NJointTaskSpaceDMPControllerMode::CartesianSelection::ePosition) + { + return VirtualRobot::IKSolver::CartesianSelection::Position; + } + if (mode == NJointTaskSpaceDMPControllerMode::CartesianSelection::eOrientation) + { + return VirtualRobot::IKSolver::CartesianSelection::Orientation; + } + if (mode == NJointTaskSpaceDMPControllerMode::CartesianSelection::eAll) + { + return VirtualRobot::IKSolver::CartesianSelection::All; + } + ARMARX_ERROR_S << "invalid mode " << mode; + return (VirtualRobot::IKSolver::CartesianSelection)0; + } + + + void NJointCCDMPController::setTorqueKp(const StringFloatDictionary& torqueKp, const Ice::Current&) + { + LockGuardType guard {controlDataMutex}; + for (size_t i = 0; i < tcpController->rns->getSize(); i++) + { + getWriterControlStruct().torqueKp.at(i) = torqueKp.at(tcpController->rns->getNode(i)->getName()); + } + writeControlStruct(); + } + + void NJointCCDMPController::setNullspaceJointVelocities(const StringFloatDictionary& nullspaceJointVelocities, const Ice::Current&) + { + LockGuardType guard {controlDataMutex}; + for (size_t i = 0; i < tcpController->rns->getSize(); i++) + { + getWriterControlStruct().nullspaceJointVelocities.at(i) = nullspaceJointVelocities.at(tcpController->rns->getNode(i)->getName()); + } + writeControlStruct(); + } + + void NJointCCDMPController::runDMP(const Ice::Current&) + { + + finished = false; + + + ARMARX_INFO << "run DMP"; + controllerTask->start(); + + } + + void NJointCCDMPController::setTemporalFactor(int dmpId, double tau, const Ice::Current&) + { + LockGuardType guard(controllerMutex); + dmpPtrList[dmpId]->setTemporalFactor(tau); + } + + void NJointCCDMPController::rtPreActivateController() + { + } + + void NJointCCDMPController::rtPostDeactivateController() + { + + } + + void NJointCCDMPController::onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx& debugObs) + { + StringVariantBaseMap datafields; + auto values = debugOutputData.getUpToDateReadBuffer().latestTargetVelocities; + for (auto& pair : values) + { + datafields[pair.first] = new Variant(pair.second); + } + + auto dmpTargets = debugOutputData.getUpToDateReadBuffer().dmpTargets; + for (auto& pair : dmpTargets) + { + datafields[pair.first] = new Variant(pair.second); + } + + datafields["mpcFactor"] = new Variant(debugOutputData.getUpToDateReadBuffer().mpcFactor); + datafields["poseError"] = new Variant(debugOutputData.getUpToDateReadBuffer().error); + datafields["phaseStop"] = new Variant(debugOutputData.getUpToDateReadBuffer().phaseStop); + datafields["posError"] = new Variant(debugOutputData.getUpToDateReadBuffer().posError); + datafields["oriError"] = new Variant(debugOutputData.getUpToDateReadBuffer().oriError); + datafields["deltaT"] = new Variant(debugOutputData.getUpToDateReadBuffer().deltaT); + datafields["canVal0"] = new Variant(debugOutputData.getUpToDateReadBuffer().canVal0); + + debugObs->setDebugChannel("DMPController", datafields); + } + + void NJointCCDMPController::onInitComponent() + { + ARMARX_INFO << "init ..."; + controllerTask = new PeriodicTask<NJointCCDMPController>(this, &NJointCCDMPController::controllerRun, 0.5); + } + + void NJointCCDMPController::onDisconnectComponent() + { + controllerTask->stop(); + ARMARX_INFO << "stopped ..."; + } + + + +} diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.h new file mode 100644 index 0000000000000000000000000000000000000000..80ecfc3a8b1783a7066895b6d26f7e8321760185 --- /dev/null +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.h @@ -0,0 +1,162 @@ + +#pragma once + +#include <RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h> +#include <VirtualRobot/Robot.h> +#include <RobotAPI/components/units/RobotUnit/RobotUnit.h> +#include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h> +#include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h> +#include <VirtualRobot/IK/DifferentialIK.h> +#include <dmp/representation/dmp/umidmp.h> +#include <RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.h> +#include <RobotAPI/libraries/core/CartesianVelocityController.h> + + +using namespace DMP; +namespace armarx +{ + + + TYPEDEF_PTRS_HANDLE(NJointCCDMPController); + TYPEDEF_PTRS_HANDLE(NJointCCDMPControllerControlData); + + typedef std::pair<double, DVec > ViaPoint; + typedef std::vector<ViaPoint > ViaPointsSet; + class NJointCCDMPControllerControlData + { + public: + std::vector<float> targetTSVel; + // cartesian velocity control data + std::vector<float> nullspaceJointVelocities; + float avoidJointLimitsKp = 0; + std::vector<float> torqueKp; + std::vector<float> torqueKd; + VirtualRobot::IKSolver::CartesianSelection mode = VirtualRobot::IKSolver::All; + }; + + class pidController + { + public: + float Kp = 0, Kd = 0; + float lastError = 0; + float update(float dt, float error) + { + float derivative = (error - lastError) / dt; + float retVal = Kp * error + Kd * derivative; + lastError = error; + return retVal; + } + }; + + class NJointCCDMPController : + public NJointControllerWithTripleBuffer<NJointCCDMPControllerControlData>, + public NJointCCDMPControllerInterface + { + public: + using ConfigPtrT = NJointCCDMPControllerConfigPtr; + NJointCCDMPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&); + + // NJointControllerInterface interface + std::string getClassName(const Ice::Current&) const; + + // NJointController interface + + void rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration); + + // NJointCCDMPControllerInterface interface + void learnDMPFromFiles(int dmpId, const Ice::StringSeq& fileNames, const Ice::Current&); + bool isFinished(const Ice::Current&) + { + return finished; + } + + void runDMP(const Ice::Current&); + void setTemporalFactor(int dmpId, Ice::Double tau, const Ice::Current&); + void setViaPoints(int dmpId, Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&); + void setGoals(int dmpId, const Ice::DoubleSeq& goals, const Ice::Current&); + + void setControllerTarget(Ice::Float avoidJointLimitsKp, NJointTaskSpaceDMPControllerMode::CartesianSelection mode, const Ice::Current&); + void setTorqueKp(const StringFloatDictionary& torqueKp, const Ice::Current&); + void setNullspaceJointVelocities(const StringFloatDictionary& nullspaceJointVelocities, const Ice::Current&); + protected: + void rtPreActivateController() override; + void rtPostDeactivateController() override; + VirtualRobot::IKSolver::CartesianSelection ModeFromIce(const NJointTaskSpaceDMPControllerMode::CartesianSelection mode); + virtual void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&); + + void onInitComponent(); + void onDisconnectComponent(); + void controllerRun(); + + private: + struct DebugBufferData + { + StringFloatDictionary latestTargetVelocities; + StringFloatDictionary dmpTargets; + double mpcFactor; + double error; + double phaseStop; + double posError; + double oriError; + double deltaT; + double canVal0; + }; + + TripleBuffer<DebugBufferData> debugOutputData; + + struct NJointCCDMPControllerSensorData + { + double currentTime; + double deltaT; + Eigen::Matrix4f currentPose; + }; + TripleBuffer<NJointCCDMPControllerSensorData> controllerSensorData; + + std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors; + std::vector<const SensorValue1DoFGravityTorque*> gravityTorqueSensors; + std::vector<ControlTarget1DoFActuatorVelocity*> targets; + + // velocity ik controller parameters + std::vector<pidController> torquePIDs; + CartesianVelocityControllerPtr tcpController; + std::string nodeSetName; + + // dmp parameters + std::vector<UMIDMPPtr > dmpPtrList; + std::vector<double> canVals; + std::vector<double> timeDurations; + std::vector<std::string > dmpTypes; + + std::vector<Vec<DMPState > > currentStates; + std::vector<DVec > targetSubStates; + + bool finished; + double tau; + ViaPointsSet viaPoints; + bool isDisturbance; + + + // phaseStop parameters + double phaseL; + double phaseK; + double phaseDist0; + double phaseDist1; + double phaseKpPos; + double phaseKpOri; + + double posToOriRatio; + + std::vector<float> targetVels; + + NJointCCDMPControllerConfigPtr cfg; + VirtualRobot::RobotNodePtr tcp; + Eigen::Vector3f tcpPosition; + Eigen::Vector3f tcpOrientation; + + DMP::DVec targetState; + mutable MutexType controllerMutex; + PeriodicTask<NJointCCDMPController>::pointer_type controllerTask; + }; + +} // namespace armarx + diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h index 16b456700cc05f175718e381eb4e7683378f3d8f..625058be3fa1a6d22047392e6cd4dce582590afc 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h @@ -9,7 +9,7 @@ #include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h> #include <dmp/representation/dmp/umidmp.h> #include <ArmarXCore/core/services/tasks/RunningTask.h> -#include <RobotAPI/interface/units/DMPController/NJointJointSpaceDMPController.h> +#include <RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.h> namespace armarx { diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h index 9d7e6a53edc234f521373d4bb7cf3f0106df8f1a..173c7cfb146f2117b2c6a8df498baffa2eb21477 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h @@ -8,7 +8,7 @@ #include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h> #include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h> #include <dmp/representation/dmp/umidmp.h> -#include <RobotAPI/interface/units/DMPController/NJointJointSpaceDMPController.h> +#include <RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.h> namespace armarx { diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp index 9480a8c0364636520ff5bc9e0c6a3c7e41a3b0d0..92df61bbc9a916d76e403329d823c70f7ed3cd6a 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp @@ -115,12 +115,19 @@ namespace armarx currentState = controllerSensorData.getReadBuffer().currentState; + std::vector<double> currentposi; + currentposi.resize(3); for (size_t i = 0; i < 3; ++i) { + currentposi[i] = currentState[i].pos; posError += pow(currentState[i].pos - targetState[i], 2); } + + std::vector<double> currentori; + currentori.resize(3); for (size_t i = 0; i < 3; ++i) { + currentori[i] = currentState[i + 3].pos; oriError += pow(currentState[i + 3].pos - targetState[i + 3], 2); } @@ -140,7 +147,7 @@ namespace armarx phaseDist = phaseDist0; } - phaseStop = 0;//phaseL / (1 + exp(-phaseK * (error - phaseDist))); + phaseStop = phaseL / (1 + exp(-phaseK * (error - phaseDist))); mpcFactor = 1 - (phaseStop / phaseL); if (mpcFactor < 0.1) @@ -164,13 +171,13 @@ namespace armarx for (size_t i = 0; i < 3; i++) { vel0 = currentState[i].vel / timeDuration; - vel1 = phaseKpPos * (targetState[i] - tcpPosition[i]); + vel1 = phaseKpPos * (targetState[i] - currentposi[i]); targetVels[i] = mpcFactor * vel0 + (1 - mpcFactor) * vel1; } for (size_t i = 0; i < 3; i++) { vel0 = currentState[i + 3].vel / timeDuration; - vel1 = phaseKpOri * (targetState[i + 3] - tcpOrientation[i]); + vel1 = phaseKpOri * (targetState[i + 3] - currentori[i]); targetVels[i + 3] = mpcFactor * vel0 + (1 - mpcFactor) * vel1; } } diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h index ec8d216b992dd30b13edfa6f49b41ad987f897b3..e23451a67396f9e3303b760b25fb70aed9d2269f 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h @@ -8,7 +8,7 @@ #include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h> #include <VirtualRobot/IK/DifferentialIK.h> #include <dmp/representation/dmp/umidmp.h> -#include <RobotAPI/interface/units/DMPController/NJointTaskSpaceDMPController.h> +#include <RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.h> #include <RobotAPI/libraries/core/CartesianVelocityController.h> diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h index d45c8ce03449c3a2c1694269563a4618a657220c..b5f3fa66e39c20002747e7e02372e7f45c5aed86 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h @@ -8,7 +8,7 @@ #include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h> #include <VirtualRobot/IK/DifferentialIK.h> #include <dmp/representation/dmp/umidmp.h> -#include <RobotAPI/interface/units/DMPController/NJointTaskSpaceDMPController.h> +#include <RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.h> #include <RobotAPI/libraries/core/CartesianVelocityController.h>