Ejemplo n.º 1
0
def identify_motor_acc(dt, dq, ddq, current, tau, Kt_p, Kv_p, ZERO_VELOCITY_THRESHOLD_SMALL, ZERO_JERK_THRESHOLD,
                       SHOW_THRESHOLD_EFFECT):
    # Filter current*****************************************************
    win = signal.hann(10)
    filtered_current = signal.convolve(current, win, mode='same') / sum(win)
    current = filtered_current

    # Mask valid data***************************************************
    # # remove high jerk
    dddq = np.gradient(ddq, 1) / dt
    maskConstAcc = (abs(dddq) < ZERO_JERK_THRESHOLD)
    # # erode to get only steady phases where acceleration is constant
    maskConstAcc = ndimage.morphology.binary_erosion(maskConstAcc, None, 100)
    maskPosVel = (dq > ZERO_VELOCITY_THRESHOLD_SMALL)
    maskNegVel = (dq < -ZERO_VELOCITY_THRESHOLD_SMALL)
    maskConstPosAcc = np.logical_and(maskConstAcc, maskPosVel)
    maskConstNegAcc = np.logical_and(maskConstAcc, maskNegVel)

    if SHOW_THRESHOLD_EFFECT:
        plt.figure()
        plt.plot(ddq)
        plt.ylabel('ddq')
        ddq_const = ddq.copy()
        ddq_const[np.logical_not(maskConstAcc)] = np.nan
        plt.plot(ddq_const)
        plt.ylabel('ddq_const')
        plt.show()

    # y              = a. x   +  b
    # i-Kt.tau-Kv.dq = Ka.ddq +  Kf
    #
    # Identification ***************************************************
    y = current - Kt_p * tau - Kv_p * dq
    y[maskConstPosAcc] = current[maskConstPosAcc] - Kt_p * tau[maskConstPosAcc] - Kv_p * dq[maskConstPosAcc]
    y[maskConstNegAcc] = current[maskConstNegAcc] - Kt_p * tau[maskConstNegAcc] - Kv_p * dq[maskConstNegAcc]
    y_label = r'$i(t)-{K_t}{\tau(t)}-{K_v}{\dot{q}(t)}$'
    x = ddq
    x_label = r'$\ddot{q}(t)$'
    (Kap, Kfp) = solve1stOrderLeastSquare(x[maskConstPosAcc], y[maskConstPosAcc])
    (Kan, b) = solve1stOrderLeastSquare(x[maskConstNegAcc], y[maskConstNegAcc])
    Kfn = -b

    # Plot *************************************************************
    plt.figure()
    plt.axhline(0, color='black', lw=1)
    plt.axvline(0, color='black', lw=1)
    plt.plot(x, y, '.', lw=3, markersize=1, c='0.5')
    plt.plot(x[maskConstPosAcc], y[maskConstPosAcc], 'rx', lw=3, markersize=1)
    plt.plot(x[maskConstNegAcc], y[maskConstNegAcc], 'bx', lw=3, markersize=1)

    # plot identified lin model
    plt.plot([min(x), max(x)], [Kap * min(x) + Kfp, Kap * max(x) + Kfp], 'g:', lw=3)
    plt.plot([min(x), max(x)], [Kan * min(x) - Kfn, Kan * max(x) - Kfn], 'g:', lw=3)
    plt.ylabel(y_label)
    plt.xlabel(x_label)
    plt.show()

    return (Kap, Kan, Kfp, Kfn)
