def init_variables(self):
     ''' Iniciação das variaveis da classe '''
     self.scannedChannels = [1, 2, 3]  # escolher canais nessa variavel
     self.stimMsg = Stimulator()
     self.stimMsg.channel = [1]
     self.stimMsg.mode = ['single']
     self.counter = 0
     self.channelIndex = 0
     self.maxAngle = []
     self.breaker = False
     self.channelCurrent = {}
     for c in self.scannedChannels:
         self.channelCurrent[c] = 0
     self.angleThreshold = 30
     self.min_current = 10
     self.current_step = 2
     self.current = self.min_current
示例#2
0
    def init_variables(self):
        ''' Iniciação das variaveis da classe '''
        self.stimMsg = Stimulator()
        self.stimMsg.mode = ['single']

        self.channelCurrent = {}
        self.channelCurrentReference = []
        self.start = False
        self.counter = 0
        self.totalCounter = 0

        self.activeChannels = 0
        self.activeCurrents = 0
        self.activePulseWidths = 0

        self.maxAngle = 0

        self.angleThreshold = 20
##################################################
######### Iniciando variáveis globais ############
##################################################
lowerRightLegAngle = -1
upperRightLegAngle = -1
rightKneeAngle = -1
lowerLeftLegAngle = -1
upperLeftLegAngle = -1
leftKneeAngle = -1

# estado atual
state = state0
# lista com todos estados, para implementação de botões usando outra imu
stateList = [state0, state1, state2, state3, state4, state5]

stimMsg = Stimulator()

#[quadrícepsDireito, ísquiosDireito, 'pé caído'Direito, panturrilhaDireito, quadrícepsEsquerdo, ísquiosEsquerdo, 'pé caído'Esquerdo, panturrilhaEsquerdo]
# Nota: músculo do 'pé caído' ativa com facilidade, usar corrente baixa
#stimMsg.channel = [1, 2, 3, 4, 5, 6, 7, 8]
#stimMsg.mode = ['single', 'single', 'single', 'single', 'single', 'single', 'single', 'single']
##stimMsg.pulse_current = [2, 2, 2, 2, 0, 0, 0, 0] # currenet in mA
##stimMsg.pulse_width = [0, 0, 0, 0, 0, 0, 0, 0]

#[quadrícepsDireito, ísquiosDireito, quadrícepsEsquerdo, ísquiosEsquerdo]
stimMsg.channel = [1, 2, 3, 4]
stimMsg.mode = ['single', 'single', 'single', 'single']
stimMsg.pulse_current = [18, 18, 18, 16]  # currenet in mA
#stimMsg.pulse_current = [10, 10, 10, 10] # currenet in mA
stimMsg.pulse_width = [0, 0, 0, 0]
            rospy.sleep(5)

            counter = 0
            channel += 1
    else:
        breaker = True


##################################################
##### Iniciação de variáveis globais #############
##################################################

numOfChannels = 2

stimMsg = Stimulator()
stimMsg.channel = [1]
stimMsg.mode = ['single']

counter = 0

channel = 1

maxAngle = []

bestChannels = []

breaker = False

