feat: added comments
This commit is contained in:
		
							
								
								
									
										179
									
								
								control.py
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								control.py
									
									
									
									
									
								
							@@ -56,12 +56,15 @@ REAL = 0
 | 
			
		||||
 | 
			
		||||
# Robot setup
 | 
			
		||||
if REAL == 1:
 | 
			
		||||
    portHandler = PortHandler("/dev/ttyUSB1")
 | 
			
		||||
    try:
 | 
			
		||||
        portHandler = PortHandler("/dev/ttyUSB0")
 | 
			
		||||
    except:
 | 
			
		||||
        portHandler = PortHandler("/dev/ttyUSB1")
 | 
			
		||||
 | 
			
		||||
    packetHandler = PacketHandler(1.0)
 | 
			
		||||
 | 
			
		||||
    portHandler.openPort()
 | 
			
		||||
    x = portHandler.setBaudRate(1000000)
 | 
			
		||||
    print(x)
 | 
			
		||||
    portHandler.setBaudRate(1000000)
 | 
			
		||||
    ADDR_GOAL_POSITION = 30
 | 
			
		||||
 | 
			
		||||
    ids = []
 | 
			
		||||
@@ -76,15 +79,19 @@ if REAL == 1:
 | 
			
		||||
        input()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Done
 | 
			
		||||
 | 
			
		||||
def interpol2(point2, point1, t):
 | 
			
		||||
    """
 | 
			
		||||
    Linear interpolation between two points in space
 | 
			
		||||
    """
 | 
			
		||||
    x1, y1, z1 = point1
 | 
			
		||||
    x2, y2, z2 = point2
 | 
			
		||||
    return t * x1 + (1 - t) * x2, t * y1 + (1 - t) * y2, t * z1 + (1 - t) * z2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_current_step(t, step_duration, movement_duration):
 | 
			
		||||
    """
 | 
			
		||||
    helper function used to calculate the current step of the movement i.e. what part of the movement.
 | 
			
		||||
    """
 | 
			
		||||
    time_passed = 0
 | 
			
		||||
    for i in range(len(step_duration)):
 | 
			
		||||
        time_passed += step_duration[i]
 | 
			
		||||
@@ -93,6 +100,9 @@ def get_current_step(t, step_duration, movement_duration):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_current_step_advancement(t, movement_duration, step_duration, current_step):
 | 
			
		||||
    """
 | 
			
		||||
    helper function used to calculate the current advancement of the movement step i.e. the percentage of progression of said movement.
 | 
			
		||||
    """
 | 
			
		||||
    current_step = get_current_step(t, step_duration, movement_duration)
 | 
			
		||||
    t = t % movement_duration
 | 
			
		||||
    for i in range(0, current_step):
 | 
			
		||||
