From 69b769ef1c6a349fdf608505c98681c6d310469f Mon Sep 17 00:00:00 2001
From: Markus Grotz <Markus Grotz markus.grotz@kit.edu>
Date: Wed, 31 Jul 2019 09:33:05 +0200
Subject: [PATCH] add NJointHolonomicPlatformGlobalPositionController

---
 .../components/units/RobotUnit/CMakeLists.txt |   2 +
 ...onomicPlatformGlobalPositionController.cpp | 151 ++++++++++++++++++
 ...olonomicPlatformGlobalPositionController.h | 122 ++++++++++++++
 .../RobotUnitModules/RobotUnitModuleUnits.cpp |  18 +++
 .../units/RobotUnit/Units/PlatformSubUnit.h   |   1 +
 5 files changed, 294 insertions(+)
 mode change 100644 => 100755 source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
 create mode 100755 source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.cpp
 create mode 100755 source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.h

diff --git a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
old mode 100644
new mode 100755
index 8b255aed2..60ce76b94
--- a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
+++ b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
@@ -43,6 +43,7 @@ set(LIB_FILES
     NJointControllers/NJointKinematicUnitPassThroughController.cpp
     NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.cpp
     NJointControllers/NJointHolonomicPlatformRelativePositionController.cpp
+    NJointControllers/NJointHolonomicPlatformGlobalPositionController.cpp
     NJointControllers/NJointTCPController.cpp
     NJointControllers/NJointCartesianVelocityController.cpp
     NJointControllers/NJointCartesianTorqueController.cpp
@@ -111,6 +112,7 @@ set(LIB_HEADERS
     NJointControllers/NJointKinematicUnitPassThroughController.h
     NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.h
     NJointControllers/NJointHolonomicPlatformRelativePositionController.h
+    NJointControllers/NJointHolonomicPlatformGlobalPositionController.h
     NJointControllers/NJointTCPController.h
     NJointControllers/NJointCartesianVelocityController.h
     NJointControllers/NJointCartesianTorqueController.h
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.cpp
new file mode 100755
index 000000000..222b7f42c
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.cpp
@@ -0,0 +1,151 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * 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    ArmarX
+ * @author     Markus Grotz (markus.grotz at kit dot edu)
+ * @date       2019
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#include "NJointHolonomicPlatformGlobalPositionController.h"
+
+namespace armarx
+{
+    NJointControllerRegistration<NJointHolonomicPlatformGlobalPositionController>
+    registrationNJointHolonomicPlatformGlobalPositionController("NJointHolonomicPlatformGlobalPositionController");
+
+
+    NJointHolonomicPlatformGlobalPositionController::NJointHolonomicPlatformGlobalPositionController(
+        const RobotUnitPtr&,
+        const NJointHolonomicPlatformGlobalPositionControllerConfigPtr& cfg,
+        const VirtualRobot::RobotPtr&) :
+        pid(cfg->p, cfg->i, cfg->d, cfg->maxVelocity, cfg->maxAcceleration)
+
+    {
+        const SensorValueBase* sv = useSensorValue(cfg->platformName);
+        this->sv = sv->asA<SensorValueHolonomicPlatform>();
+        target = useControlTarget(cfg->platformName, ControlModes::HolonomicPlatformVelocity)->asA<ControlTargetHolonomicPlatformVelocity>();
+        ARMARX_CHECK_EXPRESSION_W_HINT(target, "The actuator '" << cfg->platformName << "' has no control mode " << ControlModes::HolonomicPlatformVelocity);
+
+        pid.threadSafe = false;
+
+        oriCtrl.maxV = cfg->maxRotationVelocity;
+        oriCtrl.acceleration = cfg->maxRotationAcceleration;
+        oriCtrl.deceleration = cfg->maxRotationAcceleration;
+        oriCtrl.maxDt = 0.1;
+        oriCtrl.pid->Kp = cfg->p;
+        oriCtrl.positionPeriodLo = -M_PI;
+        oriCtrl.positionPeriodHi = M_PI;
+        pid.preallocate(2);
+
+    }
+
+    void NJointHolonomicPlatformGlobalPositionController::rtRun(const IceUtil::Time& currentTime, const IceUtil::Time& timeSinceLastIteration)
+    {
+        currentPosition << sv->relativePositionX, sv->relativePositionY;
+        currentOrientation = sv->relativePositionRotation;
+
+
+        if (rtGetControlStruct().newTargetSet)
+        {
+            pid.reset();
+            *const_cast<bool*>(&rtGetControlStruct().newTargetSet) = false;
+        }
+
+        if ((rtGetControlStruct().lastUpdate + IceUtil::Time::seconds(2)) < currentTime)
+        {
+
+            // ARMARX_RT_LOGF_WARNING  << deactivateSpam(0.5) << "Waiting for global pos";
+
+            target->velocityX = 0;
+            target->velocityY = 0;
+
+            target->velocityRotation = 0;
+
+            return;
+        }
+
+        float relativeOrientation = currentOrientation - rtGetControlStruct().startOrientation;
+        Eigen::Vector2f relativeCurrentPosition = currentPosition - rtGetControlStruct().startPosition;
+
+        Eigen::Vector2f updatedPosition = rtGetControlStruct().globalPosition + relativeCurrentPosition;
+        float updatedOrientation = rtGetControlStruct().globalOrientation + relativeOrientation;
+        updatedOrientation = std::atan2(std::sin(updatedOrientation), std::cos(updatedOrientation));
+
+        pid.update(timeSinceLastIteration.toSecondsDouble(), updatedPosition, rtGetControlStruct().target);
+
+        oriCtrl.dt = timeSinceLastIteration.toSecondsDouble();
+        oriCtrl.accuracy = rtGetControlStruct().rotationAccuracy;
+        oriCtrl.currentPosition = updatedOrientation;
+        oriCtrl.targetPosition =  getWriterControlStruct().targetOrientation;
+        oriCtrl.currentV = sv->velocityRotation;
+
+        Eigen::Vector2f localTargetVelocity = Eigen::Rotation2Df(-updatedOrientation) * Eigen::Vector2f(pid.getControlValue()[0], pid.getControlValue()[1]);
+        target->velocityX = localTargetVelocity(0);
+        target->velocityY = localTargetVelocity(1);
+        target->velocityRotation = oriCtrl.run();
+
+        Eigen::Vector2f posError = pid.target.head(2) - pid.processValue.head(2);
+        if (posError.norm() < rtGetControlStruct().translationAccuracy)
+        {
+            // target->velocityX = 0;
+            // target->velocityY = 0;
+        }
+
+        float orientationError = oriCtrl.currentPosition - oriCtrl.targetPosition;
+        orientationError = std::atan2(std::sin(orientationError), std::cos(orientationError));
+        if (std::fabs(orientationError) < rtGetControlStruct().rotationAccuracy)
+        {
+            //target->velocityRotation = 0;
+        }
+    }
+
+    void NJointHolonomicPlatformGlobalPositionController::rtPreActivateController()
+    {
+    }
+
+    void NJointHolonomicPlatformGlobalPositionController::setTarget(float x, float y, float yaw, float translationAccuracy, float rotationAccuracy)
+    {
+        // todo do we really need a recursive mutex?
+
+        std::lock_guard<std::recursive_mutex> lock(controlDataMutex);
+
+        getWriterControlStruct().target << x, y;
+        getWriterControlStruct().targetOrientation = std::atan2(std::sin(yaw), std::cos(yaw));
+        getWriterControlStruct().translationAccuracy = translationAccuracy;
+        getWriterControlStruct().rotationAccuracy = rotationAccuracy;
+        getWriterControlStruct().newTargetSet = true;
+        writeControlStruct();
+    }
+
+
+    void NJointHolonomicPlatformGlobalPositionController::setGlobalPos(float x, float y, float yaw, const IceUtil::Time& time = ::IceUtil::Time::now())
+    {
+        // ..todo:: lock :)
+
+        getWriterControlStruct().globalPosition << x, y;
+        getWriterControlStruct().globalOrientation = yaw;
+
+        getWriterControlStruct().startPosition = currentPosition;
+        getWriterControlStruct().startOrientation = currentOrientation;
+
+        getWriterControlStruct().lastUpdate = time;
+        writeControlStruct();
+    }
+
+} // namespace armarx
+
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.h
new file mode 100755
index 000000000..b151f3802
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformGlobalPositionController.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * 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    ArmarX
+ * @author     Markus Grotz (markus.grotz at kit dot edu)
+ * @date       2019
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#pragma once
+
+
+#include <atomic>
+
+#include <VirtualRobot/Robot.h>
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "NJointController.h"
+#include "../RobotUnit.h"
+#include "../SensorValues/SensorValueHolonomicPlatform.h"
+
+#include "../ControlTargets/ControlTarget1DoFActuator.h"
+#include <RobotAPI/libraries/core/PIDController.h>
+
+#include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTargetHolonomicPlatformVelocity.h>
+
+#include <RobotAPI/components/units/RobotUnit/BasicControllers.h>
+namespace armarx
+{
+
+    TYPEDEF_PTRS_HANDLE(NJointHolonomicPlatformGlobalPositionControllerConfig);
+    class NJointHolonomicPlatformGlobalPositionControllerConfig : virtual public NJointControllerConfig
+    {
+    public:
+        std::string platformName;
+        float p = 1.0f;
+        float i = 0.0f;
+        float d = 0.0f;
+        float maxVelocity = 300;
+        float maxAcceleration = 500;
+        float maxRotationVelocity = 0.5;
+        float maxRotationAcceleration = 0.5;
+    };
+
+    struct NJointHolonomicPlatformGlobalPositionControllerTarget
+    {
+        Eigen::Vector2f target; // x,y
+        float targetOrientation;
+        float translationAccuracy = 0.0f;
+        float rotationAccuracy = 0.0f;
+        bool newTargetSet = false;
+
+
+        Eigen::Vector2f startPosition;
+        float startOrientation;
+
+        Eigen::Vector2f globalPosition;
+        float globalOrientation;
+        IceUtil::Time lastUpdate = IceUtil::Time::seconds(0);
+    };
+
+    TYPEDEF_PTRS_HANDLE(NJointHolonomicPlatformGlobalPositionController);
+
+    /**
+     * @brief The NJointHolonomicPlatformGlobalPositionController class
+     * @ingroup Library-RobotUnit-NJointControllers
+     */
+    class NJointHolonomicPlatformGlobalPositionController:
+        virtual public NJointControllerWithTripleBuffer<NJointHolonomicPlatformGlobalPositionControllerTarget>
+    {
+    public:
+        using ConfigPtrT = NJointHolonomicPlatformGlobalPositionControllerConfigPtr;
+
+        inline NJointHolonomicPlatformGlobalPositionController(
+            const RobotUnitPtr& robotUnit,
+            const NJointHolonomicPlatformGlobalPositionControllerConfigPtr& cfg,
+            const VirtualRobot::RobotPtr&);
+
+        inline virtual void rtRun(const IceUtil::Time&, const IceUtil::Time& timeSinceLastIteration) override;
+        inline virtual void rtPreActivateController() override;
+
+        //ice interface
+        inline virtual std::string getClassName(const Ice::Current& = Ice::emptyCurrent) const override
+        {
+            return "NJointHolonomicPlatformGlobalPositionController";
+        }
+
+        void setTarget(float x, float y, float yaw, float translationAccuracy, float rotationAccuracy);
+
+        void setGlobalPos(float x, float y, float yaw, const IceUtil::Time&);
+
+
+    protected:
+        const SensorValueHolonomicPlatform* sv;
+        MultiDimPIDController pid;
+
+        PositionThroughVelocityControllerWithAccelerationBoundsAndPeriodicPosition oriCtrl;
+        ControlTargetHolonomicPlatformVelocity* target;
+
+
+        Eigen::Vector2f currentPosition;
+        float currentOrientation;
+
+    };
+} // namespace armarx
+
+
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
index 59a461de6..27c760de9 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
@@ -354,6 +354,24 @@ namespace armarx
             unit->platformSensorIndex = _module<Devices>().getSensorDevices().index(_module<RobotData>().getRobotPlatformName());
             //add
             addUnit(std::move(unit));
+
+
+            NJointHolonomicPlatformGlobalPositionControllerConfigPtr configGlobalPositionCtrlCfg = new NJointHolonomicPlatformGlobalPositionControllerConfig;
+            configGlobalPositionCtrlCfg->platformName = _module<RobotData>().getRobotPlatformName();
+            auto ctrlGlobalPosition = NJointHolonomicPlatformGlobalPositionControllerPtr::dynamicCast(
+                                          _module<ControllerManagement>().createNJointController(
+                                              "NJointHolonomicPlatformGlobalPositionController",
+                                              getName() + "_" + configName + "_GlobalPositionContoller",
+                                              configGlobalPositionCtrlCfg, false, true
+                                          )
+                                      );
+            ARMARX_CHECK_EXPRESSION(ctrlGlobalPosition);
+            unit->pt = ctrl;
+            unit->globalPosCtrl = ctrlGlobalPosition;
+
+            unit->platformSensorIndex = _module<Devices>().getSensorDevices().index(_module<RobotData>().getRobotPlatformName());
+            //add
+            addUnit(std::move(unit));
         }
 
         void Units::initializeForceTorqueUnit()
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/PlatformSubUnit.h b/source/RobotAPI/components/units/RobotUnit/Units/PlatformSubUnit.h
index bac5190ed..6184af471 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/PlatformSubUnit.h
+++ b/source/RobotAPI/components/units/RobotUnit/Units/PlatformSubUnit.h
@@ -66,6 +66,7 @@ namespace armarx
 
         NJointHolonomicPlatformUnitVelocityPassThroughControllerPtr pt;
         NJointHolonomicPlatformRelativePositionControllerPtr relativePosCtrl;
+        NJointHolonomicPlatformGlobalPositionControllerPtr globalPosCtrl;
         std::size_t platformSensorIndex;
     protected:
         Eigen::Matrix4f getRelativePose() const;
-- 
GitLab