##################################################
##### Loop do ROS ################################
示例#5
0
def control_knee():
    global t_control
    global stimMsg
    global update_values
    global co_activation
    global new_current_quad
    global new_current_hams
    global control_sel
    global pw_min_h
    global pw_min_q
    global channels_sel
    global control_onoff
    global control_enable_quad
    global control_enable_hams
    global ilc_memory
    global ilc_i
    global Kp_now
    global Ki_now
    global Kd_now
    global ES_A_now
    global ES_omega_now
    global ES_phase_now
    global ES_K_now
    global ES_RC_now
    global ILC_alpha_now
    global ILC_beta_now
    global ILC_gama_now
    global initTime

    # init_variables
    t_control = [0, 0]

    # init control node
    controller = control.Control(rospy.init_node('control', anonymous=False))

    # communicate with the dynamic server
    dyn_params = reconfig.Client('server', config_callback=server_callback)

    # subscribed topics
    sub = dict()
    sub.update({
        'pedal':
        rospy.Subscriber('imu/pedal', Imu, callback=imu_callback),
        'ref':
        rospy.Subscriber('ref_channel', Float64, callback=reference_callback),
        'steps':
        rospy.Subscriber('steps_channel', Float64, callback=steps_callback),
        'curve':
        rospy.Subscriber('calibration_channel',
                         Float64,
                         callback=curve_callback)
    })
    # sub = {}
    # sub['pedal'] = rospy.Subscriber('imu/pedal', Imu, callback=imu_callback)
    # sub['ref'] = rospy.Subscriber('ref_channel', Float64, callback=reference_callback)
    # sub['steps'] = rospy.Subscriber('steps_channel', Float64, callback=steps_callback)

    # published topics
    pub = dict()
    pub.update({
        'talker':
        rospy.Publisher('chatter', String, queue_size=10),
        'control':
        rospy.Publisher('stimulator/ccl_update', Stimulator, queue_size=10),
        'angle':
        rospy.Publisher('control/angle', Float64, queue_size=10),
        'signal':
        rospy.Publisher('control/stimsignal', Int32MultiArray, queue_size=10)
    })

    # define loop rate (in hz)
    rate = rospy.Rate(freq)

    # build basic angle message
    angleMsg = Float64()
    # errMsg = Float64()

    # build basic stimulator message
    stimMsg = Stimulator()
    stimMsg.mode = ['single', 'single', 'single', 'single']
    stimMsg.pulse_width = [0, 0, 0, 0]
    stimMsg.pulse_current = [0, 0, 0, 0]
    stimMsg.channel = [1, 2, 3, 4]

    control_sel = 0
    pw_min_h = 0
    pw_min_q = 0
    channels_sel = 0
    control_onoff = False
    ESC_now = [0, 0, 0, 0, 0]
    ILC_now = [0, 0, 0]
    co_activation = False
    initTime = tempo.time()

    # load inverse dynamics
    try:
        ID_data = sio.loadmat(ID_path)
        id_pw = ID_data['id_pw'][0]
        id_angle = ID_data['id_angle'][0]
        # knee_ref = reference_data['knee_ref'][0]
        # loaded = 1
    except:
        print("Ooops, the file you tried to load is not in the folder.")
        # knee_ref = [0, 0, 0, 0]

    # ---------------------------------------------------- start
    while not rospy.is_shutdown():

        thisKnee = angle[-1]
        thisError = err_angle[-1]
        thisRef = refKnee[-1]
        thisTime = tempo.time() - initTime

        # ============================== >controllers start here
        new_kp = Kp_vector[-1]
        new_ki = Ki_vector[-1]
        new_kd = Kd_vector[-1]
        new_kp_hat = Kp_hat_vector[-1]
        new_ki_hat = Ki_hat_vector[-1]
        new_kd_hat = Kd_hat_vector[-1]
        newIntegralError = 0
        new_u = 0
        jcost = controller.jfunction(thisError, freq)  # cost function

        if not co_activation:
            co_act_h = 0
            co_act_q = 0
        else:
            co_act_h = pw_min_h
            co_act_q = pw_min_q

        if control_onoff:

            # Open-loop inverse dynamics
            if control_sel == 0:

                try:
                    res = next(x for x in id_angle if x > thisRef)
                    # print list(id_angle).index(res)
                except StopIteration:
                    res = 0
                    print "Not in recruitment curve"

                new_u = res / 500

                # if thisError < 0:
                #     new_u = -1
                # else:
                #     new_u = 1

            # PID
            elif control_sel == 1:
                new_kp = Kp_now
                new_ki = Ki_now
                new_kd = Kd_now

                new_u, newIntegralError = controller.pid(
                    thisError, u[-1], u[-2], integralError[-1], freq,
                    [new_kp, new_ki, new_kd])

            # PID-ILC
            elif control_sel == 2:
                new_kp = Kp_now
                new_ki = Ki_now
                new_kd = Kd_now

                # first do PID
                thisU_PID, newIntegralError = controller.pid(
                    thisError, u[-1], u[-2], integralError[-1], freq,
                    [new_kp, new_ki, new_kd])

                # then ILC
                ilc_send[0] = ilc_memory[0][ilc_i]
                ilc_send[1] = ilc_memory[1][ilc_i]

                # only change new_u after the second cycle
                if ilc_memory[0][ilc_i] == 0:
                    new_u = thisU_PID
                else:
                    ILC_now[0] = ILC_alpha_now
                    ILC_now[1] = ILC_beta_now
                    ILC_now[2] = ILC_gama_now
                    new_u = controller.pid_ilc(ilc_send, ILC_now, thisU_PID,
                                               ilc_i)

                if new_u > 1:
                    new_u = 1
                elif new_u < -1:
                    new_u = -1

                # update ilc_memory
                ilc_memory[0][ilc_i] = thisError
                ilc_memory[1][ilc_i] = new_u

                # update counter
                if ilc_i < len(ilc_memory[0]) - 1:
                    ilc_i = ilc_i + 1
                else:
                    ilc_i = 0

            # PID-ES
            elif control_sel == 3:
                # calculate new pid parameters using ES
                ESC_now[0] = ES_A_now
                ESC_now[1] = ES_omega_now
                ESC_now[2] = ES_phase_now
                ESC_now[3] = ES_RC_now
                ESC_now[4] = ES_K_now

                new_kp, new_kp_hat = controller.pid_es2(
                    jcost, jcost_vector[-1], Kp_vector[-1], Kp_hat_vector[-1],
                    1 / freq, thisTime, ESC_now)  # new kp

                ESC_now[0] = ES_A_now / 4  # ES_A_now
                # ESC_now[1] = ES_omega_now-2
                ESC_now[2] = ES_phase_now + 0.1745
                # ESC_now[3] = ES_RC_now/2
                # ESC_now[4] = ES_K_now/2
                new_ki, new_ki_hat = controller.pid_es2(
                    jcost, jcost_vector[-1], Ki_vector[-1], Ki_hat_vector[-1],
                    1 / freq, thisTime, ESC_now)  # new ki

                ESC_now[0] = ES_A_now / 16  # ES_A_now
                # ESC_now[1] = ES_omega_now-3
                ESC_now[2] = ES_phase_now + 0.523
                # ESC_now[3] = ES_RC_now/8
                # ESC_now[4] = ES_K_now/8

                new_kd, new_kd_hat = controller.pid_es2(
                    jcost, jcost_vector[-1], Kd_vector[-1], Kd_hat_vector[-1],
                    1 / freq, thisTime, ESC_now)  # new kd

                # do PID
                new_u, newIntegralError = controller.pid(
                    thisError, u[-1], u[-2], integralError[-1], freq,
                    [new_kp, new_ki, new_kd])
            # CR
            elif control_sel == 4:  # curve recruitment
                if control_enable_quad == 1:
                    new_u = curveRecr[-1]
                elif control_enable_hams == 1:
                    new_u = -curveRecr[-1]

            # no controller
            else:
                print("No controller was selected.")

                new_kp = 0
                new_ki = 0
                new_kd = 0
                new_kp_hat = 0
                new_ki_hat = 0
                new_kd_hat = 0
                jcost = 0
                newIntegralError = 0
                new_u = 0

        if new_u > 1:
            new_u = 1
        elif new_u < -1:
            new_u = -1

        # update vectors
        Kp_vector.append(new_kp)
        Ki_vector.append(new_ki)
        Kd_vector.append(new_kd)
        Kp_hat_vector.append(new_kp_hat)
        Ki_hat_vector.append(new_ki_hat)
        Kd_hat_vector.append(new_kd_hat)
        jcost_vector.append(jcost)
        integralError.append(newIntegralError)
        u.append(new_u)

        # print refKnee[-1]

        # ============================== controllers end here

        # u to pw
        # new_pw = round(abs(u[-1] * 500) / 10) * 10

        # define pw for muscles
        if u[-1] < 0:
            # new_pw = round(abs(u[-1]) * (500-pw_min_h) + pw_min_h) / 10 * 10  # u to pw
            new_pw = round(abs(u[-1]) * (500 - pw_min_h) + pw_min_h)  # u to pw
            pw_h.append(new_pw)
            pw_q.append(co_act_q)
            controlMsg = "angle: %.3f, error: %.3f, u: %.3f (pw: %.1f) (Q), kp,ki,kd = { %.5f, %.5f, %.5f} : "\
                         % (thisKnee, thisError, u[-1], pw_q[-1], Kp_vector[-1], Ki_vector[-1], Kd_vector[-1])

        else:
            new_pw = round(abs(u[-1]) * (500 - pw_min_q) + pw_min_q)  # u to pw
            pw_q.append(new_pw)
            pw_h.append(co_act_h)
            controlMsg = "angle: %.3f, error: %.3f, u: %.3f (pw: %.1f) (H), kp,ki,kd = { %.5f, %.5f, %.5f} : "\
                         % (thisKnee, thisError, u[-1], pw_h[-1], Kp_vector[-1], Ki_vector[-1], Kd_vector[-1])

        print(controlMsg)

        # define current for muscles
        current_q.append(new_current_quad)
        current_h.append(new_current_hams)

        # update topics
        if channels_sel == 1:  # right leg
            stimMsg.pulse_width = [0, 0, pw_q[-1], pw_h[-1]]
            stimMsg.pulse_current = [0, 0, current_q[-1], current_h[-1]]
        else:  # left leg
            stimMsg.pulse_width = [pw_q[-1], pw_h[-1], 0, 0]
            stimMsg.pulse_current = [current_q[-1], current_h[-1], 0, 0]

        pub['control'].publish(stimMsg)  # send stim update

        angleMsg.data = thisKnee
        pub['angle'].publish(angleMsg)  # send imu update

        # update timestamp
        # ts = tempo.time()
        t_control.append(thisTime)

        # next iteration
        rate.sleep()

    # ---------------------------------------------------- save everything
    # recreate vectors
    angle_err_lists = [angle, err_angle, t_angle]
    pid_lists = [Kp_vector, Ki_vector, Kd_vector, integralError, t_control]
    stim_lists = [current_q, current_h, pw_q, pw_h, t_control]
    ref_lists = [refKnee, t_ref, curveRecr, t_curve]
    ilc_lists = [ilc_memory, ILC_now, t_control]
    esc_lists = [
        ESC_now, t_control, Kp_hat_vector, Ki_hat_vector, Kd_hat_vector,
        jcost_vector
    ]
    control_lists = [u, t_control]
    gui_lists = ([
        t_gui, gui_enable_c, gui_control_sel, gui_step_time, gui_kp, gui_ki,
        gui_kd, gui_alpha, gui_beta, gui_gama, gui_A, gui_omega, gui_phase,
        gui_channels_sel, gui_pw_min_q, gui_pw_min_h, gui_K, gui_RC
    ])
    path_lists = ([gui_ref_param])
    steps_lists = ([t_steps, count_steps])

    # create name of the file
    currentDT = datetime.datetime.now()
    # path_str = "/home/bb8/Desktop/gait_"
    path_str = gui_save_param[-1]
    if channels_sel == 1:  # right leg
        leg_str = '_R_'
    else:  # left leg
        leg_str = '_L_'

    if control_sel == 0:
        control_str = '0_'
    elif control_sel == 1:
        control_str = '1_'
    elif control_sel == 2:
        control_str = '2_'
    elif control_sel == 3:
        control_str = '3_'
    elif control_sel == 4:
        control_str = '4_'
    else:
        control_str = 'x_'

    if not co_activation:
        coact_str = "_noCA"
    else:
        coact_str = "_CA"

    currentDT_str = str(currentDT)
    name_file = path_str + coact_str + leg_str + control_str + currentDT_str + ".mat"

    # save .mat
    sio.savemat(
        name_file, {
            'angle_err_lists': angle_err_lists,
            'pid_lists': pid_lists,
            'stim_lists': stim_lists,
            'ref_lists': ref_lists,
            'ilc_lists': ilc_lists,
            'control_lists': control_lists,
            'esc_lists': esc_lists,
            'gui_lists': gui_lists,
            'path_lists': path_lists,
            'steps_lists': steps_lists
        })