@@ -102,6 +112,7 @@ def get_current_step_advancement(t, movement_duration, step_duration, current_st
 | 
			
		||||
 | 
			
		||||
def inverse(x, y, z):
 | 
			
		||||
    """
 | 
			
		||||
    Calculate the angle of each motor to have the end of the feet at a specified position
 | 
			
		||||
    """
 | 
			
		||||
    # Dimensions (m)
 | 
			
		||||
    z += l1v
 | 
			
		||||
@@ -109,7 +120,6 @@ def inverse(x, y, z):
 | 
			
		||||
    theta0 = atan2(y, x)
 | 
			
		||||
 | 
			
		||||
    l = sqrt((sqrt(x ** 2 + y ** 2) - l1) ** 2 + z ** 2)
 | 
			
		||||
    # l = sqrt((x - l1h*cos(theta0)) ** 2 + (y - l1h*sin(theta0)) ** 2 + (z + l1v) ** 2)
 | 
			
		||||
 | 
			
		||||
    param2 = -1 * (-(l ** 2) + l2 ** 2 + l3 ** 2) / (2 * l2 * l3)
 | 
			
		||||
 | 
			
		||||
@@ -126,15 +136,13 @@ def inverse(x, y, z):
 | 
			
		||||
 | 
			
		||||
    theta1 = acos(param1) + asin(z / l)
 | 
			
		||||
 | 
			
		||||
    # return [-theta0, theta1, theta2]
 | 
			
		||||
    angle1 = atan(l2v / l2h)
 | 
			
		||||
    return [-theta0, theta1 + angle1, theta2 + angle1 - pi / 2 + atan(l3h / l3v)]
 | 
			
		||||
    # return [0, angle1 , angle1 -pi/2 + atan(l3h/l3v)]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def legs(targets_robot):
 | 
			
		||||
    """
 | 
			
		||||
    takes a list of target and offsets it to be in the legs referential
 | 
			
		||||
    takes a list of target and offsets them to be in the legs referential
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    targets = [0] * 18
 | 
			
		||||
@@ -163,7 +171,72 @@ def legs(targets_robot):
 | 
			
		||||
    return targets
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def normalize(matrix, slider_max, speed):
 | 
			
		||||
    return (matrix / slider_max) * speed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
counter = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def convert_to_robot(positions):
 | 
			
		||||
    """
 | 
			
		||||
    Send a robot position to the real robot.
 | 
			
		||||
    """
 | 
			
		||||
    global counter
 | 
			
		||||
    counter += 1
 | 
			
		||||
    if counter % 2 != 0:
 | 
			
		||||
        return
 | 
			
		||||
    index = [
 | 
			
		||||
        11, 12, 13,
 | 
			
		||||
        41, 42, 43,
 | 
			
		||||
        21, 22, 23,
 | 
			
		||||
        51, 52, 53,
 | 
			
		||||
        61, 62, 63,
 | 
			
		||||
        31, 32, 33]
 | 
			
		||||
    dir = [-1] * 18
 | 
			
		||||
 | 
			
		||||
    for i in range(len(positions)):
 | 
			
		||||
        value = int(512 + positions[i] * 150 * dir[i])
 | 
			
		||||
        packetHandler.write2ByteTxOnly(portHandler, index[i], ADDR_GOAL_POSITION, value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def walk(t, sx, sy, sr):
 | 
			
		||||
    """
 | 
			
		||||
    Choose the algorithm depending on input of xbox controller
 | 
			
		||||
    """
 | 
			
		||||
    xboxdata = xbox.get_data()
 | 
			
		||||
    if xbox.initialized:
 | 
			
		||||
        max_slider = 0.200
 | 
			
		||||
        controllerLogger.debug(xboxdata)
 | 
			
		||||
        if xbox.mode == 0:
 | 
			
		||||
            positions = static()
 | 
			
		||||
        elif xbox.mode == 1:
 | 
			
		||||
            positions = jump(xboxdata["y2"])
 | 
			
		||||
        elif xbox.mode == 2:
 | 
			
		||||
            positions = dino_naive(t, max_slider * xboxdata["y1"], max_slider * xboxdata["x1"],
 | 
			
		||||
                                   max_slider * xboxdata["y2"],
 | 
			
		||||
                                   max_slider * xboxdata["x2"], max_slider * (xboxdata["r2"] + 1))
 | 
			
		||||
        elif xbox.mode == 3:
 | 
			
		||||
            positions = naive_walk(t, max_slider * xboxdata["x1"], max_slider * xboxdata["y1"])
 | 
			
		||||
        elif xbox.mode == 4:
 | 
			
		||||
            positions = walk_v2(t, max_slider * xboxdata["y1"], -1 * max_slider * xboxdata["x1"],
 | 
			
		||||
                                xboxdata["x2"] * max_slider,
 | 
			
		||||
                                max_slider * xboxdata["y2"])
 | 
			
		||||
        # print(positions)
 | 
			
		||||
        if REAL == 1:
 | 
			
		||||
            convert_to_robot(positions)
 | 
			
		||||
 | 
			
		||||
        return positions
 | 
			
		||||
    else:
 | 
			
		||||
        return walk_v2(t, sx, sy, sr, None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# different move algorithm
 | 
			
		||||
 | 
			
		||||
def naive_walk(t, speed_x, speed_y):
 | 
			
		||||
    """
 | 
			
		||||
    First version of walk, using triangle for each step
 | 
			
		||||
    """
 | 
			
		||||
    slider_max = 0.200
 | 
			
		||||
 | 
			
		||||
    real_position = np.copy(neutral_position)
 | 
			
		||||
@@ -229,88 +302,25 @@ def naive_walk(t, speed_x, speed_y):
 | 
			
		||||
    return legs(real_position)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def normalize(matrix, slider_max, speed):
 | 
			
		||||
    return (matrix / slider_max) * speed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
counter = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def convert_to_robot(positions):
 | 
			
		||||
    global counter
 | 
			
		||||
    counter += 1
 | 
			
		||||
    if counter % 2 != 0:
 | 
			
		||||
        return
 | 
			
		||||
    index = [
 | 
			
		||||
        11, 12, 13,
 | 
			
		||||
        41, 42, 43,
 | 
			
		||||
        21, 22, 23,
 | 
			
		||||
        51, 52, 53,
 | 
			
		||||
        61, 62, 63,
 | 
			
		||||
        31, 32, 33]
 | 
			
		||||
    dir = [-1] * 18
 | 
			
		||||
 | 
			
		||||
    for i in range(len(positions)):
 | 
			
		||||
        value = int(512 + positions[i] * 150 * dir[i])
 | 
			
		||||
        packetHandler.write2ByteTxOnly(portHandler, index[i], ADDR_GOAL_POSITION, value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def stand(x1, y1, x2, y2):
 | 
			
		||||
    return [
 | 
			
		||||
        0, 0, 0,
 | 
			
		||||
        0, 0, 0,
 | 
			
		||||
        x1, 0, 0,
 | 
			
		||||
        0, -0.5, 0,
 | 
			
		||||
        0, -0.5, 0,
 | 
			
		||||
        y1, 0, 0
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def walk(t, sx, sy, sr):
 | 
			
		||||
    xboxdata = xbox.get_data()
 | 
			
		||||
    if xbox.initialized:
 | 
			
		||||
        max_slider = 0.200
 | 
			
		||||
        controllerLogger.debug(xboxdata)
 | 
			
		||||
        if xbox.mode == 0:
 | 
			
		||||
            positions = static()
 | 
			
		||||
        elif xbox.mode == 1:
 | 
			
		||||
            positions = jump(xboxdata["y2"])
 | 
			
		||||
        elif xbox.mode == 2:
 | 
			
		||||
            positions = dino_naive(t, max_slider * xboxdata["y1"], max_slider * xboxdata["x1"],
 | 
			
		||||
                                   max_slider * xboxdata["y2"],
 | 
			
		||||
                                   max_slider * xboxdata["x2"], max_slider * (xboxdata["r2"] + 1))
 | 
			
		||||
        elif xbox.mode == 3:
 | 
			
		||||
            positions = naive_walk(t, max_slider * xboxdata["x1"], max_slider * xboxdata["y1"])
 | 
			
		||||
        elif xbox.mode == 4:
 | 
			
		||||
            positions = walk_v2(t, max_slider * xboxdata["y1"], -1 * max_slider * xboxdata["x1"],
 | 
			
		||||
                                xboxdata["x2"] * max_slider,
 | 
			
		||||
                                max_slider * xboxdata["y2"])
 | 
			
		||||
        elif xbox.mode == 5:
 | 
			
		||||
            positions = stand(xboxdata["x1"], xboxdata["y1"], xboxdata["x2"], xboxdata["y2"])
 | 
			
		||||
 | 
			
		||||
        # print(positions)
 | 
			
		||||
        if REAL == 1:
 | 
			
		||||
            convert_to_robot(positions)
 | 
			
		||||
 | 
			
		||||
        return positions
 | 
			
		||||
    else:
 | 
			
		||||
        return walk_v2(t, sx, sy, sr, None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def static():
 | 
			
		||||
    """
 | 
			
		||||
    Function to have the robot stand at the neutral position
 | 
			
		||||
    """
 | 
			
		||||
    return legs(neutral_position)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Walk V2
 | 
			
		||||
def walk_v2(t, speed_x, speed_y, speed_r, y2):
 | 
			
		||||
    """
 | 
			
		||||
    x1: speed along the x-axis
 | 
			
		||||
    y1: speed along the y-axis
 | 
			
		||||
    x2: rotational speed along the z-axis
 | 
			
		||||
    Second version of the walking algorithm, using circle for each leg
 | 
			
		||||
    This is the main algorithm.
 | 
			
		||||
    """
 | 
			
		||||
    max_dist = 0.3
 | 
			
		||||
 | 
			
		||||
    def get_rotation_center(speed_x, speed_y, theta_point):
 | 
			
		||||
        """
 | 
			
		||||
        Helper function that calculate the center of rotation of the robot based on the current parameters
 | 
			
		||||
        """
 | 
			
		||||
        norm = sqrt(speed_x ** 2 + speed_y ** 2)
 | 
			
		||||
 | 
			
		||||
        r = 1000 if theta_point == 0 else norm / theta_point
 | 
			
		||||
@@ -320,9 +330,7 @@ def walk_v2(t, speed_x, speed_y, speed_r, y2):
 | 
			
		||||
            return 0, 0
 | 
			
		||||
 | 
			
		||||
    center_x, center_y = get_rotation_center(speed_x, speed_y, speed_r)
 | 
			
		||||
 | 
			
		||||
    legsLogger.debug(f"rotation center: center_x: {center_x}, center_y: {center_y}")
 | 
			
		||||
 | 
			
		||||
    real_position = np.copy(neutral_position)
 | 
			
		||||
 | 
			
		||||
    movement_z = np.array([
 | 
			
		||||
@@ -408,6 +416,9 @@ def walk_v2(t, speed_x, speed_y, speed_r, y2):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def jump(sy):
 | 
			
		||||
    """
 | 
			
		||||
    Make the robot jump (at least we wished)
 | 
			
		||||
    """
 | 
			
		||||
    offset = np.array([
 | 
			
		||||
        [0, 0, -0.15],
 | 
			
		||||
        [0, 0, -0.15],
 | 
			
		||||
@@ -420,8 +431,10 @@ def jump(sy):
 | 
			
		||||
    return legs(neutral_position + offset)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# based on walk V1
 | 
			
		||||
def dino_naive(t, speed_x, speed_y, hz, hy, hx):
 | 
			
		||||
    """
 | 
			
		||||
    based on walk naive, but with a head and a tail
 | 
			
		||||
    """
 | 
			
		||||
    slider_max = 0.200
 | 
			
		||||
 | 
			
		||||
    real_position = np.copy(neutral_position)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user