def identify_motor_vel(dt, dq, ddq, ctrl, current, tau, Ktp, Ktn, Ks,
                       ZERO_VEL_THRESHOLD, ZERO_ACC_THRESHOLD, Nvel,
                       SHOW_THRESHOLD_EFFECT):
    # Mask valid data***************************************************
    # remove high acceleration
    maskConstVel = np.logical_and((abs(ddq) < ZERO_ACC_THRESHOLD),
                                  (abs(dq) > ZERO_VEL_THRESHOLD))
    # erode to get only steady phases where velocity is constant
    maskConstVel = ndimage.morphology.binary_erosion(maskConstVel, None, 100)
    maskPosVel = (dq > ZERO_VEL_THRESHOLD)
    maskNegVel = (dq < -ZERO_VEL_THRESHOLD)
    maskConstPosVel = np.logical_and(maskConstVel, maskPosVel)
    maskConstNegVel = np.logical_and(maskConstVel, maskNegVel)

    if SHOW_THRESHOLD_EFFECT:
        plt.figure()
        time = np.arange(0, dt * ddq.shape[0], dt)
        plt.plot(time, ddq, label='ddq')
        plt.ylabel('ddq')
        plt.plot(time[maskConstVel],
                 ddq[maskConstVel],
                 'rx ',
                 label='ddq const vel')
        plt.legend()

        plt.figure()
        plt.plot(dq)
        plt.ylabel('dq')
        dq_const = dq.copy()
        dq_const[np.logical_not(maskConstVel)] = np.nan
        plt.plot(dq_const)
        plt.ylabel('dq_const')
        plt.show()

    # Identification of BEMF effect ************************************
    times = np.arange(len(dq)) * dt
    plt.subplot(221)
    plt.plot(times, dq, lw=1)
    vels = kmeans(dq[maskConstVel], Nvel)
    # print('Velocity founds are:', vels)
    couleurs = ['g', 'r', 'c', 'm', 'y', 'k'] * 10  # why not?
    masksVels = []
    av_dq = []  # List of point kept for identification of BEMF effect
    av_delta_i = []
    it = 0
    for vel in vels[0]:
        it += 1
        currentMask = np.logical_and(dq > vel - 0.1, dq < vel + 0.1)
        currentMask = np.logical_and(currentMask, maskConstVel)
        masksVels.append(currentMask)
        plt.subplot(221)
        plt.plot(times[currentMask], dq[currentMask], 'o' + couleurs[it])
        plt.subplot(222)
        plt.xlabel('control')
        plt.ylabel('current')
        plt.plot(ctrl[currentMask] / IN_OUT_GAIN, Ks * current[currentMask],
                 'x' + couleurs[it])
        plt.subplot(223)
        plt.xlabel('control - current')
        plt.ylabel('velocity')
        plt.plot(ctrl[currentMask] / IN_OUT_GAIN - Ks * current[currentMask],
                 dq[currentMask], 'x' + couleurs[it])
        av_dq.append(np.mean(dq[currentMask]))
        av_delta_i.append(
            np.mean(ctrl[currentMask] / IN_OUT_GAIN -
                    Ks * current[currentMask]))
    plt.plot(av_delta_i, av_dq, 'o')

    av_dq = np.array(av_dq)
    av_delta_i = np.array(av_delta_i)
    av_dq_pos = av_dq[av_dq > 0]
    av_dq_neg = av_dq[av_dq < 0]
    av_delta_i_pos = av_delta_i[av_dq > 0]
    av_delta_i_neg = av_delta_i[av_dq < 0]
    (ap, bp) = solve1stOrderLeastSquare(av_delta_i_pos, av_dq_pos)
    (an, bn) = solve1stOrderLeastSquare(av_delta_i_neg, av_dq_neg)
    a = (an + ap) / 2
    b = (-bp + bn) / 2
    DeadZone = b / a
    # the half of the total dead zone
    K_bemf = 1.0 / a

    x = av_delta_i
    plt.plot([-b / a, b / a], [0., 0.], 'g:', lw=3)
    plt.plot([min(x), -b / a], [a * min(x) + b, 0.], 'g:', lw=3)
    plt.plot([b / a, max(x)], [0., a * max(x) - b], 'g:', lw=3)
    plt.show()
    # y        = a. x +  b
    # i-Kt.tau = Kv.dq + Kf
    #
    # Identification with fixed Kt ***************************************************
    y = Ks * current - Ktp * tau
    y[maskConstPosVel] = Ks * current[maskConstPosVel] - Ktp * tau[
        maskConstPosVel]
    y[maskConstNegVel] = Ks * current[maskConstNegVel] - Ktn * tau[
        maskConstNegVel]
    x = dq
    (a, b) = solve1stOrderLeastSquare(x[maskConstPosVel], y[maskConstPosVel])
    Kvp = a
    Kfp = b
    (a, b) = solve1stOrderLeastSquare(x[maskConstNegVel], y[maskConstNegVel])
    Kvn = a
    Kfn = -b

    # Plot *************************************************************
    plt.figure()
    plt.axhline(0, color='black', lw=1)
    plt.axvline(0, color='black', lw=1)
    plt.plot(x, y, '.', lw=3, markersize=1, c='0.5')
    plt.plot(x[maskConstPosVel], y[maskConstPosVel], 'rx', lw=3, markersize=1)
    plt.plot(x[maskConstNegVel], y[maskConstNegVel], 'bx', lw=3, markersize=1)
    # plot identified lin model
    plt.plot([0.0, max(dq)], [Kfp, Kvp * max(dq) + Kfp], 'g-')
    plt.plot([0.0, min(dq)], [-Kfn, Kvn * min(dq) - Kfn], 'g-')
    plt.ylabel(r'$i(t)-{K_t}{\tau(t)}$')
    plt.xlabel(r'$\dot{q}(t)$')
    plt.title('Fixed Kt identification')

    # Identification with variable Kt ***************************************************
    #    y = Ks*current
    #    A=np.vstack([np.ones(len(y[maskConstPosVel])),dq[maskConstPosVel], tau[maskConstPosVel]])
    #    coef = solveLeastSquare(A.T,y[maskConstPosVel])
    #    (Ktp2,Kvp2,Kfp2)=coef[2,0],coef[1,0],coef[0,0]
    #    A=np.vstack([np.ones(len(y[maskConstNegVel])),dq[maskConstNegVel], tau[maskConstNegVel]])
    #    coef = solveLeastSquare(A.T,y[maskConstNegVel])
    #    (Ktn2,Kvn2,Kfn2)=coef[2,0],coef[1,0],-coef[0,0]
    #    print 'Ktp2      = ', Ktp2;
    #    print 'Kvp2      = ', Kvp2;
    #    print 'Kfp2      = ', Kfp2;
    #    print 'Ktn2      = ', Ktn2;
    #    print 'Kvn2      = ', Kvn2;
    #    print 'Kfn2      = ', Kfn2;
    #    y = Ks*current-Ktp2*tau
    #    y[maskConstPosVel] = Ks*current[maskConstPosVel]-Ktp2*tau[maskConstPosVel]
    #    y[maskConstNegVel] = Ks*current[maskConstNegVel]-Ktn2*tau[maskConstNegVel]
    #    plt.figure()
    #    plt.axhline(0, color='black',lw=1)
    #    plt.axvline(0, color='black',lw=1)
    #    plt.plot(x     ,y     ,'.' ,lw=3,markersize=1,c='0.5');
    #    plt.plot(x[maskConstPosVel],y[maskConstPosVel],'rx',lw=3,markersize=1);
    #    plt.plot(x[maskConstNegVel],y[maskConstNegVel],'bx',lw=3,markersize=1);
    #    #plot identified lin model
    #    plt.plot([0.0,max(dq)],[ Kfp2,Kvp2*max(dq)+Kfp2],'g-')
    #    plt.plot([0.0,min(dq)],[-Kfn2,Kvn2*min(dq)-Kfn2],'g-')
    #    plt.ylabel(r'$i(t)-{K_t}{\tau(t)}$')
    #    plt.xlabel(r'$\dot{q}(t)$')
    #    plt.title('Variable Kt identification')
    #
    #     Plot to compare identification with variable/fixed Kt *****************************
    #    plt.figure()
    #    plt.plot(Ks*current, label='current');
    #    plt.plot(Ktp*tau, '--', label='Ktp*tau')
    #    plt.plot(Kvp*dq,   '--', label='Kvp*dq');
    #    plt.plot(Ktp*tau+Kvp*dq+Kfp, label='Ktp*tau+Kvp*dq+Kfp');
    #    plt.plot(Ktn*tau+Kvn*dq-Kfn, label='Ktn*tau+Kvn*dq-Kfn');
    #    plt.plot(Ktp2*tau+Kvp2*dq+Kfp2, label='Ktp2*tau+Kvp2*dq+Kfp2');
    #    plt.plot(Ktn2*tau+Kvn2*dq-Kfn2, label='Ktn2*tau+Kvn2*dq-Kfn2');
    #    plt.legend();

    plt.show()

    return (Kvp, Kvn, Kfp, Kfn, DeadZone, K_bemf)