示例#6
0
def main():
    global stimMsg

    # init control node
    controller = control.Control(rospy.init_node('control', anonymous=False))

    # get control config
    config_dict = rospy.get_param('/ema_trike/control')

    # list subscribed topics
    sub = {}
    sub['pedal'] = rospy.Subscriber('imu/pedal', Imu, callback=pedal_callback)
    sub['remote'] = rospy.Subscriber('imu/remote_buttons',
                                     Int8,
                                     callback=remote_callback)

    # list published topics
    pub = {}
    pub['control'] = rospy.Publisher('stimulator/ccl_update',
                                     Stimulator,
                                     queue_size=10)
    pub['angle'] = rospy.Publisher('control/angle', Float64, queue_size=10)
    pub['speed'] = rospy.Publisher('control/speed', Float64, queue_size=10)

    # define loop rate (in hz)
    rate = rospy.Rate(50)

    # build basic stimulator message
    stimMsg = Stimulator()
    stimMsg.channel = [1, 2]
    stimMsg.mode = ['single', 'single']
    stimMsg.pulse_current = [18, 18]

    # build basic angle message
    angleMsg = Float64()

    # build basic speed message
    speedMsg = Float64()

    # node loop
    while not rospy.is_shutdown():
        # calculate control signal
        if on_off == True:
            pwl, pwr = controller.calculate(angle[-1], speed[-1], speed_ref,
                                            speed_err)
        else:
            pwl, pwr = [0, 0]

        # send stimulator update
        stimMsg.pulse_width = [pwl, pwr]
        pub['control'].publish(stimMsg)

        # send angle update
        angleMsg.data = angle[-1]
        pub['angle'].publish(angleMsg)

        # send speed update
        speedMsg.data = speed[-1]
        pub['speed'].publish(speedMsg)

        # store control signal for plotting
        pw_left.append(pwl)
        pw_right.append(pwr)

        # wait for next control loop
        rate.sleep()
