feat: created modules, logs and removed unuzed functions
This commit is contained in:
parent
ed7915386d
commit
8479dec345
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
models
|
||||||
|
__pycache__
|
158
control.py
158
control.py
@ -1,87 +1,55 @@
|
|||||||
|
import logging
|
||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
def sandbox(t):
|
|
||||||
"""
|
|
||||||
python simulator.py -m sandbox
|
|
||||||
|
|
||||||
Un premier bac à sable pour faire des expériences
|
|
||||||
|
|
||||||
La fonction reçoit le temps écoulé depuis le début (t) et retourne une position cible
|
|
||||||
pour les angles des 12 moteurs
|
|
||||||
|
|
||||||
- Entrée: t, le temps (secondes écoulées depuis le début)
|
|
||||||
- Sortie: un tableau contenant les 12 positions angulaires cibles (radian) pour les moteurs
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Par exemple, on envoie un mouvement sinusoidal
|
|
||||||
targets = [0] * 12
|
|
||||||
targets[0] = t ** 3
|
|
||||||
targets[1] = 0
|
|
||||||
targets[2] = 0
|
|
||||||
targets[3] = t ** 3
|
|
||||||
targets[4] = 0
|
|
||||||
targets[5] = 0
|
|
||||||
targets[6] = t ** 3
|
|
||||||
targets[7] = 0
|
|
||||||
targets[8] = 0
|
|
||||||
targets[9] = t ** 3
|
|
||||||
targets[10] = 0
|
|
||||||
targets[11] = 0
|
|
||||||
|
|
||||||
return targets
|
|
||||||
|
|
||||||
|
|
||||||
def direct(alpha, beta, gamma):
|
|
||||||
"""
|
|
||||||
python simulator.py -m direct
|
|
||||||
|
|
||||||
Le robot est figé en l'air, on ne contrôle qu'une patte
|
|
||||||
|
|
||||||
Reçoit en argument la cible (alpha, beta, gamma) des degrés de liberté de la patte, et produit
|
|
||||||
la position (x, y, z) atteinte par le bout de la patte
|
|
||||||
|
|
||||||
- Sliders: les angles des trois moteurs (alpha, beta, gamma)
|
|
||||||
- Entrées: alpha, beta, gamma, la cible (radians) des moteurs
|
|
||||||
- Sortie: un tableau contenant la position atteinte par le bout de la patte (en mètres)
|
|
||||||
"""
|
|
||||||
|
|
||||||
return 0, 0, 0
|
|
||||||
|
|
||||||
|
|
||||||
from math import *
|
from math import *
|
||||||
|
from logs import *
|
||||||
|
from xbox import *
|
||||||
|
import time
|
||||||
|
|
||||||
|
# DEBUG
|
||||||
|
LEGS_LOG_LEVEL = logging.INFO
|
||||||
|
CONTROLLER_LOG_LEVEL = logging.INFO
|
||||||
|
# Variables configurations
|
||||||
|
|
||||||
l1h = 0.049
|
l1h = 0.049
|
||||||
l1v = 0.032
|
l1v = 0.032
|
||||||
l1 = l1h
|
l1 = l1h # this is not the real distance as it's not the one needed to calculate position.
|
||||||
|
|
||||||
|
# length between motor 2 and motor 3.
|
||||||
l2h = 0.0605
|
l2h = 0.0605
|
||||||
l2v = 0.02215
|
l2v = 0.02215
|
||||||
l2 = sqrt(l2h ** 2 + l2v ** 2)
|
l2 = sqrt(l2h ** 2 + l2v ** 2)
|
||||||
|
|
||||||
|
# length between motor 3 and end of the leg.
|
||||||
l3h = 0.012
|
l3h = 0.012
|
||||||
l3v = 0.093
|
l3v = 0.093
|
||||||
l3 = sqrt(l3h ** 2 + l3v ** 2)
|
l3 = sqrt(l3h ** 2 + l3v ** 2)
|
||||||
|
|
||||||
|
# offset of the 'head', the legs isolated at each end.
|
||||||
tete_x = 0.095
|
tete_x = 0.095
|
||||||
|
|
||||||
|
# offset of the legs at the side.
|
||||||
patte_y = 0.032
|
patte_y = 0.032
|
||||||
patte_x = 0.079
|
patte_x = 0.079
|
||||||
|
num_patte = 6
|
||||||
|
|
||||||
|
# Logs functions
|
||||||
|
legsLogger = setup_logger("legs", LEGS_LOG_LEVEL)
|
||||||
|
controllerLogger = setup_logger("Controller", CONTROLLER_LOG_LEVEL)
|
||||||
|
|
||||||
|
# Initialize controller
|
||||||
|
xbox = Xbox(controllerLogger)
|
||||||
|
CONTROLLER_MODE = xbox.initialized
|
||||||
|
|
||||||
|
|
||||||
|
def interpol2(point2, point1, t):
|
||||||
|
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 inverse(x, y, z):
|
def inverse(x, y, z):
|
||||||
"""
|
"""
|
||||||
python simulator.py -m inverse
|
|
||||||
|
|
||||||
Le robot est figé en l'air, on ne contrôle qu'une patte
|
|
||||||
|
|
||||||
Reçoit en argument une position cible (x, y, z) pour le bout de la patte, et produit les angles
|
|
||||||
(alpha, beta, gamma) pour que la patte atteigne cet objectif
|
|
||||||
|
|
||||||
- Sliders: la position cible x, y, z du bout de la patte
|
|
||||||
- Entrée: x, y, z, une position cible dans le repère de la patte (mètres), provenant du slider
|
|
||||||
- Sortie: un tableau contenant les 3 positions angulaires cibles (en radians)
|
|
||||||
"""
|
"""
|
||||||
# Dimensions (m)
|
# Dimensions (m)
|
||||||
z += l1v
|
z += l1v
|
||||||
@ -112,53 +80,9 @@ def inverse(x, y, z):
|
|||||||
# return [0, angle1 , angle1 -pi/2 + atan(l3h/l3v)]
|
# return [0, angle1 , angle1 -pi/2 + atan(l3h/l3v)]
|
||||||
|
|
||||||
|
|
||||||
def draw(t):
|
|
||||||
"""
|
|
||||||
python simulator.py -m draw
|
|
||||||
|
|
||||||
Le robot est figé en l'air, on ne contrôle qu'une patte
|
|
||||||
|
|
||||||
Le but est, à partir du temps donné, de suivre une trajectoire de triangle. Pour ce faire, on
|
|
||||||
utilisera une interpolation linéaire entre trois points, et la fonction inverse précédente.
|
|
||||||
|
|
||||||
- Entrée: t, le temps (secondes écoulées depuis le début)
|
|
||||||
- Sortie: un tableau contenant les 3 positions angulaires cibles (en radians)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def interpol(x2, y2, z2, x1, y1, z1, t):
|
|
||||||
return t * x1 + (1 - t) * x2, t * y1 + (1 - t) * y2, t * z1 + (1 - t) * z2
|
|
||||||
|
|
||||||
p1 = [0.15, 0, 0]
|
|
||||||
p2 = [0.1, 0.1, 0]
|
|
||||||
p3 = [0.1, 0, 0.05]
|
|
||||||
|
|
||||||
positions = [p1, p2, p3]
|
|
||||||
|
|
||||||
ratio = (t % 1)
|
|
||||||
partie = floor((t % 3))
|
|
||||||
partie2 = (partie + 1) % 3
|
|
||||||
# print(f"partie: {partie}, partie2: {partie2}")
|
|
||||||
wanted_origin_x, wanted_origin_y, wanted_origin_z = positions[partie][0], positions[partie][1], positions[partie][
|
|
||||||
2],
|
|
||||||
wanted_dest_x, wanted_dest_y, wanted_dest_z = positions[partie2][0], positions[partie2][1], positions[partie2][2],
|
|
||||||
# print(wanted_origin_x, wanted_origin_y, wanted_origin_z)
|
|
||||||
# print(wanted_dest_x, wanted_dest_y, wanted_dest_z)
|
|
||||||
# print(t)
|
|
||||||
wanted_x, wanted_y, wanted_z = interpol(wanted_origin_x, wanted_origin_y, wanted_origin_z, wanted_dest_x,
|
|
||||||
wanted_dest_y, wanted_dest_z, ratio)
|
|
||||||
|
|
||||||
return inverse(wanted_x, wanted_y, wanted_z)
|
|
||||||
|
|
||||||
|
|
||||||
def legs(targets_robot):
|
def legs(targets_robot):
|
||||||
"""
|
"""
|
||||||
python simulator.py -m legs
|
takes a list of target and offsets it to be in the legs referential
|
||||||
|
|
||||||
Le robot est figé en l'air, on contrôle toute les pattes
|
|
||||||
|
|
||||||
- Sliders: les 12 coordonnées (x, y, z) du bout des 4 pattes
|
|
||||||
- Entrée: des positions cibles (tuples (x, y, z)) pour le bout des 4 pattes
|
|
||||||
- Sortie: un tableau contenant les 12 positions angulaires cibles (radian) pour les moteurs
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
targets = [0] * 18
|
targets = [0] * 18
|
||||||
@ -187,25 +111,13 @@ def legs(targets_robot):
|
|||||||
return targets
|
return targets
|
||||||
|
|
||||||
|
|
||||||
def interpol2(point2, point1, t):
|
|
||||||
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 walkV1(t, speed_x, speed_y, speed_rotation):
|
def walkV1(t, speed_x, speed_y, speed_rotation):
|
||||||
"""
|
max_slider = 0.200
|
||||||
python simulator.py -m walk
|
xboxdata = xbox.get_data()
|
||||||
|
print(xboxdata)
|
||||||
|
speed_x = max_slider * xboxdata["x1"]
|
||||||
|
speed_y = max_slider * xboxdata["y1"]
|
||||||
|
|
||||||
Le but est d'intégrer tout ce que nous avons vu ici pour faire marcher le robot
|
|
||||||
|
|
||||||
- Sliders: speed_x, speed_y, speed_rotation, la vitesse cible du robot
|
|
||||||
- Entrée: t, le temps (secondes écoulées depuis le début)
|
|
||||||
speed_x, speed_y, et speed_rotation, vitesses cibles contrôlées par les sliders
|
|
||||||
- Sortie: un tableau contenant les 12 positions angulaires cibles (radian) pour les moteurs
|
|
||||||
"""
|
|
||||||
# t = t*speed_x * 20
|
|
||||||
num_patte = 6
|
|
||||||
slider_max = 0.200
|
slider_max = 0.200
|
||||||
|
|
||||||
neutral_position = np.array([
|
neutral_position = np.array([
|
||||||
|
47
logs.py
Normal file
47
logs.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
class ColorFormatter(logging.Formatter):
|
||||||
|
"""Custom formatter with colored output based on log level"""
|
||||||
|
|
||||||
|
# ANSI color codes
|
||||||
|
GREY = "\x1b[38;21m"
|
||||||
|
GREEN = "\x1b[92m"
|
||||||
|
YELLOW = "\x1b[93m"
|
||||||
|
RED = "\x1b[91m"
|
||||||
|
BOLD_RED = "\x1b[31;1m"
|
||||||
|
RESET = "\x1b[0m"
|
||||||
|
|
||||||
|
# Format including function name
|
||||||
|
FORMAT = "%(asctime)s | %(funcName)s | %(message)s"
|
||||||
|
|
||||||
|
FORMATS = {
|
||||||
|
logging.DEBUG: GREY + FORMAT + RESET,
|
||||||
|
logging.INFO: GREEN + FORMAT + RESET,
|
||||||
|
logging.WARNING: YELLOW + FORMAT + RESET,
|
||||||
|
logging.ERROR: RED + FORMAT + RESET,
|
||||||
|
logging.CRITICAL: BOLD_RED + FORMAT + RESET
|
||||||
|
}
|
||||||
|
|
||||||
|
def format(self, record):
|
||||||
|
log_format = self.FORMATS.get(record.levelno)
|
||||||
|
formatter = logging.Formatter(log_format)
|
||||||
|
return formatter.format(record)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logger(name, level=logging.INFO):
|
||||||
|
"""Set up a logger with the custom color formatter"""
|
||||||
|
logger = logging.getLogger(name)
|
||||||
|
logger.setLevel(level)
|
||||||
|
|
||||||
|
# Create console handler
|
||||||
|
console_handler = logging.StreamHandler()
|
||||||
|
console_handler.setLevel(level)
|
||||||
|
|
||||||
|
# Add formatter to console handler
|
||||||
|
console_handler.setFormatter(ColorFormatter())
|
||||||
|
|
||||||
|
# Add console handler to logger
|
||||||
|
logger.addHandler(console_handler)
|
||||||
|
|
||||||
|
return logger
|
50
xbox.py
Normal file
50
xbox.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import pygame
|
||||||
|
|
||||||
|
|
||||||
|
class Xbox:
|
||||||
|
def __init__(self, controllerLogger):
|
||||||
|
|
||||||
|
pygame.init()
|
||||||
|
self.controllers = []
|
||||||
|
for i in range(0, pygame.joystick.get_count()):
|
||||||
|
self.controllers.append(pygame.joystick.Joystick(i))
|
||||||
|
self.controllers[-1].init()
|
||||||
|
controllerLogger.info(f"Detected controller {self.controllers[-1].get_name()}")
|
||||||
|
|
||||||
|
if len(self.controllers) == 0:
|
||||||
|
controllerLogger.critical("No controllers detected. Can't initialize remote control.")
|
||||||
|
self.initialized = True
|
||||||
|
else:
|
||||||
|
self.initialized = False
|
||||||
|
self.data = {"x1": 0, "x2": 0, "y1": 0, "y2": 0, "up": 0, "down": 0, "left": 0, "right": 0, "r1": 0, "r2": 0,
|
||||||
|
"r3": 0,
|
||||||
|
"l1": 0, "l2": 0, "l3": 0}
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
for event in pygame.event.get():
|
||||||
|
event = dict(event.dict)
|
||||||
|
keys = event.keys()
|
||||||
|
try:
|
||||||
|
if "axis" in keys:
|
||||||
|
axis = event["axis"]
|
||||||
|
if axis in [1, 4]:
|
||||||
|
value = -event["value"]
|
||||||
|
if abs(value) < 0.1:
|
||||||
|
value = 0
|
||||||
|
self.data[{0: "x1", 1: "y1", 4: "y2", 3: "x2", 5: "r2", 2: "l2"}[event["axis"]]] = value
|
||||||
|
else:
|
||||||
|
value = event["value"]
|
||||||
|
if abs(value) < 0.1:
|
||||||
|
value = 0
|
||||||
|
self.data[{0: "x1", 1: "y1", 4: "y2", 3: "x2", 5: "r2", 2: "l2"}[event["axis"]]] = value
|
||||||
|
elif "button" in keys:
|
||||||
|
# TODO
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print(event)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(event)
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
return self.data
|
Loading…
x
Reference in New Issue
Block a user