3#include <boost/archive/text_iarchive.hpp>
4#include <boost/archive/text_oarchive.hpp>
8#include <VirtualRobot/Robot.h>
19#include <armarx/control/deprecated_njoint_mp_controller/joint_space/ControllerInterface.h>
21#include <dmp/representation/dmp/umidmp.h>
26 NJointControllerRegistration<NJointJSDMPController>
32 return "NJointJSDMPController";
36 const armarx::NJointControllerConfigPtr& config,
39 ARMARX_INFO <<
"creating joint space dmp controller ... ";
42 cfg = NJointJointSpaceDMPControllerConfigPtr::dynamicCast(config);
45 for (std::string jointName : cfg->jointNames)
49 targets.insert(std::make_pair(jointName, ct->
asA<ControlTarget1DoFActuatorVelocity>()));
50 positionSensors.insert(
51 std::make_pair(jointName, sv->
asA<SensorValue1DoFActuatorPosition>()));
52 velocitySensors.insert(
53 std::make_pair(jointName, sv->
asA<SensorValue1DoFActuatorVelocity>()));
55 if (cfg->jointNames.size() == 0)
60 <<
" baseMode: " << cfg->baseMode;
62 dmpPtr.reset(
new DMP::UMIDMP(cfg->kernelSize, 100, cfg->baseMode, 1));
63 timeDuration = cfg->timeDuration;
66 phaseDist0 = cfg->phaseDist0;
67 phaseDist1 = cfg->phaseDist1;
68 phaseKp = cfg->phaseKp;
69 dimNames = cfg->jointNames;
72 targetVels.resize(cfg->jointNames.size());
75 for (
size_t i = 0; i < cfg->jointNames.size(); ++i)
84 NJointJSDMPControllerSensorData initSensorData;
85 initSensorData.currentTime = 0;
86 initSensorData.deltaT = 0;
87 initSensorData.currentState.resize(cfg->jointNames.size());
88 controllerSensorData.reinitAllBuffers(initSensorData);
92 qpos.resize(dimNames.size());
93 qvel.resize(dimNames.size());
99 if (!started || finished)
101 for (
size_t i = 0; i < dimNames.size(); ++i)
108 currentState = controllerSensorData.getUpToDateReadBuffer().currentState;
109 double deltaT = controllerSensorData.getUpToDateReadBuffer().deltaT;
113 double phaseStop = 0;
114 double mpcFactor = 1;
116 std::vector<double> currentPosition;
118 currentPosition.resize(dimNames.size());
120 for (
size_t i = 0; i < currentState.size(); i++)
122 DMP::DMPState currentPos = currentState[i];
123 currentPosition[i] = currentPos.pos;
124 error += pow(currentPos.pos - targetState[i], 2);
127 if (cfg->isPhaseStop)
133 phaseDist = phaseDist1;
137 phaseDist = phaseDist0;
141 phaseStop = phaseL / (1 + exp(-phaseK * (error - phaseDist)));
142 mpcFactor = 1 - (phaseStop / phaseL);
146 isDisturbance =
true;
151 isDisturbance =
false;
155 canVal -= tau * deltaT * 1 / (1 + phaseStop);
156 double dmpDeltaT = deltaT / timeDuration;
158 currentDMPState = dmpPtr->calculateDirectlyVelocity(
159 currentDMPState, canVal / timeDuration, dmpDeltaT, targetState);
161 for (
size_t i = 0; i < currentDMPState.size(); ++i)
163 double vel0 = tau * currentDMPState[i].vel / timeDuration;
164 double vel1 = phaseKp * (targetState[i] - currentPosition[i]);
166 double vel = vel1 + vel0;
168 debugOutputData.getWriteBuffer().latestTargetVelocities[dimNames[i]] =
170 debugOutputData.getWriteBuffer().latestTargets[dimNames[i]] =
171 (
float)currentDMPState[i].pos;
174 debugOutputData.getWriteBuffer().currentCanVal = canVal;
175 debugOutputData.getWriteBuffer().mpcFactor = mpcFactor;
176 debugOutputData.commitWrite();
181 for (
size_t i = 0; i < dimNames.size(); ++i)
195 const IceUtil::Time& timeSinceLastIteration)
197 for (
size_t i = 0; i < dimNames.size(); i++)
199 const auto& jointName = dimNames.at(i);
200 DMP::DMPState currentPos;
201 currentPos.pos = (positionSensors.count(jointName) == 1)
202 ? positionSensors[jointName]->position
204 currentPos.vel = (velocitySensors.count(jointName) == 1)
205 ? velocitySensors[jointName]->velocity
207 qpos[i] = currentPos.pos;
208 qvel[i] = currentPos.vel;
209 controllerSensorData.getWriteBuffer().currentState[i] = currentPos;
211 controllerSensorData.getWriteBuffer().deltaT = timeSinceLastIteration.toSecondsDouble();
212 controllerSensorData.getWriteBuffer().currentTime +=
213 timeSinceLastIteration.toSecondsDouble();
214 controllerSensorData.commitWrite();
217 rt2UserData.getWriteBuffer().qpos = qpos;
218 rt2UserData.getWriteBuffer().qvel = qvel;
219 rt2UserData.commitWrite();
224 for (
size_t i = 0; i < dimNames.size(); ++i)
227 if (fabs(targetJointVels[i]) > cfg->maxJointVel)
229 targets[dimNames[i]]->velocity =
230 targetJointVels[i] < 0 ? -cfg->maxJointVel : cfg->maxJointVel;
234 targets[dimNames[i]]->velocity = targetJointVels[i];
242 DMP::Vec<DMP::SampledTrajectoryV2> trajs;
245 for (
size_t i = 0; i < fileNames.size(); ++i)
247 DMP::SampledTrajectoryV2 traj;
248 traj.readFromCSVFile(fileNames.at(i));
249 traj = DMP::SampledTrajectoryV2::normalizeTimestamps(traj, 0, 1);
250 trajs.push_back(traj);
254 ratios.push_back(1.0);
258 ratios.push_back(0.0);
261 dmpPtr->learnFromTrajectories(trajs);
262 dmpPtr->styleParas = dmpPtr->getStyleParasWithRatio(ratios);
270 while (!rt2UserData.updateReadBuffer())
276 targetState.resize(dimNames.size());
277 currentState.clear();
278 currentState.resize(dimNames.size());
279 currentDMPState.clear();
280 currentDMPState.resize(dimNames.size());
282 std::vector<double> goalVec = goals;
283 for (
size_t i = 0; i < dimNames.size(); i++)
285 DMP::DMPState currentPos;
286 currentPos.pos = rt2UserData.getReadBuffer().qpos[i];
287 currentPos.vel = rt2UserData.getReadBuffer().qvel[i];
289 currentState[i] = currentPos;
290 currentDMPState[i] = currentPos;
292 targetState.push_back(currentPos.pos);
294 if (
rtGetRobot()->getRobotNode(dimNames[i])->isLimitless())
296 double tjv = goalVec[i];
297 double cjv = currentPos.pos;
298 double diff = std::fmod(tjv - cjv, 2 *
M_PI);
299 if (fabs(diff) >
M_PI)
303 diff = -2 *
M_PI - diff;
307 diff = 2 *
M_PI - diff;
318 <<
" current state: qpos: " << currentPos.pos
319 <<
" orig target: " << goals[i] <<
" current goal: " << tjv;
323 dmpPtr->prepareExecution(goalVec, currentDMPState, 1, 1);
324 canVal = timeDuration;
326 isDisturbance =
false;
341 std::stringstream ss;
342 boost::archive::text_oarchive oa{ss};
350 std::stringstream ss;
352 boost::archive::text_iarchive ia{ss};
353 DMP::UMIDMP* newDmpPtr;
355 dmpPtr.reset(newDmpPtr);
356 return dmpPtr->defaultGoal;
363 dmpPtr->setViaPoint(u, viapoint);
369 dmpPtr->setWeights(weights);
375 DMP::DVec2d res = dmpPtr->getWeights();
377 for (
size_t i = 0; i < res.size(); ++i)
379 std::vector<double> cvec;
380 for (
size_t j = 0; j < res[i].size(); ++j)
382 cvec.push_back(res[i][j]);
384 resvec.push_back(cvec);
413 auto values = debugOutputData.getUpToDateReadBuffer().latestTargetVelocities;
414 for (
auto& pair : values)
416 datafields[pair.first] =
new Variant(pair.second);
419 values = debugOutputData.getUpToDateReadBuffer().latestTargets;
420 for (
auto& pair : values)
422 datafields[pair.first +
"_pos"] =
new Variant(pair.second);
425 datafields[
"canVal"] =
new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal);
426 datafields[
"mpcFactor"] =
new Variant(debugOutputData.getUpToDateReadBuffer().mpcFactor);
427 debugObs->setDebugChannel(
"latestDMPTargetVelocities", datafields);
435 runTask(
"NJointJSDMPController",
440 while (
getState() == eManagedIceObjectStarted)
446 c.waitForCycleDuration();
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 NJointJSDMPControllerControlData & rtGetControlStruct() const
MutexType controlDataMutex
std::lock_guard< std::recursive_mutex > LockGuardType
void writeControlStruct()
NJointJSDMPControllerControlData & getWriterControlStruct()
void reinitTripleBuffer(const NJointJSDMPControllerControlData &initial)
The SensorValueBase class.
The Variant class is described here: Variants.
Eigen::VectorXf targetJointVels
virtual void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
void onInitNJointController() override
void runDMP(const Ice::DoubleSeq &goals, double times, const Ice::Current &) override
void setMPWeights(const DoubleSeqSeq &weights, const Ice::Current &) override
void onDisconnectNJointController() override
void learnDMPFromFiles(const Ice::StringSeq &fileNames, const Ice::Current &) override
NJointJSDMPController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void setSpeed(double times, const Ice::Current &) override
std::vector< double > createDMPFromString(const std::string &dmpString, const Ice::Current &) override
void setViaPoints(Ice::Double u, double viapoint, const Ice::Current &) override
std::string getClassName(const Ice::Current &) const override
void rtPreActivateController() override
This function is called before the controller is activated.
#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_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
DoubleSeqSeq getMPWeights()
std::shared_ptr< class Robot > RobotPtr
NJointControllerRegistration< NJointJSDMPController > registrationControllerNJointJSDMPController("NJointJSDMPController")
::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