示例#7
0
# estado atual
state = state0
# lista com todos estados, para implementação de botões usando outra imu
stateList = [state0, state1, state2, state3, state4, state5]

##################################################
##### CANAIS DO ELETROESTIMIULADOR################
##################################################
##### DESATIVAR CANAIS NAO UTILIZADOS ############
##### EM  EM STIMULATOR.YALM #####################
##################################################

#testar se desativar canais no stimulator.yalm é suficiente, para não ter necessidade de alterar o código aqui

stimMsg = Stimulator()

#[quadrícepsDireito, ísquiosDireito, flexorQuadrilDireito, quadrícepsEsquerdo, ísquiosEsquerdo, flexorQuadrilEsquerdo]
#stimMsg.channel = [1, 2, 3, 4, 5, 6]
#stimMsg.mode = ['single', 'single', 'single', 'single', 'single', 'single', 'single', 'single']
##stimMsg.pulse_current = [2, 2, 2, 2, 2, 2, 2, 2] # currenet in mA
##stimMsg.pulse_width = [0, 0, 0, 0, 0, 0, 0, 0]

#[quadrícepsDireito, ísquiosDireito, quadrícepsEsquerdo, ísquiosEsquerdo]
stimMsg.channel = [1, 2, 3, 4, 5, 6]
stimMsg.mode = ['single'] * 6
stimMsg.pulse_current = [2, 2, 2, 2, 2, 2]  # calibrar pra cada paciente
stimMsg.pulse_width = [0] * 6

##################################################
##### Loop do ROS ################################