예제 #1
0
void Walker::flattenFoot( Hubo_Control &hubo, zmp_traj_element_t &elem,
			nudge_state_t &state, balance_gains_t &gains, double dt )
{
     
    state.ankle_roll_compliance[LEFT] -= gains.decay_gain[LEFT]*state.ankle_roll_compliance[LEFT];
    state.ankle_roll_compliance[RIGHT] -= gains.decay_gain[RIGHT]*state.ankle_roll_compliance[RIGHT];

    state.ankle_pitch_compliance[LEFT] -= gains.decay_gain[LEFT]*state.ankle_pitch_compliance[LEFT];
    state.ankle_pitch_compliance[RIGHT] -= gains.decay_gain[RIGHT]*state.ankle_pitch_compliance[RIGHT];

    if( gains.force_min_threshold[RIGHT] < hubo.getRightFootFz() 
     && hubo.getRightFootFz() < gains.force_max_threshold[RIGHT] )
    {
        state.ankle_roll_compliance[RIGHT] += dt*gains.flattening_gain[RIGHT]
                                                *( hubo.getRightFootMx() );
        state.ankle_pitch_compliance[RIGHT] += dt*gains.flattening_gain[RIGHT]
                                                 *( hubo.getRightFootMy() );
    }

    if( gains.force_min_threshold[LEFT] < hubo.getLeftFootFz()
     && hubo.getLeftFootFz() < gains.force_max_threshold[LEFT] )
    {
        state.ankle_roll_compliance[LEFT] += dt*gains.flattening_gain[LEFT]
                                               *( hubo.getLeftFootMx() );
        state.ankle_pitch_compliance[LEFT] += dt*gains.flattening_gain[LEFT]
                                                *( hubo.getLeftFootMy() );
    }


    elem.angles[RAR] += state.ankle_roll_compliance[RIGHT];
    elem.angles[RAP] += state.ankle_pitch_compliance[RIGHT];
    elem.angles[LAR] += state.ankle_roll_compliance[LEFT];
    elem.angles[LAP] += state.ankle_pitch_compliance[LEFT];

}
void printFTSensorValues(Hubo_Control &hubo){
	printf("Left Foot fz is %f	 ", hubo.getLeftFootFz());	
	printf("Right Foot fz is %f	 ", hubo.getRightFootFz());	
	printf("Left Hand fz is %f 	", hubo.getLeftHandFz());	
	printf("RightHand fz is %f\n", hubo.getRightHandFz());	
}
예제 #3
0
void Walker::nudgeHips( Hubo_Control &hubo, zmp_traj_element_t &elem,
            nudge_state_t &state, balance_gains_t &gains, double dt )
{
    bool debug = false;
    double kP, kD;  //!< Proportional and derivative gains
    int side;    //!< variable for stance leg
    // Figure out if we're in single or double support stance and which leg
    switch(elem.stance)
    {
        case SINGLE_LEFT:
            side = LEFT;
            kP = gains.single_support_hip_nudge_kp;
            kD = gains.single_support_hip_nudge_kd;
            break;
        case SINGLE_RIGHT:
            side = RIGHT;
            kP = gains.single_support_hip_nudge_kp;
            kD = gains.single_support_hip_nudge_kd;
            break;
        case DOUBLE_LEFT:
        case DOUBLE_RIGHT:
            side = 100;
            kP = gains.double_support_hip_nudge_kp;
            kD = gains.double_support_hip_nudge_kd;
            break;
        default:
            return;
    }

    // Store leg joint angels for current trajectory timestep
    std::vector<Vector6d, Eigen::aligned_allocator<Vector6d> > qPrev(2);
    qPrev[LEFT](HY) = elem.angles[LHY],
    qPrev[LEFT](HR) = elem.angles[LHR],
    qPrev[LEFT](HP) = elem.angles[LHP],
    qPrev[LEFT](KN) = elem.angles[LKN],
    qPrev[LEFT](AP) = elem.angles[LAP],
    qPrev[LEFT](AR) = elem.angles[LAR];

    qPrev[RIGHT](HY) = elem.angles[RHY],
    qPrev[RIGHT](HR) = elem.angles[RHR],
    qPrev[RIGHT](HP) = elem.angles[RHP],
    qPrev[RIGHT](KN) = elem.angles[RKN],
    qPrev[RIGHT](AP) = elem.angles[RAP],
    qPrev[RIGHT](AR) = elem.angles[RAR];

    // Skew matrix for torque reaction logic
    Eigen::Matrix3d skew; 
    skew << 0, 1, 0,
           -1, 0, 0,
            0, 0, 0;

    // Proportional gain matrix for ankle roll and pitch
    Eigen::Matrix3d shiftGainsKp;
    shiftGainsKp << kP,  0, 0,
                     0, kP, 0,
                     0,  0, 0;

    // Derivative gain matrix for ankle roll and pitch
    Eigen::Matrix3d shiftGainsKd;
    shiftGainsKd << kD,  0, 0,
                     0, kD, 0,
                     0,  0, 0;

    // Get rotation matrix for each hip yaw
    std::vector< Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d> > yawRot(2);
    yawRot[LEFT] = Eigen::AngleAxisd(hubo.getJointAngle(LHY), Eigen::Vector3d::UnitZ()).toRotationMatrix();
    yawRot[RIGHT]= Eigen::AngleAxisd(hubo.getJointAngle(RHY), Eigen::Vector3d::UnitZ()).toRotationMatrix();

    // TF for body to each foot
    std::vector< Eigen::Isometry3d, Eigen::aligned_allocator<Eigen::Isometry3d> > footTF(2);
    // New joint angles for both legs
    std::vector< Vector6d, Eigen::aligned_allocator<Vector6d> > qNew(2);
    // Ankle torque error XYZ (ie. Roll/Pitch/Yaw), but just setting Z to zero.
    Vector3d torqueErr[2];

    // Determine how much we need to nudge to hips over to account for
    // error in ankle torques about the x- and y- axes.
    // If Roll torque is positive (ie. leaning left) we want hips to go right (ie. negative y-direction)
    // If Pitch torque is positive (ie. leaning back) we want hips to go forward (ie. positive x-direction)
    // Get TFs for feet
    hubo.huboLegFK( footTF[LEFT], qPrev[LEFT], LEFT ); 
    hubo.huboLegFK( footTF[RIGHT], qPrev[RIGHT], RIGHT );

    std::cout << "foot is supposedly at " << footTF[LEFT].translation().transpose() << "\n";

    // Averaged torque error in ankles (roll and pitch) (yaw is always zero)
    //FIXME The version below is has elem.torques negative b/c hubomz computes reaction torque at ankle
    // instead of torque at F/T sensor
    torqueErr[LEFT](0) = (-elem.torque[LEFT][0] - hubo.getLeftFootMx());
    torqueErr[LEFT](1) = (-elem.torque[LEFT][1] - hubo.getLeftFootMy());
    torqueErr[LEFT](2) = 0;
    
    torqueErr[RIGHT](0) = (-elem.torque[RIGHT][0] - hubo.getRightFootMx());
    torqueErr[RIGHT](1) = (-elem.torque[RIGHT][1] - hubo.getRightFootMy());
    torqueErr[RIGHT](2) = 0;

    // Feet position errors (x,y)
    Vector3d instantaneousFeetOffset;

    // Check if we're on the ground, if not set instantaneous feet offset
    // to zero so integrated feet offset doesn't change, but we still apply it.
    const double forceThreshold = 20; // Newtons
    if(hubo.getLeftFootFz() + hubo.getRightFootFz() > forceThreshold)
    {
        std::cout << "Fzs = " << hubo.getLeftFootFz() << ", " << hubo.getRightFootFz() << "\n";
        if (side != LEFT && side != RIGHT)
        {
            instantaneousFeetOffset = (dt*shiftGainsKp * (yawRot[LEFT]*skew*torqueErr[LEFT] + yawRot[RIGHT]*skew*torqueErr[RIGHT])/2)
                                      - (shiftGainsKd * (yawRot[LEFT]*skew*(torqueErr[LEFT] - state.prevTorqueErr[LEFT])
                                         + yawRot[RIGHT]*skew*(torqueErr[RIGHT] - state.prevTorqueErr[RIGHT]))/2);
        }
        else
        {
            instantaneousFeetOffset = (dt*shiftGainsKp * yawRot[side]*skew*torqueErr[side])
                                      - (shiftGainsKd * yawRot[side]*skew*(torqueErr[side] - state.prevTorqueErr[side]));
        }
    }
    else
        instantaneousFeetOffset.setZero();

    // Decay the integratedFeetOffset
    state.integratedFeetOffset -= gains.decay_gain[LEFT]*state.integratedFeetOffset;

    // Add the instantaneous feet offset to the integrator
    state.integratedFeetOffset += instantaneousFeetOffset;

    const double integratedFeetOffsetTol = 0.06;
    double n = state.integratedFeetOffset.norm();
    if (n > integratedFeetOffsetTol) {
      state.integratedFeetOffset *= integratedFeetOffsetTol/n;
    }

    // Pretranslate feet TF by integrated feet error translation vector
    footTF[LEFT].pretranslate(state.integratedFeetOffset);
    footTF[RIGHT].pretranslate(state.integratedFeetOffset);
    // Run IK on the adjusted feet TF to get new joint angles
    bool ok = true;
    ok = hubo.huboLegIK(qNew[LEFT], footTF[LEFT], qPrev[LEFT], LEFT);
    if(ok)
        ok = hubo.huboLegIK(qNew[RIGHT], footTF[RIGHT], qPrev[RIGHT], RIGHT);
    // TODO: FIXME: MZ doesn't like the above code, he will explain

    hubo.huboLegFK( footTF[LEFT], qNew[LEFT], LEFT ); 
    std::cout << "now foot is supposedly at " << footTF[LEFT].translation().transpose() << "\n";

    if(debug)
    {
        std::cout //<< " K: " << kP
                  //<< " TdL: " << -elem.torque[LEFT][0] << ", " << -elem.torque[LEFT][1]
                  //<< " TdR: " << -elem.torque[RIGHT][0] << ", " << -elem.torque[RIGHT][1]
                  //<< " MyLR: " << hubo.getLeftFootMy() << ", " << hubo.getRightFootMy()
                  //<< " MxLR: " << hubo.getLeftFootMx() << ", " << hubo.getRightFootMx()
                  //<< " Te: " << torqueErr.transpose()
                  //<< " Fte: " << instantaneousFeetOffset.transpose()
                  //<< " qDfL: " << (qNew[LEFT] - qPrev[LEFT]).transpose()
                  << " FeetE: " << state.integratedFeetOffset.transpose()
                  << "\tqDfR: " << qNew[RIGHT].transpose()
                  << "\n";
    }

    //ok = false;

    // Set leg joint angles for current timestep of trajectory
    if(ok)
    {
        elem.angles[LHY] = qNew[LEFT](HY);
        elem.angles[LHR] = qNew[LEFT](HR);
        elem.angles[LHP] = qNew[LEFT](HP);
        elem.angles[LKN] = qNew[LEFT](KN);
        elem.angles[LAP] = qNew[LEFT](AP);
        elem.angles[LAR] = qNew[LEFT](AR);

        elem.angles[RHY] = qNew[RIGHT](HY);
        elem.angles[RHR] = qNew[RIGHT](HR);
        elem.angles[RHP] = qNew[RIGHT](HP);
        elem.angles[RKN] = qNew[RIGHT](KN);
        elem.angles[RAP] = qNew[RIGHT](AP);
        elem.angles[RAR] = qNew[RIGHT](AR);
    }
    else
        std::cout << "IK Invalid\n";

    // Save current force torque readings for next iteration
    for(int i=0; i<2; i++)
        state.prevTorqueErr[i] = torqueErr[i];
}
예제 #4
0
void Walker::complyKnee( Hubo_Control &hubo, zmp_traj_element_t &elem,
        nudge_state_t &state, balance_gains_t &gains, double dt )
{
    counter++;
    //-------------------------
    //      STANCE TYPE
    //-------------------------
    // Figure out if we're in single or double support stance and which leg
    int side;    //!< variable for stance leg
    if((unsigned char*)0x8 == elem.supporting)
        side = LEFT;
    else if((unsigned char*)"0100" == elem.supporting)
        side = RIGHT;
    else
        side = 100;

    //-------------------------
    //          GAINS
    //-------------------------
    Eigen::Vector3d spring_gain, damping_gain;
    spring_gain.setZero(); damping_gain.setZero();

    spring_gain.z() = gains.spring_gain[LEFT];
    damping_gain.z() = gains.damping_gain[LEFT];

    //-------------------------
    //    COPY JOINT ANGLES
    //-------------------------
    // Store leg joint angels for current trajectory timestep
    Vector6d qPrev[2];
    qPrev[LEFT](HY) = elem.angles[LHY],
    qPrev[LEFT](HR) = elem.angles[LHR],
    qPrev[LEFT](HP) = elem.angles[LHP],
    qPrev[LEFT](KN) = elem.angles[LKN],
    qPrev[LEFT](AP) = elem.angles[LAP],
    qPrev[LEFT](AR) = elem.angles[LAR];

    qPrev[RIGHT](HY) = elem.angles[RHY],
    qPrev[RIGHT](HR) = elem.angles[RHR],
    qPrev[RIGHT](HP) = elem.angles[RHP],
    qPrev[RIGHT](KN) = elem.angles[RKN],
    qPrev[RIGHT](AP) = elem.angles[RAP],
    qPrev[RIGHT](AR) = elem.angles[RAR];


    //-------------------------
    //        HIP YAWS
    //-------------------------
    // Get rotation matrix for each hip yaw
    Eigen::Matrix3d yawRot[2];
    yawRot[LEFT] = Eigen::AngleAxisd(hubo.getJointAngle(LHY), Eigen::Vector3d::UnitZ()).toRotationMatrix();
    yawRot[RIGHT]= Eigen::AngleAxisd(hubo.getJointAngle(RHY), Eigen::Vector3d::UnitZ()).toRotationMatrix();

    //-------------------------
    //        FOOT TFs
    //-------------------------
    // Determine how much we need to nudge to hips over to account for
    // error in ankle torques about the x- and y- axes.
    // If Roll torque is positive (ie. leaning left) we want hips to go right (ie. negative y-direction)
    // If Pitch torque is positive (ie. leaning back) we want hips to go forward (ie. positive x-direction)
    // Get TFs for feet
    Eigen::Isometry3d footTF[2];
    hubo.huboLegFK( footTF[LEFT], qPrev[LEFT], LEFT ); 
    hubo.huboLegFK( footTF[RIGHT], qPrev[RIGHT], RIGHT );

    if(counter > 40)
        std::cout << " now " << footTF[LEFT](2,3);

    //-------------------------
    //   FORCE/TORQUE ERROR
    //-------------------------
    // Averaged torque error in ankles (roll and pitch) (yaw is always zero)
    //FIXME The version below is has elem.torques negative b/c hubomz computes reaction torque at ankle
    // instead of torque at F/T sensor
    Eigen::Vector3d forceTorqueErr[2];

    forceTorqueErr[LEFT](0) = (-elem.torque[LEFT][0] - hubo.getLeftFootMx());
    forceTorqueErr[LEFT](1) = (-elem.torque[LEFT][1] - hubo.getLeftFootMy());
    forceTorqueErr[LEFT](2) = (-elem.forces[LEFT][2] - hubo.getLeftFootFz()); //FIXME should be positive
    
    forceTorqueErr[RIGHT](0) = (-elem.torque[RIGHT][0] - hubo.getRightFootMx());
    forceTorqueErr[RIGHT](1) = (-elem.torque[RIGHT][1] - hubo.getRightFootMy());
    forceTorqueErr[RIGHT](2) = (-elem.forces[RIGHT][2] - hubo.getRightFootFz()); //FIXME should be positive

    // Skew matrix for torque reaction logic
    Eigen::Matrix3d skew; 
    skew << 0, 1, 0,
           -1, 0, 0,
            0, 0, 1; //FIXME should be negative
    skew(0,1) = 0;
    skew(1,0) = 0;
    //------------------------
    //  IMPEDANCE CONTROLLER
    //------------------------
    // Check if we're on the ground, if not set instantaneous feet offset
    // to zero so integrated feet offset doesn't change, but we still apply it.
    const double forceThreshold = 0;//20; // Newtons
    if(hubo.getLeftFootFz() + hubo.getRightFootFz() > forceThreshold)
    {
        if(LEFT == side || RIGHT == side)
            impCtrl.run(state.dFeetOffset, yawRot[side]*skew*forceTorqueErr[side], dt);
        else
            impCtrl.run(state.dFeetOffset, (yawRot[LEFT]*skew*forceTorqueErr[LEFT] + yawRot[RIGHT]*skew*forceTorqueErr[RIGHT])/2, dt);
    }
    else
    {
        // Don't add to the dFeetOffset
    }

    // Decay the dFeetOffset
//    state.dFeetOffset -= gains.decay_gain[LEFT]*state.dFeetOffset;

    //------------------------
    //    CAP BODY OFFSET
    //------------------------
    const double dFeetOffsetTol = 0.06;
    double n = state.dFeetOffset.norm();
    if (n > dFeetOffsetTol) {
      state.dFeetOffset *= dFeetOffsetTol/n;
    }

    //------------------------
    //    ADJUST FEET TFs
    //------------------------
    // Pretranslate feet TF by integrated feet error translation vector
    Eigen::Isometry3d tempFootTF[2];
    tempFootTF[LEFT] = footTF[LEFT].pretranslate(state.dFeetOffset.block<3,1>(0,0));
    tempFootTF[RIGHT] = footTF[RIGHT].pretranslate(state.dFeetOffset.block<3,1>(0,0));

    //------------------------
    //   GET NEW LEG ANGLES
    //------------------------
    // Run IK on the adjusted feet TF to get new joint angles
    bool ok = false;
    // Check IK for each new foot TF. If either fails, use previous feet TF
    // New joint angles for both legs
    Vector6d qNew[2];
    ok = hubo.huboLegIK(qNew[LEFT], tempFootTF[LEFT], qPrev[LEFT], LEFT);
    if(ok)
    {
        ok = hubo.huboLegIK(qNew[RIGHT], tempFootTF[RIGHT], qPrev[RIGHT], RIGHT);
        state.prevdFeetOffset = state.dFeetOffset;
    }
    else // use previous integrated feet offset to get joint angles
    {
        std::cout << "IK Failed in impedance controller. Using previous feet TF.\n";
        // Pretranslate feet TF by integrated feet error translation vector
        footTF[LEFT].pretranslate(state.prevdFeetOffset.block<3,1>(0,0));
        footTF[RIGHT].pretranslate(state.prevdFeetOffset.block<3,1>(0,0));
        hubo.huboLegIK(qNew[LEFT], footTF[LEFT], qPrev[LEFT], LEFT);
        hubo.huboLegIK(qNew[RIGHT], footTF[RIGHT], qPrev[RIGHT], RIGHT);
    }

    hubo.huboLegFK( footTF[LEFT], qNew[LEFT], LEFT ); 
    if(counter > 40)
        std::cout << " aft " << footTF[LEFT](2,3);

    //----------------------
    //   DEBUG PRINT OUT
    //----------------------
    if(counter > 40)
    {
    if(true)
    {
        std::cout //<< " K: " << kP
                  //<< " TdL: " << -elem.torque[LEFT][0] << ", " << -elem.torque[LEFT][1]
                  //<< " TdR: " << -elem.torque[RIGHT][0] << ", " << -elem.torque[RIGHT][1]
                  //<< " MyLR: " << hubo.getLeftFootMy() << ", " << hubo.getRightFootMy()
                  //<< " MxLR: " << hubo.getLeftFootMx() << ", " << hubo.getRightFootMx()
                  << " mFz: " << hubo.getLeftFootFz()
                  << " dFz: " << -elem.forces[LEFT][2]
                  << " FTe: " << forceTorqueErr[LEFT].z()
                  //<< " Fte: " << instantaneousFeetOffset.transpose()
                  << " FeetE: " << state.dFeetOffset(2)
                  << " qDfL: " << (qNew[LEFT] - qPrev[LEFT]).transpose()
                  << "\n";
    }
    }
    //-----------------------
    //   SET JOINT ANGLES
    //-----------------------
    // Set leg joint angles for current timestep of trajectory
    {
        elem.angles[LHY] = qNew[LEFT](HY);
        elem.angles[LHR] = qNew[LEFT](HR);
        elem.angles[LHP] = qNew[LEFT](HP);
        elem.angles[LKN] = qNew[LEFT](KN);
        elem.angles[LAP] = qNew[LEFT](AP);
        elem.angles[LAR] = qNew[LEFT](AR);

        elem.angles[RHY] = qNew[RIGHT](HY);
        elem.angles[RHR] = qNew[RIGHT](HR);
        elem.angles[RHP] = qNew[RIGHT](HP);
        elem.angles[RKN] = qNew[RIGHT](KN);
        elem.angles[RAP] = qNew[RIGHT](AP);
        elem.angles[RAR] = qNew[RIGHT](AR);
    }
    if(counter > 40)
        counter = 0;
}