From 27f4dbbeb845a09331c52242d6be588d4fe20dbc Mon Sep 17 00:00:00 2001 From: Frederik Koch <ulxvc@student.kit.edu> Date: Mon, 20 May 2024 18:59:49 +0200 Subject: [PATCH] KneeHip balance controller now works --- .../NJointKneeHipController.cpp | 146 ++++++++++++++---- .../NJointKneeHipController.h | 46 ++++-- 2 files changed, 146 insertions(+), 46 deletions(-) diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.cpp index faefcca81..1fe823ca4 100644 --- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.cpp +++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.cpp @@ -1,9 +1,15 @@ #include "NJointKneeHipController.h" +#include <algorithm> +#include <cmath> #include <SimoxUtility/math/distance/angle_between.h> #include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/interface/observers/VariantBase.h> +#include "RobotAPI/components/units/RobotUnit/ControlModes.h" +#include "RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h" +#include "RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h" + // #include <armar7/rt/units/njoint_controller/common/controller_types.h> // #include <armar7/rt/units/njoint_controller/knee_hip_controller/aron/ControllerConfig.aron.generated.h> @@ -28,8 +34,8 @@ namespace armarx ARMARX_CHECK_EXPRESSION(robotUnit); // config - ConfigPtrT cfg = ConfigPtrT::dynamicCast(config); - ARMARX_CHECK_EXPRESSION(cfg); + // ConfigPtrT cfg = ConfigPtrT::dynamicCast(config); + // ARMARX_CHECK_EXPRESSION(cfg); // const arondto::Config configData = arondto::Config::FromAron(cfg->config); @@ -55,13 +61,19 @@ namespace armarx ARMARX_CHECK_NOT_NULL(_rtHipNode); ARMARX_CHECK_NOT_NULL(_rtHipBodyNode); - _rtKneeCtrlTarget = useControlTarget<armarx::ControlTarget1DoFActuatorPosition>( - kneeJointName, armarx::ControlModes::Position1DoF); - ARMARX_CHECK_NOT_NULL(_rtKneeCtrlTarget); - _rtHipCtrlTarget = useControlTarget<armarx::ControlTarget1DoFActuatorPosition>( - hipJointName, armarx::ControlModes::Position1DoF); + // auto kneeBase = useControlTarget(kneeJointName, armarx::ControlModes::Position1DoF); + // _rtKneeCtrlTarget = kneeBase->asA<ControlTarget1DoFActuatorPosition>(); + // ARMARX_CHECK_NOT_NULL(_rtKneeCtrlTarget); + + // _rtHipCtrlTarget = useControlTarget<armarx::ControlTarget1DoFActuatorPosition>( + // hipJointName, armarx::ControlModes::Position1DoF); + auto hipBase = useControlTarget(hipJointName, armarx::ControlModes::Velocity1DoF); + _rtHipCtrlTarget = hipBase->asA<ControlTarget1DoFActuatorVelocity>(); ARMARX_CHECK_NOT_NULL(_rtHipCtrlTarget); } + const SensorValueBase* sv = useSensorValue(_rtKneeNode->getName()); + velocitySensor = sv->asA<SensorValue1DoFActuatorVelocity>(); + // positionSensor = sv->asA<SensorValue1DoFActuatorPosition>(); ARMARX_RT_LOGF("Nodes set up successfully"); } @@ -93,42 +105,88 @@ namespace armarx std::string NJointKneeHipController::getClassName(const Ice::Current&) const { - return "KneeHipController"; + return "NJointKneeHipController"; + } + + double + NJointKneeHipController::calculate_dAnkle_dKnee(double kneeAngle, double shank, double p1, double p2, double p3) + { + constexpr auto squared = [](const double t) { return t * t; }; + const double k1 = shank / p1; + const double k2 = shank / p3; + const double k3 = (squared(shank) + squared(p1) + squared(p3) - squared(p2)) / (2 * p1 * p3); + const double theta = kneeAngle; + + double T_fkt = sin(theta) * (((squared(k1)+k1+1)*k2-k1*k3)*cos(theta)-squared(k3)+(k1-1)*k2*k3+k1*squared(k2)+k1+1) + +((k3+k2)*cos(theta)+k1+1)*sqrt(-squared(k1)*squared(cos(theta))-(2*k1*k3-2*k2)*cos(theta)-squared(k3)+squared(k2)+1); + + + double B_fkt = sqrt(-squared(k1)*squared(cos(theta))-(2*k1*k3-2*k2)*cos(theta)-squared(k3)+squared(k2)+1) + * (sin(theta) * sqrt(-squared(k1)*squared(cos(theta))-(2*k1*k3-2*k2)*cos(theta)-squared(k3)+squared(k2)+1) + + k1*squared(cos(theta))+(k3+(k1+2)*k2)*cos(theta)+k2*k3+squared(k2)+1); + + + double dAnkle_dKnee = T_fkt / B_fkt; + + return dAnkle_dKnee; } + + // double NJointKneeHipController::calculate_psi(double kneeAngle, double shank, double p1, double p2, double p3) + // { + // constexpr auto squared = [](const double t) { return t * t; }; + // const double k1 = shank / p1; + // const double k2 = shank / p3; + // const double k3 = (squared(shank) + squared(p1) + squared(p3) - squared(p2)) / (2 * p1 * p3); + // const double theta = kneeAngle; + + // /* Solution of Freudenstein Equation*/ + // double psi = 2 * atan((cos(theta) + sqrt(cos(theta) * cos(theta) - + // 4 * (k1 * cos(theta) + cos(theta) + k2 + k3) * + // (k1 * cos(theta) - cos(theta) - k2 + k3))) / + // (k1 * cos(theta) + cos(theta) + k2 + k3)); + + // return psi; + // } + + void NJointKneeHipController::rtRun(const IceUtil::Time& /*sensorValuesTimestamp*/, - const IceUtil::Time& /*timeSinceLastIteration*/) + const IceUtil::Time& timeSinceLastIteration) { - const float currentHipJointValue = _rtHipNode->getJointValue(); - const auto hipRotation = - _rtHipBodyNode->getOrientationInRootFrame() * Eigen::Vector3f::UnitY(); - // angle between robot root and hip body in the yz-plane - // leaning forwards < 90° = upright < leaning backwards - const float hipAngle = simox::math::angle_between_vec3f_vec3f( - Eigen::Vector3f::UnitY(), hipRotation, Eigen::Vector3f::UnitX()); + auto& debugData = bufferRtToOnPublish_.getWriteBuffer(); + - // hip joint has positive angles leaning forwards (inverse to hipAngle) - float targetHipAngle = - currentHipJointValue + hipAngle - M_PI_2 + rtGetControlStruct().bowAngle; - float targetKneeAngle = rtGetControlStruct().kneeAngle; + double kneeVelocity = velocitySensor->velocity; + debugData.kneeVelocity = kneeVelocity; + + double kneeAngle = _rtKneeNode->getJointValue(); + debugData.kneeAngle = kneeAngle; - // check reachability - const bool targetReachable = _rtKneeNode->checkJointLimits(targetKneeAngle) && - _rtHipNode->checkJointLimits(targetHipAngle); - if (not targetReachable) - { - // limit joint ranges to avoid damage - targetKneeAngle = std::clamp( - targetKneeAngle, _rtKneeNode->getJointLimitLow(), _rtKneeNode->getJointLimitHigh()); - targetHipAngle = std::clamp( - targetHipAngle, _rtHipNode->getJointLimitLow(), _rtHipNode->getJointLimitHigh()); - } - _rtKneeCtrlTarget->position = targetKneeAngle; - _rtHipCtrlTarget->position = targetHipAngle; + double deltaKnee = kneeVelocity; + double dHip_dKnee = 1 - calculate_dAnkle_dKnee(kneeAngle, 280, 84.372, 269.964, 45); + + double deltaHip = dHip_dKnee * deltaKnee; + double hipVelocity = deltaHip; + debugData.hipVelocity = hipVelocity; + + std::clamp(hipVelocity, -0.5, 0.5); + _rtHipCtrlTarget->velocity = hipVelocity; + + + + /* Position approach */ + + // double theta = _rtKneeNode->getJointValue(); + // double psi = calculate_psi(theta, 280, 84.372, 269.964, 45); + // double target = theta - psi + M_PI/5; + + // _rtHipCtrlTarget->position = target; + + bufferRtToOnPublish_.commitWrite(); } void @@ -141,5 +199,27 @@ namespace armarx { } + void + NJointKneeHipController::onPublish(const SensorAndControl&, + const DebugDrawerInterfacePrx&, + const DebugObserverInterfacePrx& debugObservers) + { + + StringVariantBaseMap datafields; + + const auto& debugData = bufferRtToOnPublish_.getUpToDateReadBuffer(); + + datafields["localTimestamp"] = new Variant(debugData.localTimestamp); + + datafields["kneeAngle"] = new Variant(debugData.kneeAngle); + datafields["kneeVelocity"] = new Variant(debugData.kneeVelocity); + datafields["hipAngle"] = new Variant(debugData.hipAngle); + datafields["hipVelocity"] = new Variant(debugData.hipVelocity); + + debugObservers->setDebugChannel("NJointKneeHipController", + datafields); + + } + } // namespace armarx diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.h index 94fc676f8..270d36a68 100644 --- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.h +++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKneeHipController.h @@ -21,6 +21,8 @@ */ #pragma once +#include <ArmarXCore/interface/core/BasicTypes.h> +#include "RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h" #include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h> #include <RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h> #include <RobotAPI/components/units/RobotUnit/RobotUnit.h> @@ -41,23 +43,17 @@ namespace armarx float bowAngle; }; - TYPEDEF_PTRS_HANDLE(NJointKneeHipControllerConfig); - - class NJointKneeHipControllerConfig : virtual public armarx::NJointControllerConfig - { - public: - std::string deviceName1; - std::string deviceName; - std::string controlMode; - }; + // TYPEDEF_PTRS_HANDLE(NJointKneeHipControllerConfig); + TYPEDEF_PTRS_HANDLE(NJointKneeHipController); class NJointKneeHipController : virtual public armarx::NJointControllerWithTripleBuffer<Config> { public: - using ConfigPtrT = NJointKneeHipControllerConfigPtr; + // using ConfigPtrT = NJointKneeHipControllerPtr; + using ConfigPtrT = NJointControllerConfigPtr; NJointKneeHipController(RobotUnit* robotUnit, const armarx::NJointControllerConfigPtr& config, @@ -67,7 +63,10 @@ namespace armarx // void updateConfig(const ::armarx::aron::data::dto::DictPtr& dto, // const Ice::Current& iceCurrent = Ice::emptyCurrent) ; - + void onPublish(const SensorAndControl&, + const DebugDrawerInterfacePrx&, + const DebugObserverInterfacePrx& debugObserver) override; + protected: // // NJointControllerInterface interface @@ -85,6 +84,8 @@ namespace armarx void rtPreActivateController() override; void rtPostDeactivateController() override; + + // ---------------- private: @@ -93,9 +94,28 @@ namespace armarx VirtualRobot::RobotNodePtr _rtKneeNode; VirtualRobot::RobotNodePtr _rtHipNode; VirtualRobot::RobotNodePtr _rtHipBodyNode; + const SensorValue1DoFActuatorVelocity* velocitySensor; + // const SensorValue1DoFActuatorPosition* positionSensor; + static double calculate_dAnkle_dKnee(double kneeAngle, double shank, double p1, double p2, double p3); + static double calculate_psi(double kneeAngle, double shank, double p1, double p2, double p3); + + // armarx::ControlTarget1DoFActuatorPosition* _rtKneeCtrlTarget; + armarx::ControlTarget1DoFActuatorVelocity* _rtHipCtrlTarget; + + struct DebugData + { + std::int64_t localTimestamp; + + double kneeAngle; + double kneeVelocity; + double hipAngle; + double hipVelocity; + + + }; + + TripleBuffer<DebugData> bufferRtToOnPublish_; - armarx::ControlTarget1DoFActuatorPosition* _rtKneeCtrlTarget; - armarx::ControlTarget1DoFActuatorPosition* _rtHipCtrlTarget; }; } // namespace armarx -- GitLab