Skip to content
Snippets Groups Projects
main_solo12_control.py 7.46 KiB
Newer Older
import threading
Fanny Risbourg's avatar
Fanny Risbourg committed
import time
Fanny Risbourg's avatar
Fanny Risbourg committed
import numpy as np
Ale's avatar
Ale committed
import git
Ale's avatar
Ale committed
from datetime import datetime
Fanny Risbourg's avatar
Fanny Risbourg committed

Ale's avatar
Ale committed
import quadruped_reactive_walking as qrw
Fanny Risbourg's avatar
Fanny Risbourg committed
from .Controller import Controller
Fanny Risbourg's avatar
Fanny Risbourg committed
from .tools.LoggerControl import LoggerControl
Ale's avatar
Ale committed
from .WB_MPC.ProblemData import ProblemData, ProblemDataFull
Ale's avatar
Ale committed
from .WB_MPC.Target import Target
Your Name's avatar
Your Name committed

Fanny Risbourg's avatar
Fanny Risbourg committed
params = qrw.Params()  # Object that holds all controller parameters
Ale's avatar
Ale committed
pd = ProblemDataFull(params)
Ale's avatar
Ale committed
target = Target(pd)
Ale's avatar
Ale committed
target.update(0)
Ale's avatar
Ale committed
repo = git.Repo(search_parent_directories=True)
sha = repo.head.object.hexsha
Ale's avatar
Ale committed
msg = repo.head.object.message + "\nCommit: " + sha
Ale's avatar
Ale committed

Fanny Risbourg's avatar
Fanny Risbourg committed
    from .tools.PyBulletSimulator import PyBulletSimulator
    import libodri_control_interface_pywrap as oci
Fanny Risbourg's avatar
Fanny Risbourg committed
    from .tools.qualisysClient import QualisysClient
Fanny Risbourg's avatar
Fanny Risbourg committed
    """
    Thread to get the input
    """
    Make the robot go to the default initial position and wait for the user
    to press the Enter key to start the main control loop

    Args:
        device (robot wrapper): a wrapper to communicate with the robot
        q_init (array): the default position of the robot
    """
Fanny Risbourg's avatar
Fanny Risbourg committed
    Kp_pos = 6.0

    device.joints.set_position_gains(Kp_pos * np.ones(12))
    device.joints.set_velocity_gains(Kd_pos * np.ones(12))
    device.joints.set_desired_positions(q_init)
    device.joints.set_desired_velocities(np.zeros(12))
    device.joints.set_torques(np.zeros(12))

    i = threading.Thread(target=get_input)
    print("Put the robot on the floor and press Enter")
    while i.is_alive():
        device.parse_sensor_data()
        device.send_command_and_wait_end_of_cycle(params.dt_wbc)
    # Slow increase till 1/4th of mass is supported by each foot
Fanny Risbourg's avatar
Fanny Risbourg committed
    duration_increase = 2.0
    steps = int(duration_increase / params.dt_wbc)
Fanny Risbourg's avatar
Fanny Risbourg committed
    tau_ff = np.array([0.0, 0.022, 0.5] * 2 + [0.0, -0.022, -0.5] * 2)
    # tau_ff = np.array([0.0, 0.022, 0.5, 0.0, 0.022, 0.5, 0.0, 0.025, 0.575, 0.0, 0.025, 0.575])

    for i in range(steps):
        device.joints.set_torques(tau_ff * i / steps)
        device.parse_sensor_data()
        device.send_command_and_wait_end_of_cycle(params.dt_wbc)

def check_position_error(device, controller):
    """
    Check the distance between current and desired position of the joints

    Args:
        device (robot wrapper): a wrapper to communicate with the robot
        controller (array): the controller storing the desired position
    """
Ale's avatar
Ale committed
    if np.max(np.abs(controller.result.q_des - device.joints.positions)) > 0.15:
        print("DIFFERENCE: ", controller.result.q_des - device.joints.positions)
        print("q_des: ", controller.result.q_des)
        print("q_mes: ", device.joints.positions)
        return True
    return False


def damp_control(device, nb_motors):
    """
    Damp the control during 2.5 seconds
        device  (robot wrapper): a wrapper to communicate with the robot
        nb_motors (int): number of motors
    t = 0.0
    t_max = 2.5
    while (not device.is_timeout) and (t < t_max):
Fanny Risbourg's avatar
Fanny Risbourg committed
        device.parse_sensor_data()

        # Set desired quantities for the actuators
        device.joints.set_position_gains(np.zeros(nb_motors))
        device.joints.set_velocity_gains(0.1 * np.ones(nb_motors))
        device.joints.set_desired_positions(np.zeros(nb_motors))
        device.joints.set_desired_velocities(np.zeros(nb_motors))
        device.joints.set_torques(np.zeros(nb_motors))

        # Send command to the robot
        device.send_command_and_wait_end_of_cycle(params.dt_wbc)
        if (t % 1) < 5e-5:
