Skip to content
Snippets Groups Projects
NJointKneeHipController.cpp 8.06 KiB
Newer Older
#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>
// #include <armar7/rt/units/njoint_controller/knee_hip_controller/aron_conversions.h>




namespace armarx

{
    const armarx::NJointControllerRegistration<NJointKneeHipController>
        registrationControllerNJointKneeHipController(
            "NJointKneeHipController");

    NJointKneeHipController::NJointKneeHipController(RobotUnit* robotUnit,
                                         const armarx::NJointControllerConfigPtr& config,
                                         const VirtualRobot::RobotPtr&)
    {
        ARMARX_RT_LOGF("Creating knee hip controller");

        ARMARX_CHECK_EXPRESSION(robotUnit);

        // config
        // ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
        // ARMARX_CHECK_EXPRESSION(cfg);

        // const arondto::Config configData = arondto::Config::FromAron(cfg->config);

        // robot
        ARMARX_RT_LOGF("Setting up nodes");
        {
            _rtRobot = useSynchronizedRtRobot();
            _rtRobot->setThreadsafe(false);
            ARMARX_CHECK_NOT_NULL(_rtRobot);

            // _rtKneeNode = _rtRobot->getRobotNode(configData.params.kneeJointName);
            // _rtHipNode = _rtRobot->getRobotNode(configData.params.hipJointName);
            // _rtHipBodyNode = _rtRobot->getRobotNode(configData.params.hipBodyName);
            const auto *kneeJointName = "Knee";
            const auto *hipJointName = "Hip";
            const auto *hipBodyName = "Hip_body";


            _rtKneeNode = _rtRobot->getRobotNode(kneeJointName);
            _rtHipNode = _rtRobot->getRobotNode(hipJointName);
            _rtHipBodyNode = _rtRobot->getRobotNode(hipBodyName);
            ARMARX_CHECK_NOT_NULL(_rtKneeNode);
            ARMARX_CHECK_NOT_NULL(_rtHipNode);
            ARMARX_CHECK_NOT_NULL(_rtHipBodyNode);

            // 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");
    }

    NJointKneeHipController::~NJointKneeHipController() = default;

    // void
    // KneeHipController::updateConfig(const ::armarx::aron::data::dto::DictPtr& dto,
    //                                 const Ice::Current& /*iceCurrent*/)
    // {
    //     // const auto updateConfigDto = arondto::Config::FromAron(dto);

    //     // Config config;
    //     // fromAron(updateConfigDto, config);

    //     // setControlStruct(config);
    // }

    void
    NJointKneeHipController::onInitNJointController()
    {
    }

    void
    NJointKneeHipController::onConnectNJointController()
    {
    }

    std::string
    NJointKneeHipController::getClassName(const Ice::Current&) const
    {
        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)
        auto& debugData = bufferRtToOnPublish_.getWriteBuffer();
        
        double kneeVelocity = velocitySensor->velocity;
        debugData.kneeVelocity = kneeVelocity;
        
        double kneeAngle = _rtKneeNode->getJointValue();
        debugData.kneeAngle = kneeAngle;
        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
    NJointKneeHipController::rtPreActivateController()
    {
    }

    void
    NJointKneeHipController::rtPostDeactivateController()
    {
    }

    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