def identify_motor_static(enc, dq, ctrl, current, tau, JOINT_ID, JOINT_NAME,
                          ZERO_VELOCITY_THRESHOLD,
                          ZERO_VELOCITY_THRESHOLD_SMALL,
                          SHOW_THRESHOLD_EFFECT):
    # remove high velocity
    maskConstAng = (abs(dq) < ZERO_VELOCITY_THRESHOLD)
    # erode to get only steady phases where velocity is small
    maskConstAng = ndimage.morphology.binary_erosion(maskConstAng, None, 100)
    maskPosVel = (dq > ZERO_VELOCITY_THRESHOLD_SMALL)
    maskNegVel = (dq < -ZERO_VELOCITY_THRESHOLD_SMALL)
    maskConstPosAng = np.logical_and(maskConstAng, maskPosVel)
    maskConstNegAng = np.logical_and(maskConstAng, maskNegVel)
    if SHOW_THRESHOLD_EFFECT:
        plt.figure()
        plt.plot(enc, label='q')
        q_const = enc.copy()
        q_const[np.logical_not(maskConstAng)] = np.nan
        plt.plot(q_const, label='q_const')
        plt.legend()

    # identify current sensor gain
    x = current[maskConstAng]
    y = ctrl[maskConstAng] / IN_OUT_GAIN
    maskPosErr = np.logical_and(y - x > 0.0, np.abs(x) > 0.5)
    maskNegErr = np.logical_and(y - x < 0.0, np.abs(x) > 0.5)
    print "Number of samples with constant angle:", x.shape[0]
    print "Number of samples with constant angle and pos vel:", x[
        maskPosErr].shape[0]
    print "Number of samples with constant angle and neg vel:", x[
        maskNegErr].shape[0]
    if (x[maskPosErr].shape[0] < 10):
        (Ks, DZ) = solve1stOrderLeastSquare(x[maskNegErr], y[maskNegErr])
    elif (x[maskNegErr].shape[0] < 10):
        (Ks, DZ) = solve1stOrderLeastSquare(x[maskPosErr], y[maskPosErr])
    else:
        (Ksn, DZn) = solve1stOrderLeastSquare(x[maskNegErr], y[maskNegErr])
        (Ksp, DZp) = solve1stOrderLeastSquare(x[maskPosErr], y[maskPosErr])
        Ks = 0.5 * (Ksp + Ksn)
        Ks = min([Ksp, Ksn])
        DZ = 0.5 * (DZp - DZn)
        print "Current sensor gains = ", Ksp, Ksn
        print "Deadzones            = ", DZp, -DZn

        x_neg = x[maskNegErr]
        y_neg = y[maskNegErr]
        plt.figure()
        plt.plot(x_neg, y_neg, '.', lw=3, markersize=1, c='0.5')
        plt.plot([min(x_neg), max(x_neg)],
                 [Ksn * min(x_neg) + DZn, Ksn * max(x_neg) + DZn],
                 'g:',
                 lw=3)
        plt.ylabel(r'$i(t)$')
        plt.xlabel(r'$u(t)$')
        plt.title('Negative current errors - Joint ' + JOINT_NAME)

        x_pos = x[maskPosErr]
        y_pos = y[maskPosErr]
        plt.figure()
        plt.plot(x_pos, y_pos, '.', lw=3, markersize=1, c='0.5')
        plt.plot([min(x_pos), max(x_pos)],
                 [Ksp * min(x_pos) + DZp, Ksp * max(x_pos) + DZp],
                 'g:',
                 lw=3)
        plt.ylabel(r'$i(t)$')
        plt.xlabel(r'$u(t)$')
        plt.title('Positive current errors - Joint ' + JOINT_NAME)
        plt.show()

    if (Ks < 0.0):
        print "ERROR: estimated Ks is negative! Setting it to 1"
        Ks = 1.0

    # plot dead zone effect ********************************************
    plt.figure()
    plt.plot(Ks * current, label='current')
    plt.plot(ctrl / IN_OUT_GAIN, label='control')
    plt.legend()

    plt.figure()
    y = Ks * current[maskConstAng]
    x = ctrl[maskConstAng] / IN_OUT_GAIN - Ks * current[maskConstAng]
    plt.ylabel(r'$i(t)$')
    plt.xlabel(r'$ctrl(t)-i(t)$')
    plt.plot(x, y, '.', lw=3, markersize=1, c='0.5')
    plt.plot(x[maskPosErr],
             y[maskPosErr],
             'rx',
             lw=3,
             markersize=1,
             label='pos err')
    plt.plot(x[maskNegErr],
             y[maskNegErr],
             'bx',
             lw=3,
             markersize=1,
             label='neg err')
    plt.legend()

    plt.figure()
    y = ctrl[maskConstAng] / IN_OUT_GAIN
    x = ctrl[maskConstAng] / IN_OUT_GAIN - Ks * current[maskConstAng]
    plt.ylabel(r'$ctrl(t)$')
    plt.xlabel(r'$ctrl(t)-i(t)$')
    plt.plot(x, y, '.', lw=3, markersize=1, c='0.5')
    plt.plot(x[maskPosErr],
             y[maskPosErr],
             'rx',
             lw=3,
             markersize=1,
             label='pos err')
    plt.plot(x[maskNegErr],
             y[maskNegErr],
             'bx',
             lw=3,
             markersize=1,
             label='neg err')
    plt.legend()

    plt.figure()
    y = ctrl / IN_OUT_GAIN
    x = Ks * current
    plt.ylabel(r'$ctrl(t)$')
    plt.xlabel(r'$i(t)$')
    plt.plot(x, y, '.', lw=3, markersize=1, c='0.5')
    plt.plot([-3, 3], [-3, 3])

    plt.show()
    #    y = a. x   +  b
    #    i = Kt.tau + Kf

    # Identification ***************************************************
    y = current  #*Ks
    x = tau
    (Ktp, Kfp) = solve1stOrderLeastSquare(x[maskConstPosAng],
                                          y[maskConstPosAng])
    (Ktn, b) = solve1stOrderLeastSquare(x[maskConstNegAng], y[maskConstNegAng])
    Kfn = -b

    # Plot *************************************************************
    plt.figure()
    plt.axhline(0, color='black', lw=1)
    plt.axvline(0, color='black', lw=1)
    plt.plot(x, y, '.', lw=3, markersize=1, c='0.5')
    plt.plot(x[maskConstPosAng], y[maskConstPosAng], 'rx', lw=3, markersize=1)
    plt.plot(x[maskConstNegAng], y[maskConstNegAng], 'bx', lw=3, markersize=1)
    #plot identified lin model
    plt.plot([min(x), max(x)], [Ktp * min(x) + Kfp, Ktp * max(x) + Kfp],
             'g:',
             lw=3)
    plt.plot([min(x), max(x)], [Ktn * min(x) - Kfn, Ktn * max(x) - Kfn],
             'g:',
             lw=3)
    plt.ylabel(r'$i(t)$')
    plt.xlabel(r'$\tau(t)$')
    plt.title('Static experiment - Joint ' + JOINT_NAME)

    print "cur_sens_gain[%d] = %f" % (JOINT_ID, Ks)
    print 'deadzone[%d]      = %f' % (JOINT_ID, DZ)
    print 'Kt_p[%d]          = %f' % (JOINT_ID, Ktp)
    print 'Kt_n[%d]          = %f' % (JOINT_ID, Ktn)
    print 'Kf_p[%d]          = %f' % (JOINT_ID, Kfp)
    print 'Kf_n[%d]          = %f' % (JOINT_ID, Kfn)

    print 'Kt_m[%d]          = %f' % (JOINT_ID, (Ktp + Ktn) / 2.0)
    print 'Kf_m[%d]          = %f' % (JOINT_ID, (Kfp + Kfn) / 2.0)

    return (Ktp, Ktn, Ks, DZ)