Fanny Risbourg's avatar
Fanny Risbourg committed
            print("IMU attitude:", device.imu.attitude_euler)
            print("joint pos   :", device.joints.positions)
            print("joint vel   :", device.joints.velocities)
            device.robot_interface.PrintStats()
        t += params.dt_wbc
def control_loop():
    """
    Main function that calibrates the robot, get it into a default waiting position then launch
    the main control loop once the user has pressed the Enter key

    Args:
Fanny Risbourg's avatar
Fanny Risbourg committed
        des_vel_analysis (string)
Ale's avatar
Ale committed
    # Default position after calibration
    q_init = np.array(params.q_init.tolist())
Ale's avatar
Ale committed
    controller = Controller(pd, target, params, q_init, 0.0)
        device = oci.robot_from_yaml_file(params.config_file)
        qc = QualisysClient(ip="140.93.16.160", body_id=0)

    if params.LOGGING or params.PLOTTING:
Ale's avatar
Ale committed
        loggerControl = LoggerControl(pd, params, log_size=params.N_SIMULATION)
Fanny Risbourg's avatar
Fanny Risbourg committed
        device.Init(
Fanny Risbourg's avatar
Fanny Risbourg committed
            q_init,
            params.envID,
            params.use_flat_plane,
            params.enable_pyb_GUI,
            params.dt_wbc,
Fanny Risbourg's avatar
Fanny Risbourg committed
        )
Fanny Risbourg's avatar
Fanny Risbourg committed
    else:
        device.initialize(q_init[:])
        device.joints.set_zero_commands()
        device.parse_sensor_data()
        put_on_the_floor(device, q_init)

    # CONTROL LOOP ***************************************************
Fanny Risbourg's avatar
Fanny Risbourg committed

Fanny Risbourg's avatar
Fanny Risbourg committed
    t = 0.0
Your Name's avatar
Your Name committed
    t_max = (params.N_SIMULATION - 1) * params.dt_wbc
    t_log_whole = np.zeros((params.N_SIMULATION))
    k_log_whole = 0
Fanny Risbourg's avatar
Fanny Risbourg committed
    while (not device.is_timeout) and (t < t_max) and (not controller.error):
        if controller.compute(device, qc):
            break
Ale's avatar
Ale committed

        if t <= 10 * params.dt_wbc and check_position_error(device, controller):
            break
odri's avatar
odri committed
        device.joints.set_position_gains(controller.result.P)
        device.joints.set_velocity_gains(controller.result.D)
        device.joints.set_desired_positions(controller.result.q_des)
        device.joints.set_desired_velocities(controller.result.v_des)
        device.joints.set_torques(controller.result.FF * controller.result.tau_ff.ravel())
        device.send_command_and_wait_end_of_cycle(params.dt_wbc)
        if params.LOGGING or params.PLOTTING:
Your Name's avatar
Your Name committed
            loggerControl.sample(controller, device, qc)
        t += params.dt_wbc
        t_log_whole[k_log_whole] = t_end_whole - t_start_whole
        k_log_whole += 1

    # ****************************************************************
    damp_control(device, 12)
        print("Stopping parallel process MPC")
        controller.mpc.stop_parallel_loop()
    # ****************************************************************
    # Send 0 torques to the motors.
    device.joints.set_torques(np.zeros(12))
    device.send_command_and_wait_end_of_cycle(params.dt_wbc)
Ale's avatar
Ale committed
    if params.LOGGING:
Ale's avatar
Ale committed
        date_str = datetime.now().strftime("%Y_%m_%d_%H_%M")
        log_path = Path("/tmp") / "logs" / date_str
        log_path.mkdir(parents=True)
Ale's avatar
Ale committed
        loggerControl.save(str(log_path))
odri's avatar
odri committed
        with open(str(log_path / 'readme.txt'), 'w') as f:
            f.write(msg)
Ale's avatar
Ale committed
        if params.PLOTTING:
            loggerControl.plot(save=True, fileName=str(log_path))
            print("Plots saved in ", str(log_path) + "/")
    if params.SIMULATION and params.enable_pyb_GUI:
Your Name's avatar
Your Name committed
    return loggerControl
if __name__ == "__main__":
odri's avatar
odri committed
    # os.nice(-20)

Your Name's avatar
Your Name committed
    log = control_loop()
odri's avatar
odri committed
    # quit()