diff --git a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt index 3615120f6c99c496a64c9a7ee17c7bbb2b70dc31..317729db5c2481f35c7e1ddd722cd88b84f99566 100644 --- a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt +++ b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt @@ -124,13 +124,16 @@ if (DMP_FOUND) message(STATUS "DMP libraries is ${DMP_LIBRARIES}") include_directories(${DMP_INCLUDE_DIRS}) - link_directories(${DMP_LIB_DIRS}) +# link_directories(${DMP_LIB_DIRS}) list(APPEND LIB_HEADERS NJointControllers/NJointJointSpaceDMPController.h + NJointControllers/NJointTaskSpaceDMPController.h ) list(APPEND LIB_FILES - NJointControllers/NJointJointSpaceDMPController.cpp) + NJointControllers/NJointJointSpaceDMPController.cpp + NJointControllers/NJointTaskSpaceDMPController.cpp + ) list(APPEND LIBS ${DMP_LIBRARIES}) endif () diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointDMPCartesianVelocityController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointDMPCartesianVelocityController.cpp deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointDMPCartesianVelocityController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointDMPCartesianVelocityController.h deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.cpp index 299888c1b3020199403bd17a42d8d256de9f21e3..d7073ab3f84bab8eff8f2ed3850d6ab488cca5c6 100644 --- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.cpp +++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.cpp @@ -25,17 +25,21 @@ namespace armarx positionSensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorPosition>())); torqueSensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorTorque>())); gravityTorqueSensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFGravityTorque>())); + velocitySensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorVelocity>())); } if (cfg->jointNames.size() == 0) { ARMARX_ERROR << "cfg->jointNames.size() == 0"; } - DMPAsForwardControl = cfg->DMPAsForwardControl; - dmpPtr.reset(new DMP::UMIDMP(cfg->kernelSize, cfg->Kd, cfg->baseMode, cfg->tau)); + dmpPtr.reset(new DMP::UMIDMP(cfg->kernelSize, cfg->DMPKd, cfg->baseMode, cfg->tau)); timeDuration = cfg->timeDuration; canVal = timeDuration; finished = false; + phaseL = cfg->phaseL; + phaseK = cfg->phaseK; + phaseDist0 = cfg->phaseDist0; + phaseKp = cfg->phaseKp; NJointJointSpaceDMPControllerControlData initData; initData.tau = 1.0; @@ -48,23 +52,36 @@ namespace armarx if (rtGetControlStruct().isStart) { currentState.clear(); + double phaseStop = 0; + double error = 0; + std::vector<double> currentPosition; + std::vector<double> currentVelocity; for (size_t i = 0; i < dimNames.size(); i++) { const auto& jointName = dimNames.at(i); DMP::DMPState currentPos; currentPos.pos = (positionSensors.count(jointName) == 1) ? positionSensors[jointName]->position : 0.0f; currentPos.vel = (velocitySensors.count(jointName) == 1) ? velocitySensors[jointName]->velocity : 0.0f; + currentPos.vel *= timeDuration; currentState.push_back(currentPos); + currentPosition.push_back(currentPos.pos); + currentVelocity.push_back(currentPos.vel); + + error += pow(currentPos.pos - targetState[i], 2); + } + error = sqrt(error); + phaseStop = phaseL / (1 + exp(-phaseK * (error - phaseDist0))); + double mpcFactor = 1 - (phaseStop / phaseL); double tau = rtGetControlStruct().tau; double deltaT = timeSinceLastIteration.toSecondsDouble(); - canVal -= 1 / tau * deltaT * 1 ; + canVal -= 1 / tau * deltaT * 1 / (1 + phaseStop); double dmpDeltaT = deltaT / timeDuration; dmpPtr->setTemporalFactor(tau); - DMP::DVec targetState; - currentState = dmpPtr->calculateNextPointWithEulerMethod(currentState, canVal / timeDuration, dmpDeltaT, targetState, 1.0); + currentState = dmpPtr->calculateDirectlyVelocity(currentState, canVal / timeDuration, dmpDeltaT, targetState); + if (canVal < 1e-8) { finished = true; @@ -75,7 +92,10 @@ namespace armarx const auto& jointName = dimNames.at(i); if (targets.count(jointName) == 1) { - targets[jointName]->velocity = finished ? 0.0f : currentState[i].vel; + double vel0 = currentState[i].vel / timeDuration; + double vel1 = phaseKp * (targetState[i] - currentPosition[i]); + double vel = mpcFactor * vel0 + (1 - mpcFactor) * vel1; + targets[jointName]->velocity = finished ? 0.0f : vel; } } } @@ -115,6 +135,7 @@ namespace armarx void NJointJointSpaceDMPController::runDMP(const Ice::DoubleSeq& goals, double tau, const Ice::Current&) { currentState.clear(); + targetState.clear(); for (size_t i = 0; i < dimNames.size(); i++) { const auto& jointName = dimNames.at(i); @@ -122,6 +143,7 @@ namespace armarx currentPos.pos = (positionSensors.count(jointName) == 1) ? positionSensors[jointName]->position : 0.0f; currentPos.vel = (velocitySensors.count(jointName) == 1) ? velocitySensors[jointName]->velocity : 0.0f; currentState.push_back(currentPos); + targetState.push_back(currentPos.pos); } dmpPtr->prepareExecution(goals, currentState, 1, tau); finished = false; diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.h index 89d1395dcb27ca170b25d9631e1a9cfc8da07d48..7151002d7db3a35ffc3946d1eaaea7f1547ac02a 100644 --- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.h +++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointJointSpaceDMPController.h @@ -84,8 +84,16 @@ namespace armarx double tau; double finished; + + // phaseStop parameters + double phaseL; + double phaseK; + double phaseDist0; + double phaseKp; + std::vector<std::string> dimNames; DMP::Vec<DMP::DMPState> currentState; + DMP::DVec targetState; }; } // namespace armarx diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceDMPController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceDMPController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6a70da0cb1323f893b3cc1d23f7e9b75cb0e443 --- /dev/null +++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceDMPController.cpp @@ -0,0 +1,375 @@ +#include "NJointTaskSpaceDMPController.h" + +namespace armarx +{ + NJointControllerRegistration<NJointTaskSpaceDMPController> registrationControllerNJointTaskSpaceDMPController("NJointTaskSpaceDMPController"); + + NJointTaskSpaceDMPController::NJointTaskSpaceDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&) + { + cfg = NJointTaskSpaceDMPControllerConfigPtr::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()); + + + NJointTaskSpaceDMPControllerControlData initData; + 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); + + // set DMP + dmpPtr.reset(new UMIDMP(cfg->kernelSize, cfg->DMPKd, cfg->baseMode, cfg->tau)); + timeDuration = cfg->timeDuration; + canVal = timeDuration; + finished = false; + + initData.dmpPtr = dmpPtr; + initData.isStart = false; + reinitTripleBuffer(initData); + + phaseL = cfg->phaseL; + phaseK = cfg->phaseK; + phaseDist0 = cfg->phaseDist0; + phaseKp = cfg->phaseKp; + + // 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); + } + + std::string NJointTaskSpaceDMPController::getClassName(const Ice::Current&) const + { + return "NJointTaskSpaceDMPController"; + } + + void NJointTaskSpaceDMPController::rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) + { + if (rtGetControlStruct().isStart) + { + UMIDMPPtr dmpPtr = rtGetControlStruct().dmpPtr; + + // DMP controller + Eigen::Matrix4f pose = tcp->getPoseInRootFrame(); + Eigen::Vector3f currPosition; + Eigen::Vector3f currOrientation = VirtualRobot::MathTools::eigen4f2rpy(pose); + currPosition(0) = pose(0, 3); + currPosition(1) = pose(1, 3); + currPosition(2) = pose(2, 3); + + double deltaT = timeSinceLastIteration.toSecondsDouble(); + double dmpDeltaT = deltaT / timeDuration; + + Eigen::Vector3f posVel; + Eigen::Vector3f oriVel; + + if (deltaT == 0) + { + posVel << 0, 0 , 0; + oriVel << 0, 0 , 0; + } + else + { + posVel = (currPosition - tcpPosition) / deltaT; + oriVel = (currOrientation - tcpOrientation) / deltaT; + } + + tcpPosition = currPosition; + tcpOrientation = currOrientation; + + double phaseStop = 0; + double error = 0; + currentState.clear(); + for (size_t i = 0; i < 3; i++) + { + DMP::DMPState currentPos; + currentPos.pos = tcpPosition(i); + currentPos.vel = posVel(i) * timeDuration; + currentState.push_back(currentPos); + + error += pow(currentPos.pos - targetState[i], 2); + } + + for (size_t i = 0; i < 3; i++) + { + DMP::DMPState currentPos; + currentPos.pos = tcpOrientation(i); + currentPos.vel = oriVel(i) * timeDuration; + currentState.push_back(currentPos); + + error += pow(currentPos.pos - targetState[i + 3], 2); + } + + error = sqrt(error); + phaseStop = phaseL / (1 + exp(-phaseK * (error - phaseDist0))); + double mpcFactor = 1 - (phaseStop / phaseL); + + double tau = dmpPtr->getTemporalFactor(); + canVal -= 1 / tau * deltaT * 1 / (1 + phaseStop) ; + currentState = dmpPtr->calculateDirectlyVelocity(currentState, canVal / timeDuration, dmpDeltaT, targetState); + + if (canVal < 1e-8) + { + finished = true; + } + + // cartesian velocity controller + Eigen::VectorXf x; + auto mode = rtGetControlStruct().mode; + + double vel0, vel1; + if (mode == VirtualRobot::IKSolver::All) + { + x.resize(6); + + for (size_t i = 0; i < 3; i++) + { + vel0 = currentState[i].vel / timeDuration; + vel1 = phaseKp * (targetState[i] - tcpPosition[i]); + x(i) = mpcFactor * vel0 + (1 - mpcFactor) * vel1; + } + for (size_t i = 0; i < 3; i++) + { + vel0 = currentState[i + 3].vel / timeDuration; + vel1 = phaseKp * (targetState[i + 3] - tcpOrientation[i]); + x(i + 3) = mpcFactor * vel0 + (1 - mpcFactor) * vel1; + } + } + else if (mode == VirtualRobot::IKSolver::Position) + { + x.resize(3); + + for (size_t i = 0; i < 3; i++) + { + vel0 = currentState[i].vel / timeDuration; + vel1 = phaseKp * (targetState[i] - tcpPosition[i]); + x(i) = mpcFactor * vel0 + (1 - mpcFactor) * vel1; + } + } + else if (mode == VirtualRobot::IKSolver::Orientation) + { + x.resize(3); + + for (size_t i = 0; i < 3; i++) + { + vel0 = currentState[i + 3].vel / timeDuration; + vel1 = phaseKp * (targetState[i + 3] - tcpOrientation[i]); + x(i) = mpcFactor * vel0 + (1 - mpcFactor) * vel1; + } + } + 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(timeSinceLastIteration.toSecondsDouble(), torqueSensors.at(i)->torque - gravityTorqueSensors.at(i)->gravityTorque); + //jnv(i) += rtGetControlStruct().torqueKp.at(i) * (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 NJointTaskSpaceDMPController::learnDMPFromFiles(const Ice::StringSeq& fileNames, const Ice::Current&) + { + DMP::Vec<DMP::SampledTrajectoryV2 > trajs; + + DMP::DVec ratios; + 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) + { + ratios.push_back(1.0); + } + else + { + ratios.push_back(0.0); + } + } + + dmpPtr->learnFromTrajectories(trajs); + dmpPtr->setOneStepMPC(true); + dmpPtr->styleParas = dmpPtr->getStyleParasWithRatio(ratios); + + ARMARX_INFO << "Learned DMP ... "; + } + + void NJointTaskSpaceDMPController::setViaPoints(Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&) + { + ViaPoint viaPoint(u, viapoint); + dmpPtr->setViaPoint(viaPoint); + + LockGuardType guard {controlDataMutex}; + getWriterControlStruct().dmpPtr = dmpPtr; + writeControlStruct(); + } + + void NJointTaskSpaceDMPController::setGoals(const Ice::DoubleSeq& goals, const Ice::Current& ice) + { + setViaPoints(dmpPtr->getUMin(), goals, ice); + } + + void NJointTaskSpaceDMPController::setControllerTarget(Ice::Float avoidJointLimitsKp, NJointTaskSpaceDMPControllerMode::CartesianSelection mode, const Ice::Current&) + { + LockGuardType guard {controlDataMutex}; + getWriterControlStruct().avoidJointLimitsKp = avoidJointLimitsKp; + getWriterControlStruct().mode = ModeFromIce(mode); + writeControlStruct(); + } + + VirtualRobot::IKSolver::CartesianSelection NJointTaskSpaceDMPController::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 NJointTaskSpaceDMPController::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 NJointTaskSpaceDMPController::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 NJointTaskSpaceDMPController::runDMP(const Ice::DoubleSeq& goals, double tau, const Ice::Current&) + { + currentState.clear(); + targetState.clear(); + for (size_t i = 0; i < 3; i++) + { + DMP::DMPState currentPos; + currentPos.pos = tcpPosition(i); + currentPos.vel = 0; + currentState.push_back(currentPos); + targetState.push_back(currentPos.pos); + } + for (size_t i = 0; i < 3; i++) + { + DMP::DMPState currentPos; + currentPos.pos = tcpOrientation(i); + currentPos.vel = 0; + currentState.push_back(currentPos); + targetState.push_back(currentPos.pos); + } + dmpPtr->prepareExecution(goals, currentState, 1, tau); + finished = false; + dmpPtr->setTemporalFactor(tau); + + LockGuardType guard {controlDataMutex}; + getWriterControlStruct().dmpPtr = dmpPtr; + getWriterControlStruct().isStart = true; + writeControlStruct(); + + } + + void NJointTaskSpaceDMPController::setTemporalFactor(double tau, const Ice::Current&) + { + dmpPtr->setTemporalFactor(tau); + LockGuardType guard {controlDataMutex}; + getWriterControlStruct().dmpPtr = dmpPtr; + writeControlStruct(); + } + + void NJointTaskSpaceDMPController::rtPreActivateController() + { + } + + void NJointTaskSpaceDMPController::rtPostDeactivateController() + { + + } + +} diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceDMPController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceDMPController.h new file mode 100644 index 0000000000000000000000000000000000000000..7a0b4c2aabc8b6a5974cca219ad0d292cc000435 --- /dev/null +++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceDMPController.h @@ -0,0 +1,126 @@ + +#pragma once + + +#include "NJointController.h" +#include <VirtualRobot/Robot.h> +#include "../RobotUnit.h" +#include "../ControlTargets/ControlTarget1DoFActuator.h" +#include "../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(NJointTaskSpaceDMPController); + TYPEDEF_PTRS_HANDLE(NJointTaskSpaceDMPControllerControlData); + + typedef std::pair<double, DVec > ViaPoint; + typedef std::vector<ViaPoint > ViaPointsSet; + class NJointTaskSpaceDMPControllerControlData + { + public: + // dmp control data + UMIDMPPtr dmpPtr; + bool isStart; + + // 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 NJointTaskSpaceDMPController : + public NJointControllerWithTripleBuffer<NJointTaskSpaceDMPControllerControlData>, + public NJointTaskSpaceDMPControllerInterface + { + public: + using ConfigPtrT = NJointTaskSpaceDMPControllerConfigPtr; + NJointTaskSpaceDMPController(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); + + // NJointTaskSpaceDMPControllerInterface interface + void learnDMPFromFiles(const Ice::StringSeq& fileNames, const Ice::Current&); + bool isFinished(const Ice::Current&) + { + return finished; + } + + void runDMP(const Ice::DoubleSeq& goals, Ice::Double tau, const Ice::Current&); + void setTemporalFactor(Ice::Double tau, const Ice::Current&); + void setViaPoints(Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&); + void setGoals(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); + + private: + 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 + UMIDMPPtr dmpPtr; + double timeDuration; + double canVal; + bool finished; + double tau; + ViaPointsSet viaPoints; + + // phaseStop parameters + double phaseL; + double phaseK; + double phaseDist0; + double phaseKp; + + + NJointTaskSpaceDMPControllerConfigPtr cfg; + VirtualRobot::RobotNodePtr tcp; + Eigen::Vector3f tcpPosition; + Eigen::Vector3f tcpOrientation; + DMP::Vec<DMP::DMPState> currentState; + DMP::DVec targetState; + + + }; + +} // namespace armarx + diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt index 8bc308172ea96dae58ca1f38d680cdb57b75c441..2ea2965e5fc0a6c23787684003fdaf66677d335a 100644 --- a/source/RobotAPI/interface/CMakeLists.txt +++ b/source/RobotAPI/interface/CMakeLists.txt @@ -48,6 +48,7 @@ set(SLICE_FILES units/RobotUnit/RobotUnitInterface.ice units/RobotUnit/NJointJointSpaceDMPController.ice + units/RobotUnit/NJointTaskSpaceDMPController.ice components/ViewSelectionInterface.ice components/TrajectoryPlayerInterface.ice diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.ice index 4faa50476deb917d8321f2fbf9e8423aeb7fc50d..356cd9ba185bee800a404116dd6123de1c1f2c5b 100644 --- a/source/RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.ice +++ b/source/RobotAPI/interface/units/RobotUnit/NJointJointSpaceDMPController.ice @@ -20,8 +20,8 @@ * GNU General Public License */ -#ifndef _ARMARX_ROBOTAPI_NJointTrajectoryControllerInterface_SLICE_ -#define _ARMARX_ROBOTAPI_NJointTrajectoryControllerInterface_SLICE_ +#ifndef _ARMARX_ROBOTAPI_NJointJointSpaceDMPControllerInterface_SLICE_ +#define _ARMARX_ROBOTAPI_NJointJointSpaceDMPControllerInterface_SLICE_ #include <RobotAPI/interface/units/RobotUnit/NJointController.ice> #include <RobotAPI/interface/core/Trajectory.ice> @@ -31,13 +31,17 @@ module armarx class NJointJointSpaceDMPControllerConfig extends NJointControllerConfig { Ice::StringSeq jointNames; - float Kd = 20; + float DMPKd = 20; int kernelSize = 100; double tau = 1; int baseMode = 1; + double phaseL = 10; + double phaseK = 10; + double phaseDist0 = 0.3; + double phaseKp = 1; + double timeDuration = 10; - bool DMPAsForwardControl = true; }; diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice new file mode 100644 index 0000000000000000000000000000000000000000..d9d4c42d0bfc6fdff332b6eb0f979d7c33cb27c4 --- /dev/null +++ b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice @@ -0,0 +1,81 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::NJointControllerInterface + * @author Mirko Waechter ( mirko dot waechter at kit dot edu ) + * @date 2017 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#ifndef _ARMARX_ROBOTAPI_NJointTaskSpaceControllerInterface_SLICE_ +#define _ARMARX_ROBOTAPI_NJointTaskSpaceControllerInterface_SLICE_ + +#include <RobotAPI/interface/units/RobotUnit/NJointController.ice> +#include <RobotAPI/interface/core/Trajectory.ice> + +module armarx +{ + module NJointTaskSpaceDMPControllerMode + { + enum CartesianSelection + { + ePosition = 7, + eOrientation = 8, + eAll = 15 + }; + }; + + + class NJointTaskSpaceDMPControllerConfig extends NJointControllerConfig + { + + // dmp configuration + float DMPKd = 20; + int kernelSize = 100; + double tau = 1; + int baseMode = 1; + + double phaseL = 10; + double phaseK = 10; + double phaseDist0 = 0.3; + double phaseKp = 1; + + double timeDuration = 10; + + // velocity controller configuration + string nodeSetName = ""; + string tcpName = ""; + NJointTaskSpaceDMPControllerMode::CartesianSelection mode = NJointTaskSpaceDMPControllerMode::eAll; + + }; + + + interface NJointTaskSpaceDMPControllerInterface extends NJointControllerInterface + { + void learnDMPFromFiles(Ice::StringSeq trajfiles); + bool isFinished(); + void runDMP(Ice::DoubleSeq goals, double tau); + + void setTemporalFactor(double tau); + void setViaPoints(double canVal, Ice::DoubleSeq point); + void setGoals(Ice::DoubleSeq goals); + + void setControllerTarget(float avoidJointLimitsKp, NJointTaskSpaceDMPControllerMode::CartesianSelection mode); + void setTorqueKp(StringFloatDictionary torqueKp); + void setNullspaceJointVelocities(StringFloatDictionary nullspaceJointVelocities); + }; +}; +#endif