diff --git a/source/RobotAPI/interface/core/Trajectory.ice b/source/RobotAPI/interface/core/Trajectory.ice index daeb1ce6fca713dab8cc238f90a495aa9380d92d..3bcf4960af7e7571a7fd8199c7e48aa6ee175ac2 100644 --- a/source/RobotAPI/interface/core/Trajectory.ice +++ b/source/RobotAPI/interface/core/Trajectory.ice @@ -30,6 +30,15 @@ module armarx { sequence<DoubleSeqSeq> DoubleSeqSeqSeq; + struct LimitlessState + { + bool enabled; + double limitLo; + double limitHi; + }; + + sequence<LimitlessState> LimitlessStateSeq; + /** * [TrajectoryBase] defines a n-dimension trajectory with n deriviations. * @@ -47,6 +56,8 @@ module armarx */ ["protected"] DoubleSeqSeqSeq dataVec; ["protected"] Ice::DoubleSeq timestamps; + + ["protected"] LimitlessStateSeq limitless; }; diff --git a/source/RobotAPI/libraries/core/PIDController.cpp b/source/RobotAPI/libraries/core/PIDController.cpp index 106f8a723c75bc884a6efd8323cb4965cd325a3a..cea8fa2744f760265647b2d7f1ad18f5085733bb 100644 --- a/source/RobotAPI/libraries/core/PIDController.cpp +++ b/source/RobotAPI/libraries/core/PIDController.cpp @@ -25,11 +25,12 @@ #include "PIDController.h" #include <ArmarXCore/core/time/TimeUtil.h> #include <RobotAPI/libraries/core/math/MathUtils.h> +#include <RobotAPI/libraries/core/math/MathUtils.h> using namespace armarx; -PIDController::PIDController(float Kp, float Ki, float Kd, double maxControlValue, double maxDerivation) : +PIDController::PIDController(float Kp, float Ki, float Kd, double maxControlValue, double maxDerivation, bool limitless, double limitlessLimitHi) : Kp(Kp), Ki(Ki), Kd(Kd), @@ -41,7 +42,9 @@ PIDController::PIDController(float Kp, float Ki, float Kd, double maxControlValu controlValue(0), controlValueDerivation(0), maxControlValue(maxControlValue), - maxDerivation(maxDerivation) + maxDerivation(maxDerivation), + limitless(limitless), + limitlessLimitHi(limitlessLimitHi) { reset(); } @@ -95,7 +98,14 @@ void PIDController::update(double deltaSec, double measuredValue, double targetV processValue = measuredValue; target = targetValue; + double error = target - processValue; + //ARMARX_INFO << VAROUT(target) << ", " << VAROUT(processValue) << ", " << VAROUT(error); + if (limitless) + { + error = math::MathUtils::fmod(error, limitlessLimitHi - 2 * M_PI, limitlessLimitHi); + //ARMARX_INFO << "Limitless after mod:" << VAROUT(error); + } //double dt = (now - lastUpdateTime).toSecondsDouble(); // ARMARX_INFO << deactivateSpam() << VAROUT(dt); diff --git a/source/RobotAPI/libraries/core/PIDController.h b/source/RobotAPI/libraries/core/PIDController.h index cf7373d20fba53ef0da244d75b715f60fb9076a3..4e1f5528b4164f5800a585bb327861e74e2265b7 100644 --- a/source/RobotAPI/libraries/core/PIDController.h +++ b/source/RobotAPI/libraries/core/PIDController.h @@ -35,7 +35,13 @@ namespace armarx public Logging { public: - PIDController(float Kp, float Ki, float Kd, double maxControlValue = std::numeric_limits<double>::max(), double maxDerivation = std::numeric_limits<double>::max()); + PIDController(float Kp, + float Ki, + float Kd, + double maxControlValue = std::numeric_limits<double>::max(), + double maxDerivation = std::numeric_limits<double>::max(), + bool limitless = false, + double limitlessLimitHi = 2 * M_PI); void update(double deltaSec, double measuredValue, double targetValue); void update(double measuredValue, double targetValue); void update(double measuredValue); @@ -57,6 +63,8 @@ namespace armarx double maxControlValue; double maxDerivation; bool firstRun; + bool limitless; + double limitlessLimitHi; mutable RecursiveMutex mutex; }; typedef boost::shared_ptr<PIDController> PIDControllerPtr; diff --git a/source/RobotAPI/libraries/core/Trajectory.cpp b/source/RobotAPI/libraries/core/Trajectory.cpp index 33a0698f8c15a77469838339703caeae308a37c1..07530219cc7b65f415117e5cc66617ba1c4d6947 100644 --- a/source/RobotAPI/libraries/core/Trajectory.cpp +++ b/source/RobotAPI/libraries/core/Trajectory.cpp @@ -25,6 +25,7 @@ #include <ArmarXCore/core/logging/Logging.h> #include "VectorHelpers.h" #include <ArmarXCore/observers/AbstractObjectSerializer.h> +#include "math/MathUtils.h" namespace armarx { @@ -1265,8 +1266,45 @@ namespace armarx } double duration = tNext - tBefore; - double delta = next - before; + + double delta; + if (trajDimension < limitless.size() && limitless.at(trajDimension).enabled) + { + double range = limitless.at(trajDimension).limitHi - limitless.at(trajDimension).limitLo; + + double dist1 = next - before; + double dist2 = next - (before + range); + double dist3 = next - (before - range); + + if (fabs(dist1) <= fabs(dist2) && fabs(dist1) <= fabs(dist3)) + { + // no issue with bounds + //ARMARX_IMPORTANT << "LIMITLESS deriv: checking dim " << trajDimension << ", prev:" << before << ", next:" << next << ", range:" << range << ", dist1:" << dist1 << ", dist2:" << dist2 << ", dist3:" << dist3; + delta = dist1; + } + else if (fabs(dist2) <= fabs(dist3) && fabs(dist2) <= fabs(dist3)) + { + // go over hi bound + //ARMARX_IMPORTANT << "LIMITLESS deriv HIGH: checking dim " << trajDimension << ", prev:" << before << ", next:" << next << ", range:" << range << ", dist1:" << dist1 << ", dist2:" << dist2 << ", dist3:" << dist3; + delta = dist2; + } + else + { + // go over lo bound + //ARMARX_IMPORTANT << "LIMITLESS deriv LOW: checking dim " << trajDimension << ", prev:" << before << ", next:" << next << ", range:" << range << ", dist1:" << dist1 << ", dist2:" << dist2 << ", dist3:" << dist3; + delta = dist3; + } + + //ARMARX_IMPORTANT << "LIMITLESS deriv: checking dim " << trajDimension << ": delta is " << delta; + } + else + { + // no limitless joint + delta = next - before; + } + delta = delta / duration; + //ARMARX_IMPORTANT << "LIMITLESS deriv: checking dim " << trajDimension << ": delta/duration is " << delta; checkValue(delta); return delta; } @@ -1292,8 +1330,6 @@ namespace armarx } - - void Trajectory::reconstructFromDerivativeForDim(double valueAtFirstTimestamp, size_t trajDimension, size_t sourceDimOfSystemState, size_t targetDimOfSystemState) { const ordered_view& ordv = dataMap.get<TagOrdered>(); @@ -1438,10 +1474,43 @@ namespace armarx double weightPrev = fabs(t - itNext->timestamp) / distance; double weightNext = fabs(itPrev->timestamp - t) / distance; - return weightNext * next + weightPrev * previous; - + if (dimension < limitless.size() && limitless.at(dimension).enabled) + { + double result = 0; + double range = limitless.at(dimension).limitHi - limitless.at(dimension).limitLo; + double dist1 = next - previous; + double dist2 = next - (previous + range); + double dist3 = next - (previous - range); + //ARMARX_IMPORTANT << "LIMITLESS: checking dim " << dimension << ", prev:" << previous << ", next:" << next << ", range:" << range << ", dist1:" << dist1 << ", dist2:" << dist2 << ", dist3:" << dist3; + if (fabs(dist1) <= fabs(dist2) && fabs(dist1) <= fabs(dist3)) + { + // no issue with bounds + result = weightNext * next + weightPrev * previous; + } + else if (fabs(dist2) <= fabs(dist3) && fabs(dist2) <= fabs(dist3)) + { + // go over hi bound + result = weightNext * next + weightPrev * (previous + range); + result = math::MathUtils::fmod(result, limitless.at(dimension).limitLo, limitless.at(dimension).limitHi); + //ARMARX_IMPORTANT << "LIMITLESS - HIGH: checking dim " << dimension << ": high bounds, result: " << result << ", orig result would be " << weightNext* next + weightPrev* previous; + } + else + { + // go over lo bound + result = weightNext * next + weightPrev * (previous - range); + result = math::MathUtils::fmod(result, limitless.at(dimension).limitLo, limitless.at(dimension).limitHi); + //ARMARX_IMPORTANT << "LIMITLESS - LOW: checking dim " << dimension << ": low bounds, result: " << result << ", orig result would be " << weightNext* next + weightPrev* previous; + } + return result; + } + else + { + //ARMARX_IMPORTANT << "LIMITLESS: dim " << dimension << ": not limitless, limitless.size()=" << limitless.size(); + return weightNext * next + weightPrev * previous; + } } } + void Trajectory::gaussianFilter(double filterRadius) { const ordered_view& ordv = dataMap.get<TagOrdered>(); @@ -1538,6 +1607,8 @@ namespace armarx destination.addDimension(source.getDimensionData(dim), timestamps); } destination.setDimensionNames(source.getDimensionNames()); + + destination.setLimitless(source.getLimitless()); } void Trajectory::clear() @@ -1612,6 +1683,7 @@ namespace armarx normExampleTraj.addDimension(dimensionData, normTimestamps); } normExampleTraj.setDimensionNames(traj.getDimensionNames()); + normExampleTraj.setLimitless(traj.getLimitless()); return normExampleTraj; @@ -1849,4 +1921,15 @@ namespace armarx } + void Trajectory::setLimitless(const LimitlessStateSeq& limitlessStates) + { + limitless = limitlessStates; + } + + LimitlessStateSeq Trajectory::getLimitless() const + { + return limitless; + } + + } // namespace armarx diff --git a/source/RobotAPI/libraries/core/Trajectory.h b/source/RobotAPI/libraries/core/Trajectory.h index db38b1e6657b9717dd2f0f98bd418b9d5a02e234..f1b481febf2b8b62786115e3ce287b5d660e0125 100644 --- a/source/RobotAPI/libraries/core/Trajectory.h +++ b/source/RobotAPI/libraries/core/Trajectory.h @@ -424,6 +424,8 @@ namespace armarx dimensionNames = dimNames; } + void setLimitless(const LimitlessStateSeq& limitlessStates); + LimitlessStateSeq getLimitless() const; protected: void __addDimension(); diff --git a/source/RobotAPI/libraries/core/math/MathUtils.h b/source/RobotAPI/libraries/core/math/MathUtils.h index bef829c58f7f55ae16416e8524a434cce2c9d987..eae0128a8508b7963ea5820394cc9a13cbf71173 100644 --- a/source/RobotAPI/libraries/core/math/MathUtils.h +++ b/source/RobotAPI/libraries/core/math/MathUtils.h @@ -124,6 +124,28 @@ namespace armarx return max; } + static float fmod(float value, float boundLow, float boundHigh) + { + if (value < 0) + { + return std::fmod(value + boundLow, boundHigh - boundLow) - boundLow; + } + else + { + return std::fmod(value - boundLow, boundHigh - boundLow) + boundLow; + } + } + + static float angleMod2PI(float value) + { + return fmod(value, 0, 2 * M_PI); + } + + static float angleModPI(float value) + { + return angleMod2PI(value) - M_PI; + } + }; } }