cleaning up

This commit is contained in:
apirrone 2025-03-17 11:39:29 +01:00
parent 1bc8ba2d1f
commit cdfb571479
24 changed files with 9 additions and 2855 deletions

View file

@ -21,3 +21,12 @@ class FeetContacts:
if GPIO.input(RIGHT_FOOT_PIN) == GPIO.LOW: if GPIO.input(RIGHT_FOOT_PIN) == GPIO.LOW:
right = True right = True
return np.array([left, right]) return np.array([left, right])
if __name__ == "__main__":
import time
feet_contacts = FeetContacts()
while True:
print(feet_contacts.get())
time.sleep(0.05)

File diff suppressed because it is too large Load diff

View file

@ -1,120 +0,0 @@
from pypot.feetech import FeetechSTS3215IO
import time
import numpy as np
from threading import Thread
class FeetechPWMControl:
def __init__(self, ids, init_pos_rad, usb_port="/dev/ttyACM0"):
self.io = FeetechSTS3215IO(
usb_port,
baudrate=1000000,
use_sync_read=True,
)
self.ids = ids
self.io.set_mode({id: 2 for id in self.ids})
self.kps = np.ones(len(self.ids)) * 32 # default kp
self.init_pos_rad = init_pos_rad
self.init_pos_deg = np.rad2deg(self.init_pos_rad)
self.control_freq = 200 # Hz
self.goal_positions = [0] * len(self.ids)
self.goal_positions = self.init_pos_deg
self.present_positions = [0] * len(self.ids)
self.last_positions = [0] * len(self.ids)
self.present_speeds = [0] * len(self.ids)
self.speed_decimation = 2
self.speed_decimation_index = 0
self.last_t = time.time()
Thread(target=self.update, daemon=True).start()
def set_kps(self, kps):
self.kps = np.array(kps)
def disable_torque(self):
self.io.set_mode({id: 0 for id in self.ids})
self.io.disable_torque(self.ids)
# def enable_torque(self):
# self.io.enable_torque(self.ids)
# self.io.set_mode({id: 2 for id in self.ids})
def freeze(self):
present_position = list(self.io.get_present_position(self.ids))
print(present_position)
self.io.set_goal_position(
{id: present_position[i] for i, id in enumerate(self.ids)}
)
self.io.set_mode({id: 0 for id in self.ids})
self.io.enable_torque(self.ids)
def update(self):
while True:
s = time.time()
try:
self.present_positions = self.io.get_present_position(self.ids)
# self.present_speeds = self.io.get_present_speed(self.ids)
except Exception as e:
print(e)
continue
if len(self.present_positions) != len(self.ids):
print("ERROR : present_positions and ids do not have the same length")
time.sleep(1 / self.control_freq)
continue
errors = np.array(self.goal_positions) - np.array(self.present_positions)
pwms = self.kps * errors
pwms = np.int16(pwms)
pwms = np.clip(pwms, -1000, 1000)
pwm_magnitudes = abs(pwms)
direction_bits = [1 if pwm >= 0 else 0 for pwm in pwms]
goal_times = [
(direction_bits[i] << 10) | pwm_magnitudes[i]
for i in range(len(pwm_magnitudes))
]
try:
self.io.set_goal_time({id: goal_times[i] for i, id in enumerate(self.ids)})
except Exception as e:
print(e)
continue
if self.speed_decimation_index % self.speed_decimation == 0:
self.present_speeds = (
np.array(self.present_positions) - np.array(self.last_positions)
) / (time.time() - self.last_t)
self.last_positions = np.array(self.present_positions).copy()
self.last_t = time.time()
took = time.time() - s
# print("Took : ", np.around(took, 3), ". Budget : ", np.around(1/self.control_freq, 3), "diff : ", ((1/self.control_freq - took)))
# if (1 / self.control_freq - took) < 0:
# print(
# "Low level control budget exceded by ",
# np.around(took - 1 / self.control_freq, 3),
# )
time.sleep(max(0, (1 / self.control_freq - took)))
self.speed_decimation_index += 1
if __name__ == "__main__":
ids = [1, 2]
pwm_control = FeetechPWMControl(ids)
pwm_control.enable_torque()
pwm_control.set_kps([32, 32])
pwm_control.goal_positions = [-90, -90]
try:
while True:
pwm_control.goal_positions = [90, 90]
time.sleep(1)
pwm_control.goal_positions = [-90, -90]
time.sleep(1)
except KeyboardInterrupt:
pwm_control.disable_torque()

View file

@ -1,111 +0,0 @@
import rustypot
import time
import numpy as np
from threading import Thread
class FeetechPWMControl:
def __init__(self, ids, init_pos_rad, usb_port="/dev/ttyACM0"):
self.io = rustypot.feetech(usb_port, 1000000)
self.ids = ids
self.io.set_mode(self.ids, 2)
self.kps = np.ones(len(self.ids)) * 32 # default kp
self.init_pos_rad = init_pos_rad
self.init_pos_deg = np.rad2deg(self.init_pos_rad)
self.control_freq = 100 # Hz
self.goal_positions = [0] * len(self.ids)
self.goal_positions = self.init_pos_deg
self.present_positions = [0] * len(self.ids)
self.last_positions = [0] * len(self.ids)
self.present_speeds = [0] * len(self.ids)
self.speed_decimation = 2
self.speed_decimation_index = 0
self.last_t = time.time()
Thread(target=self.update, daemon=True).start()
def set_kps(self, kps):
self.kps = np.array(kps)
def disable_torque(self):
self.io.set_mode(self.ids, 0)
self.io.disable_torque(self.ids)
def freeze(self):
present_position = list(self.io.read_present_position(self.ids))
self.io.write_goal_position(self.ids, present_position)
self.io.set_mode(self.ids, 0)
def update(self):
while True:
s = time.time()
try:
self.present_positions = np.rad2deg(self.io.read_present_position(self.ids))
# self.present_speeds = self.io.get_present_speed(self.ids)
except Exception as e:
print(e)
continue
if len(self.present_positions) != len(self.ids):
print("ERROR : present_positions and ids do not have the same length")
time.sleep(1 / self.control_freq)
continue
errors = np.array(self.goal_positions) - np.array(self.present_positions)
pwms = self.kps * errors
pwms = np.int16(pwms)
pwms = np.clip(pwms, -1000, 1000)
pwm_magnitudes = abs(pwms)
direction_bits = [1 if pwm >= 0 else 0 for pwm in pwms]
goal_times = [
(direction_bits[i] << 10) | pwm_magnitudes[i]
for i in range(len(pwm_magnitudes))
]
try:
self.io.set_goal_time(self.ids, goal_times)
# self.io.set_goal_time({id: goal_times[i] for i, id in enumerate(self.ids)})
except Exception as e:
print(e)
continue
if self.speed_decimation_index % self.speed_decimation == 0:
self.present_speeds = (
np.array(self.present_positions) - np.array(self.last_positions)
) / (time.time() - self.last_t)
self.last_positions = np.array(self.present_positions).copy()
self.last_t = time.time()
took = time.time() - s
# print("Took : ", np.around(took, 3), ". Budget : ", np.around(1/self.control_freq, 3), "diff : ", ((1/self.control_freq - took)))
if (1 / self.control_freq - took) < 0:
print(
"Low level control budget exceded by ",
np.around(took - 1 / self.control_freq, 3),
)
time.sleep(max(0, (1 / self.control_freq - took)))
self.speed_decimation_index += 1
if __name__ == "__main__":
ids = [1, 2]
pwm_control = FeetechPWMControl(ids)
pwm_control.enable_torque()
pwm_control.set_kps([32, 32])
pwm_control.goal_positions = [-90, -90]
try:
while True:
pwm_control.goal_positions = [90, 90]
time.sleep(1)
pwm_control.goal_positions = [-90, -90]
time.sleep(1)
except KeyboardInterrupt:
pwm_control.disable_torque()

View file

@ -1,188 +0,0 @@
import time
from typing import List
import numpy as np
from mini_bdx_runtime.io_330 import Dxl330IO
class HWI:
def __init__(self, usb_port="/dev/ttyUSB1", baudrate=3000000):
self.dxl_io = Dxl330IO(usb_port, baudrate=baudrate, use_sync_read=True)
self.joints = {
"right_hip_yaw": 10,
"right_hip_roll": 11,
"right_hip_pitch": 12,
"right_knee": 13,
"right_ankle": 14,
"left_hip_yaw": 20,
"left_hip_roll": 21,
"left_hip_pitch": 22,
"left_knee": 23,
"left_ankle": 24,
"neck_pitch": 30,
"head_pitch": 31,
"head_yaw": 32,
}
self.init_pos = {
"right_hip_yaw": 0.001171696610228082,
"right_hip_roll": 0.006726989242258406,
"right_hip_pitch": 1.0129772861831692,
"right_knee": -1.4829304760981399,
"right_ankle": 0.6444901047812701,
"left_hip_yaw": -0.002853397830292128,
"left_hip_roll": 0.01626303761810685,
"left_hip_pitch": 1.0105624704499077,
"left_knee": -1.4865015965817336,
"left_ankle": 0.6504953719748071,
"neck_pitch": -0.17453292519943295,
"head_pitch": -0.17453292519943295,
"head_yaw": 0,
"left_antenna": 0,
"right_antenna": 0,
}
# self.joints_offsets = {
# "right_hip_yaw": -0.02,
# "right_hip_roll": 0,
# "right_hip_pitch": 0,
# "right_knee": -0.05,
# "right_ankle": -0.1,
# "left_hip_yaw": -0.05,
# "left_hip_roll": 0.05,
# "left_hip_pitch": 0.02,
# "left_knee": -0.08,
# "left_ankle": -0.1,
# "neck_pitch": 0,
# "head_pitch": 0.3,
# "head_yaw": 0,
# # "left_antenna": 0,
# # "right_antenna": 0,
# }
self.joints_offsets = {
"right_hip_yaw": 0.0,
"right_hip_roll": 0,
"right_hip_pitch": 0,
"right_knee": 0.0,
"right_ankle": 0.0,
"left_hip_yaw": 0.00,
"left_hip_roll": 0.00,
"left_hip_pitch": 0.00,
"left_knee": 0.00,
"left_ankle": 0.0,
"neck_pitch": 0,
"head_pitch": 0.0,
"head_yaw": 0,
# "left_antenna": 0,
# "right_antenna": 0,
}
self.init_pos = {
joint: position - offset
for joint, position, offset in zip(
self.init_pos.keys(),
self.init_pos.values(),
self.joints_offsets.values(),
)
}
# current based position : 0x5
self.dxl_io.set_operating_mode({id: 0x3 for id in self.joints.values()})
def set_pid(self, pid, joint_name):
self.dxl_io.set_pid_gain({self.joints[joint_name]: pid})
def set_pid_all(self, pid):
self.dxl_io.set_pid_gain({id: pid for id in self.joints.values()})
def set_low_torque(self):
self.dxl_io.set_pid_gain({id: [100, 0, 0] for id in self.joints.values()})
def set_high_torque(self):
# https://emanual.robotis.com/docs/en/dxl/x/xl330-m288/#position-pid-gain80-82-84-feedforward-1st2nd-gains88-90
# 128 P factor
# 16 D factor
self.dxl_io.set_pid_gain(
{id: [10 * 128, 0, int(0.5 * 16)] for id in self.joints.values()}
)
for name in ["neck_pitch", "head_pitch", "head_yaw"]:
self.dxl_io.set_pid_gain({self.joints[name]: [150, 0, 0]})
def turn_on(self):
# self.set_low_torque()
self.dxl_io.enable_torque(self.joints.values())
time.sleep(1)
# self.goto_zero()
self.set_position_all(self.init_pos)
time.sleep(1)
# self.set_high_torque()
def turn_off(self):
self.dxl_io.disable_torque(self.joints.values())
def goto_zero(self):
goal_dict = {joint: 0 for joint in self.joints.keys()}
self.set_position_all(goal_dict)
def set_position_all(self, joints_positions):
"""
joints_positions is a dictionary with joint names as keys and joint positions as values
Warning: expects radians
"""
ids_positions = {
self.joints[joint]: np.rad2deg(-position)
for joint, position in joints_positions.items()
}
# print(ids_positions)
self.dxl_io.set_goal_position(ids_positions)
def set_position(self, joint_name, position):
self.dxl_io.set_goal_position({self.joints[joint_name]: np.rad2deg(-position)})
def get_present_current(self, joint_name):
return self.dxl_io.get_present_current([self.joints[joint_name]])[0]
def get_voltage_all(self):
return self.dxl_io.get_present_input_voltage(self.joints.values())
def get_present_input_voltage(self, joint_name):
return self.dxl_io.get_present_input_voltage([self.joints[joint_name]])[0]
def get_current_all(self):
return self.dxl_io.get_present_current(self.joints.values())
def get_goal_current(self, joint_name):
return self.dxl_io.get_goal_current([self.joints[joint_name]])[0]
def get_current_limit(self, joint_name):
return self.dxl_io.get_current_limit([self.joints[joint_name]])[0]
def get_present_positions(self):
present_position = list(
np.around(
np.deg2rad((self.dxl_io.get_present_position(self.joints.values()))), 3
)
)
factor = np.ones(len(present_position)) * -1
return present_position * factor
def get_present_velocities(self, rad_s=True) -> List[float]:
"""
Returns the present velocities in rad/s or rev/min
"""
# rev/min
present_velocities = np.array(
self.dxl_io.get_present_velocity(self.joints.values())
)
if rad_s:
present_velocities = (2 * np.pi * present_velocities) / 60 # rad/s
factor = np.ones(len(present_velocities)) * -1
return list(present_velocities * factor)
def get_operating_modes(self):
return self.dxl_io.get_operating_mode(self.joints.values())

View file

@ -1,207 +0,0 @@
import time
from typing import List
import numpy as np
# from pypot.feetech import FeetechSTS3215IO
# from mini_bdx_runtime.feetech_pwm_control import FeetechPWMControl
from mini_bdx_runtime.feetech_pwm_control_rustypot import FeetechPWMControl
class HWI:
def __init__(self, usb_port="/dev/ttyACM0"):
# Order matters here
self.joints = {
"left_hip_yaw": 20,
"left_hip_roll": 21,
"left_hip_pitch": 22,
"left_knee": 23,
"left_ankle": 24,
"neck_pitch": 30,
"head_pitch": 31,
"head_yaw": 32,
"head_roll": 33,
# "left_antenna": None,
# "right_antenna": None,
"right_hip_yaw": 10,
"right_hip_roll": 11,
"right_hip_pitch": 12,
"right_knee": 13,
"right_ankle": 14,
}
self.zero_pos = {
"left_hip_yaw": 0,
"left_hip_roll": 0,
"left_hip_pitch": 0,
"left_knee": 0,
"left_ankle": 0,
"neck_pitch": 0,
"head_pitch": 0,
"head_yaw": 0,
"head_roll": 0,
# "left_antenna":0,
# "right_antenna":0,
"right_hip_yaw": 0,
"right_hip_roll": 0,
"right_hip_pitch": 0,
"right_knee": 0,
"right_ankle": 0,
}
self.init_pos = {
"left_hip_yaw": 0.002,
"left_hip_roll": 0.053,
"left_hip_pitch": -0.63,
"left_knee": 1.368,
"left_ankle": -0.784,
"neck_pitch": 0.0,
"head_pitch": 0.0,
"head_yaw": 0,
"head_roll": 0,
# "left_antenna": 0,
# "right_antenna": 0,
"right_hip_yaw": -0.003,
"right_hip_roll": -0.065,
"right_hip_pitch": 0.635,
"right_knee": 1.379,
"right_ankle": -0.796,
}
# self.init_pos = self.zero_pos # TODO REMOVE
# self.joints_offsets = {
# "left_hip_yaw": 0.07,
# "left_hip_roll": -0.1,
# "left_hip_pitch": 0.0,
# "left_knee": 0.05,
# "left_ankle": -0.1,
# "neck_pitch": 0.1,
# "head_pitch": 0.1,
# "head_yaw": 0,
# "head_roll": 0.1,
# # "left_antenna": 0,
# # "right_antenna": 0,
# "right_hip_yaw": -0.15,
# "right_hip_roll": 0.15,
# "right_hip_pitch": 0.05,
# "right_knee": -0.05,
# "right_ankle": -0.08,
# }
self.joints_offsets = {
"left_hip_yaw" : 0.084,
"left_hip_roll" : -0.112,
"left_hip_pitch" : -0.024,
"left_knee" : 0.005,
"left_ankle" : -0.09,
"neck_pitch" : 0.017,
"head_pitch" : 0.114,
"head_yaw" : -0.083,
"head_roll" : 0.072,
# "left_antenna": 0,
# "right_antenna": 0,
"right_hip_yaw" : -0.13499999999999998,
"right_hip_roll" : 0.205,
"right_hip_pitch" : 0.064,
"right_knee" : -0.027999999999999997,
"right_ankle" : -0.09799999999999999,
}
init_pos_with_offsets = {
joint: pos + self.joints_offsets[joint]
for joint, pos in self.init_pos.items()
}
self.control = FeetechPWMControl(
ids=list(self.joints.values()),
init_pos_rad=list(init_pos_with_offsets.values()),
usb_port=usb_port,
)
self.kps = np.ones(len(self.joints)) * 32 # default kp
self.low_torque_kps = np.ones(len(self.joints)) * 8 # default kp
def set_kps(self, kps):
self.kps = kps
self.control.set_kps(self.kps)
def turn_on(self):
self.control.set_kps(self.low_torque_kps)
print("turn on : low KPS set")
time.sleep(1)
self.set_position_all(self.init_pos)
print("turn on : init pos set")
time.sleep(1)
self.control.set_kps(self.kps)
print("turn on : high kps")
def turn_off(self):
self.control.disable_torque()
def freeze(self):
self.control.freeze()
def set_position_all(self, joints_positions):
"""
joints_positions is a dictionary with joint names as keys and joint positions as values
Warning: expects radians
"""
ids_positions = {
self.joints[joint]: np.rad2deg(position + self.joints_offsets[joint])
for joint, position in joints_positions.items()
}
self.control.goal_positions = list(ids_positions.values())
def get_present_positions(self, ignore=[]):
"""
Returns the present positions in radians
"""
# present_positions = np.deg2rad(
# self.control.io.get_present_position(self.joints.values())
# )
present_positions = np.deg2rad(self.control.present_positions)
present_positions = [
pos - self.joints_offsets[joint]
for joint, pos in zip(self.joints.keys(), present_positions)
if joint not in ignore
]
return np.array(np.around(present_positions, 3))
def get_present_velocities(self, rad_s=True, ignore=[]):
"""
Returns the present velocities in rad/s (default) or rev/min
"""
# deg/s
present_velocities = np.array(self.control.present_speeds)
present_velocities = [
vel for joint, vel in zip(self.joints.keys(), present_velocities) if joint not in ignore
]
# present_velocities = np.array(
# self.control.io.get_present_speed(self.joints.values())
# )
if rad_s:
present_velocities = np.deg2rad(present_velocities) # rad/s
return np.array(np.around(present_velocities, 3))
def get_present_voltages(self):
return np.array(self.control.io.get_present_voltage(self.joints.values())) * 0.1
# def get_present_velocities(self, rad_s=True):
# """
# Returns the present velocities in rad/s (default) or rev/min
# """
# # rev/min
# present_velocities = np.array(
# self.control.io.get_present_speed(self.joints.values())
# )
# if rad_s:
# present_velocities = (2 * np.pi * present_velocities) / 60 # rad/s
# return np.array(np.around(present_velocities, 3))

View file

@ -1,180 +0,0 @@
import time
from typing import List
import numpy as np
from pypot.feetech import FeetechSTS3215IO
class HWI:
def __init__(self, usb_port="/dev/ttyACM0", baudrate=3000000):
self.dxl_io = FeetechSTS3215IO(
usb_port,
baudrate=1000000,
use_sync_read=True,
)
self.joints = {
"left_hip_yaw": 20,
"left_hip_roll": 21,
"left_hip_pitch": 22,
"left_knee": 23,
"left_ankle": 24,
"neck_pitch": 30,
"head_pitch": 31,
"head_yaw": 32,
"head_roll": 33,
# "left_antenna": None,
# "right_antenna": None,
"right_hip_yaw": 10,
"right_hip_roll": 11,
"right_hip_pitch": 12,
"right_knee": 13,
"right_ankle": 14,
}
self.zero_pos = {
"left_hip_yaw": 0,
"left_hip_roll": 0,
"left_hip_pitch": 0,
"left_knee": 0,
"left_ankle": 0,
"neck_pitch": 0,
"head_pitch": 0,
"head_yaw": 0,
"head_roll": 0,
# "left_antenna":0,
# "right_antenna":0,
"right_hip_yaw": 0,
"right_hip_roll": 0,
"right_hip_pitch": 0,
"right_knee": 0,
"right_ankle": 0,
}
self.init_pos = {
"left_hip_yaw": 0.002,
"left_hip_roll": 0.053,
"left_hip_pitch": -0.63,
"left_knee": 1.368,
"left_ankle": -0.784,
"neck_pitch": 0.002,
"head_pitch": 0.0,
"head_yaw": 0,
"head_roll": 0,
# "left_antenna": 0,
# "right_antenna": 0,
"right_hip_yaw": -0.003,
"right_hip_roll": -0.065,
"right_hip_pitch": 0.635,
"right_knee": 1.379,
"right_ankle": -0.796,
}
# self.init_pos = self.zero_pos # TODO REMOVE
self.joints_offsets = {
"left_hip_yaw": 0.07,
"left_hip_roll": -0.1,
"left_hip_pitch": 0.0,
"left_knee": 0.05,
"left_ankle": -0.1,
"neck_pitch": 0.1,
"head_pitch": 0.1,
"head_yaw": 0,
"head_roll": 0.1,
# "left_antenna": 0,
# "right_antenna": 0,
"right_hip_yaw": -0.15,
"right_hip_roll": 0.07,
"right_hip_pitch": 0.05,
"right_knee": -0.05,
"right_ankle": -0.08,
}
def set_pid(self, pid, joint_name):
# TODO
pass
def set_pid_all(self, pid):
# TODO WEIRD THINGS HERE
# If I set 32 manually, it works, but if it comes from a variable, it doesn't.
# sometimes i get : ValueError: byte must be in range(0, 256)
# sometimes 32 becomes 76 somehow
# P = np.uint8(pid[0])
# I = np.uint8(pid[1])
# D = np.uint8(pid[2])
self.dxl_io.set_P_coefficient({id: 32 for id in self.joints.values()})
self.dxl_io.set_I_coefficient({id: 0 for id in self.joints.values()})
self.dxl_io.set_D_coefficient({id: 32 for id in self.joints.values()})
def get_pid_all(self):
Ps = self.dxl_io.get_P_coefficient(self.joints.values())
Is = self.dxl_io.get_I_coefficient(self.joints.values())
Ds = self.dxl_io.get_D_coefficient(self.joints.values())
print("Ps", Ps)
print("Is", Is)
print("Ds", Ds)
return Ps, Is, Ds
def turn_on(self):
self.dxl_io.enable_torque(self.joints.values())
self.dxl_io.set_mode({id: 0 for id in self.joints.values()})
# self.dxl_io.set_mode
self.dxl_io.set_acceleration({id: 16 for id in self.joints.values()})
time.sleep(1)
self.set_position_all(self.init_pos)
time.sleep(1)
for name, id in self.joints.items():
if "neck" in name or "head" in name:
self.dxl_io.set_acceleration({id: 32})
else:
self.dxl_io.set_acceleration({id: 254})
def turn_off(self):
self.dxl_io.disable_torque(self.joints.values())
def set_position_all(self, joints_positions):
"""
joints_positions is a dictionary with joint names as keys and joint positions as values
Warning: expects radians
"""
ids_positions = {
self.joints[joint]: np.rad2deg(position + self.joints_offsets[joint])
for joint, position in joints_positions.items()
}
self.dxl_io.set_goal_position(ids_positions)
def set_position(self, joint_name, position):
self.dxl_io.set_goal_position({self.joints[joint_name]: np.rad2deg(-position)})
def get_present_positions(self):
"""
Returns the present positions in radians
"""
present_positions = np.deg2rad(
self.dxl_io.get_present_position(self.joints.values())
)
present_positions = [
pos - self.joints_offsets[joint]
for joint, pos in zip(self.joints.keys(), present_positions)
]
return np.array(np.around(present_positions, 3))
def get_present_velocities(self, rad_s=True):
"""
Returns the present velocities in rad/s (default) or rev/min
"""
# rev/min
present_velocities = np.array(
self.dxl_io.get_present_speed(self.joints.values())
)
if rad_s:
present_velocities = (2 * np.pi * present_velocities) / 60 # rad/s
return np.array(np.around(present_velocities, 3))

View file

@ -1,139 +0,0 @@
from mini_bdx_runtime.feetech import (
FeetechMotorsBus,
convert_radians_to_steps,
convert_steps_to_radians,
configure,
)
import time
import numpy as np
# Everything is in radians here
class HWI:
def __init__(self, usb_port="/dev/ttyACM0"):
self.motors = {
"right_hip_yaw": (10, "sts3215"),
"right_hip_roll": (11, "sts3215"),
"right_hip_pitch": (12, "sts3215"),
"right_knee": (13, "sts3215"),
"right_ankle": (14, "sts3215"),
"left_hip_yaw": (20, "sts3215"),
"left_hip_roll": (21, "sts3215"),
"left_hip_pitch": (22, "sts3215"),
"left_knee": (23, "sts3215"),
"left_ankle": (24, "sts3215"),
# "neck_pitch": (30, "sts3215"),
# "head_pitch": (31, "sts3215"),
# "head_yaw": (32, "sts3215"),
}
self.joints_offsets = {
"right_hip_yaw": 0.0,
"right_hip_roll": 0.0,
"right_hip_pitch": 0.0,
"right_knee": 0.0,
"right_ankle": 0.0,
"left_hip_yaw": 0.0,
"left_hip_roll": 0.0,
"left_hip_pitch": 0.0,
"left_knee": 0.0,
"left_ankle": 0.0,
# "neck_pitch": 0.0,
# "head_pitch": 0.0,
# "head_yaw": 0.0,
}
self.joints_sign = {
"right_hip_yaw": -1,
"right_hip_roll": -1,
"right_hip_pitch": 1,
"right_knee": -1,
"right_ankle": -1,
"left_hip_yaw": -1,
"left_hip_roll": -1,
"left_hip_pitch": 1,
"left_knee": -1,
"left_ankle": -1,
# "neck_pitch": -1,
# "head_pitch": -1,
# "head_yaw": -1,
}
self.init_pos = {
"right_hip_yaw": 0.001171696610228082,
"right_hip_roll": 0.006726989242258406,
"right_hip_pitch": 1.0129772861831692,
"right_knee": -1.4829304760981399,
"right_ankle": 0.6444901047812701,
"left_hip_yaw": -0.002853397830292128,
"left_hip_roll": 0.01626303761810685,
"left_hip_pitch": -1.0105624704499077,
"left_knee": -1.4865015965817336,
"left_ankle": 0.6504953719748071,
# "neck_pitch": -0.17453292519943295,
# "head_pitch": -0.17453292519943295,
# "head_yaw": 0,
}
self.zero_pos = {
"right_hip_yaw": 0,
"right_hip_roll": 0,
"right_hip_pitch": 0,
"right_knee": 0,
"right_ankle": 0,
"left_hip_yaw": 0,
"left_hip_roll": 0,
"left_hip_pitch": 0,
"left_knee": 0,
"left_ankle": 0,
# "neck_pitch": 0,
# "head_pitch": 0,
# "head_yaw": 0,
}
self.baudrate = 1000000
self.motors_bus = FeetechMotorsBus(port=usb_port, motors=self.motors)
self.motors_bus.connect()
configure(self.motors_bus)
# We add 180 to all dofs. They were mounted in a way that 180 degrees is the neutral position.
self.global_offset = np.deg2rad(180)
def enable_torque(self):
self.motors_bus.write("Torque_Enable", 1)
def disable_torque(self):
self.motors_bus.write("Torque_Enable", 0)
def turn_on(self):
self.enable_torque()
self.set_position_all(self.init_pos)
# self.set_position_all(self.zero_pos)
time.sleep(1)
def set_position_all(self, joints_positions: dict):
positions = np.array(list(joints_positions.values()))
signs = np.array(list(self.joints_sign.values()))
rads = positions * signs + self.global_offset
rads = list(rads)
steps = convert_radians_to_steps(rads, ["sts3215"])
self.motors_bus.write("Goal_Position", steps)
def get_position_all(self):
steps = self.motors_bus.read("Present_Position", self.motors)
rads = np.array(convert_steps_to_radians(steps, ["sts3215"]))
return rads - self.global_offset
# return rads * np.array(list(self.joints_sign.values()))# - self.global_offset
if __name__ == "__main__":
hwi = HWI()
hwi.turn_on()
# hwi.disable_torque()
# time.sleep(1)
# while True:
# print(hwi.get_position_all())
# time.sleep(0.1)

View file

@ -1,221 +0,0 @@
import pypot.dynamixel.conversion as conv
from pypot.dynamixel.io.abstract_io import AbstractDxlIO, _DxlAccess, _DxlControl
from pypot.dynamixel.protocol import v2 as v2
max_pos = 4096
max_deg = 360
max_current = 1750
def dxl_to_degree(value, model):
return round(((max_deg * float(value)) / (max_pos - 1)) - (max_deg / 2), 2)
def dxl_to_current(value, model):
if value > 0x7FFF:
value = value - 65536
return value
def current_to_dxl(value, model):
if value < 0:
value = value + 65536
return int(value)
def degree_to_dxl(value, model):
pos = int(round((max_pos - 1) * ((max_deg / 2 + float(value)) / max_deg), 0))
pos = min(max(pos, 0), max_pos - 1)
return pos
def dxl_to_velocity(value, model):
if value > 2 ** (4 * 8 - 1):
value = value - 2 ** (4 * 8)
return value * 0.229
class Dxl330IO(AbstractDxlIO):
_protocol = v2
controls = {
# EEPROM
"model": {
"address": 0x00,
"access": _DxlAccess.readonly,
"dxl_to_si": conv.dxl_to_model,
},
"firmware": {"address": 0x026, "length": 1, "access": _DxlAccess.readonly},
"id": {
"address": 0x07,
"length": 1,
"access": _DxlAccess.writeonly,
"setter_name": "change_id",
},
"baudrate": {
"address": 0x08,
"length": 1,
"access": _DxlAccess.writeonly,
"setter_name": "change_baudrate",
"si_to_dxl": conv.baudrate_to_dxl,
},
"return delay time": {
"address": 0x09,
"length": 1,
"dxl_to_si": conv.dxl_to_rdt,
"si_to_dxl": conv.rdt_to_dxl,
},
"angle limit": {
"address": 0x30,
"nb_elem": 2,
"dxl_to_si": lambda value, model: (
dxl_to_degree(value[0], model),
dxl_to_degree(value[1], model),
),
"si_to_dxl": lambda value, model: (
degree_to_dxl(value[0], model),
degree_to_dxl(value[1], model),
),
},
"control mode": {
"address": 0x10,
"length": 1,
"dxl_to_si": conv.dxl_to_control_mode,
"si_to_dxl": conv.control_mode_to_dxl,
},
"operating mode": {
"address": 0xB,
"length": 1,
},
"highest temperature limit": {
"address": 0x1F,
"length": 1,
"dxl_to_si": conv.dxl_to_temperature,
"si_to_dxl": conv.temperature_to_dxl,
},
"voltage limit": {
"address": 0x20,
"length": 1,
"nb_elem": 2,
"dxl_to_si": lambda value, model: (
conv.dxl_to_voltage(value[0], model),
conv.dxl_to_voltage(value[1], model),
),
"si_to_dxl": lambda value, model: (
conv.voltage_to_dxl(value[0], model),
conv.voltage_to_dxl(value[1], model),
),
},
"current limit": {
"address": 0x26,
"length": 2,
},
# RAM
"torque_enable": {
"address": 0x40,
"length": 1,
"dxl_to_si": conv.dxl_to_bool,
"si_to_dxl": conv.bool_to_dxl,
"getter_name": "is_torque_enabled",
"setter_name": "_set_torque_enable",
},
"LED": {
"address": 0x41,
"length": 1,
"dxl_to_si": conv.dxl_to_bool,
"si_to_dxl": conv.bool_to_dxl,
"setter_name": "_set_LED",
"getter_name": "is_led_on",
},
"LED color": {
"address": 0x19,
"length": 1,
"dxl_to_si": conv.dxl_to_led_color,
"si_to_dxl": conv.led_color_to_dxl,
},
"pid gain": {
"address": 0x50,
"length": 2,
"nb_elem": 3,
# "dxl_to_si": conv.dxl_to_pid,
# "si_to_dxl": conv.pid_to_dxl,
},
"goal position": {
"address": 0x74,
"length": 4,
"dxl_to_si": dxl_to_degree,
"si_to_dxl": degree_to_dxl,
},
"present velocity": {
"address": 0x80,
"length": 4,
"access": _DxlAccess.readonly,
"dxl_to_si": dxl_to_velocity,
},
"present position": {
"address": 0x84,
"length": 4,
"access": _DxlAccess.readonly,
"dxl_to_si": dxl_to_degree,
},
"present current": {
"address": 0x7E,
"length": 2,
"access": _DxlAccess.readonly,
"dxl_to_si": dxl_to_current,
},
"goal current": {
"address": 0x66,
"length": 2,
"dxl_to_si": dxl_to_current,
"si_to_dxl": current_to_dxl,
},
"present input voltage": {
"address": 0x90,
"length": 2,
"access": _DxlAccess.readonly,
"dxl_to_si": conv.dxl_to_voltage,
},
"present temperature": {
"address": 0x92,
"length": 1,
"access": _DxlAccess.readonly,
"dxl_to_si": conv.dxl_to_temperature,
},
}
def _add_control(
name,
address,
length=2,
nb_elem=1,
access=_DxlAccess.readwrite,
models=[
"XL-330",
],
dxl_to_si=lambda val, model: val,
si_to_dxl=lambda val, model: val,
getter_name=None,
setter_name=None,
):
control = _DxlControl(
name,
address,
length,
nb_elem,
access,
models,
dxl_to_si,
si_to_dxl,
getter_name,
setter_name,
)
Dxl330IO._generate_accessors(control)
for name, args in controls.items():
_add_control(name, **args)

View file

@ -1,214 +0,0 @@
import time
from typing import List
import numpy as np
# from pypot.feetech import FeetechSTS3215IO
# from mini_bdx_runtime.feetech_pwm_control import FeetechPWMControl
# from mini_bdx_runtime.feetech_pwm_control_rustypot import FeetechPWMControl
import rustypot
class HWI:
def __init__(self, usb_port="/dev/ttyACM0"):
# Order matters here
self.joints = {
"left_hip_yaw": 20,
"left_hip_roll": 21,
"left_hip_pitch": 22,
"left_knee": 23,
"left_ankle": 24,
"neck_pitch": 30,
"head_pitch": 31,
"head_yaw": 32,
"head_roll": 33,
# "left_antenna": None,
# "right_antenna": None,
"right_hip_yaw": 10,
"right_hip_roll": 11,
"right_hip_pitch": 12,
"right_knee": 13,
"right_ankle": 14,
}
self.zero_pos = {
"left_hip_yaw": 0,
"left_hip_roll": 0,
"left_hip_pitch": 0,
"left_knee": 0,
"left_ankle": 0,
"neck_pitch": 0,
"head_pitch": 0,
"head_yaw": 0,
"head_roll": 0,
# "left_antenna":0,
# "right_antenna":0,
"right_hip_yaw": 0,
"right_hip_roll": 0,
"right_hip_pitch": 0,
"right_knee": 0,
"right_ankle": 0,
}
self.init_pos = {
"left_hip_yaw": 0.002,
"left_hip_roll": 0.053,
"left_hip_pitch": -0.63,
"left_knee": 1.368,
"left_ankle": -0.784,
"neck_pitch": 0.0,
"head_pitch": 0.0,
"head_yaw": 0,
"head_roll": 0,
# "left_antenna": 0,
# "right_antenna": 0,
"right_hip_yaw": -0.003,
"right_hip_roll": -0.065,
"right_hip_pitch": 0.635,
"right_knee": 1.379,
"right_ankle": -0.796,
}
# self.init_pos = self.zero_pos # TODO REMOVE
# self.joints_offsets = {
# "left_hip_yaw": 0.07,
# "left_hip_roll": -0.1,
# "left_hip_pitch": 0.0,
# "left_knee": 0.05,
# "left_ankle": -0.1,
# "neck_pitch": 0.1,
# "head_pitch": 0.1,
# "head_yaw": 0,
# "head_roll": 0.1,
# # "left_antenna": 0,
# # "right_antenna": 0,
# "right_hip_yaw": -0.15,
# "right_hip_roll": 0.15,
# "right_hip_pitch": 0.05,
# "right_knee": -0.05,
# "right_ankle": -0.08,
# }
self.joints_offsets = {
"left_hip_yaw": 0.084,
"left_hip_roll": -0.112,
"left_hip_pitch": -0.024,
"left_knee": 0.005,
"left_ankle": -0.09,
"neck_pitch": 0.017,
"head_pitch": 0.114,
"head_yaw": -0.083,
"head_roll": 0.072,
# "left_antenna": 0,
# "right_antenna": 0,
"right_hip_yaw": -0.13499999999999998,
"right_hip_roll": 0.205,
"right_hip_pitch": 0.064,
"right_knee": -0.027999999999999997,
"right_ankle": -0.09799999999999999,
}
init_pos_with_offsets = {
joint: np.rad2deg(pos + self.joints_offsets[joint])
for joint, pos in self.init_pos.items()
}
# self.control = FeetechPWMControl(
# ids=list(self.joints.values()),
# init_pos_rad=list(init_pos_with_offsets.values()),
# usb_port=usb_port,
# )
self.kps = np.ones(len(self.joints)) * 32 # default kp
self.low_torque_kps = np.ones(len(self.joints)) * 8 # default kp
self.control = rustypot.FeetechController(
usb_port, 1000000, 100, list(self.joints.values()), list(self.kps), list(init_pos_with_offsets.values())
)
def set_kps(self, kps):
self.kps = kps
self.control.set_new_kps(self.kps)
def turn_on(self):
self.control.set_new_kps(self.low_torque_kps)
print("turn on : low KPS set")
time.sleep(1)
self.set_position_all(self.init_pos)
print("turn on : init pos set")
time.sleep(1)
self.control.set_new_kps(self.kps)
print("turn on : high kps")
def turn_off(self):
self.control.disable_torque()
def freeze(self):
self.control.freeze()
def set_position_all(self, joints_positions):
"""
joints_positions is a dictionary with joint names as keys and joint positions as values
Warning: expects radians
"""
ids_positions = {
self.joints[joint]: np.rad2deg(position + self.joints_offsets[joint])
for joint, position in joints_positions.items()
}
self.control.set_new_target(list(ids_positions.values()))
# self.control.goal_positions = list(ids_positions.values())
def get_present_positions(self, ignore=[]):
"""
Returns the present positions in radians
"""
# present_positions = np.deg2rad(
# self.control.io.get_present_position(self.joints.values())
# )
present_positions = np.deg2rad(self.control.get_present_position())
present_positions = [
pos - self.joints_offsets[joint]
for joint, pos in zip(self.joints.keys(), present_positions)
if joint not in ignore
]
return np.array(np.around(present_positions, 3))
def get_present_velocities(self, rad_s=True, ignore=[]):
"""
Returns the present velocities in rad/s (default) or rev/min
"""
# deg/s
present_velocities = np.array(self.control.get_current_speed())
present_velocities = [
vel
for joint, vel in zip(self.joints.keys(), present_velocities)
if joint not in ignore
]
# present_velocities = np.array(
# self.control.io.get_present_speed(self.joints.values())
# )
if rad_s:
present_velocities = np.deg2rad(present_velocities) # rad/s
return np.array(np.around(present_velocities, 3))
# def get_present_voltages(self):
# return np.array(self.control.io.get_present_voltage(self.joints.values())) * 0.1
# def get_present_velocities(self, rad_s=True):
# """
# Returns the present velocities in rad/s (default) or rev/min
# """
# # rev/min
# present_velocities = np.array(
# self.control.io.get_present_speed(self.joints.values())
# )
# if rad_s:
# present_velocities = (2 * np.pi * present_velocities) / 60 # rad/s
# return np.array(np.around(present_velocities, 3))

View file

@ -1,31 +0,0 @@
from pypot.feetech import FeetechSTS3215IO
io = FeetechSTS3215IO(
"/dev/ttyACM0",
baudrate=1000000,
use_sync_read=True,
)
joints = {
"left_hip_yaw": 20,
"left_hip_roll": 21,
"left_hip_pitch": 22,
"left_knee": 23,
"left_ankle": 24,
"neck_pitch": 30,
"head_pitch": 31,
"head_yaw": 32,
"head_roll": 33,
# "left_antenna": None,
# "right_antenna": None,
"right_hip_yaw": 10,
"right_hip_roll": 11,
"right_hip_pitch": 12,
"right_knee": 13,
"right_ankle": 14,
}
voltages = io.get_present_voltage(list(joints.values()))
for i, name in enumerate(joints.keys()):
print(name, round(voltages[i] * 0.1, 2), "V")

View file

@ -1,35 +0,0 @@
import numpy as np
import RPi.GPIO as GPIO
import time
# from time import sleep
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(12, GPIO.OUT)
pwm = GPIO.PWM(12, 50)
pwm.start(0) # Start the servo with 0 duty cycle ( at 0 deg position )
# pwm.ChangeDutyCycle(0)
# time.sleep(1)
# pwm.stop(0) # Stop the servo with 0 duty cycle ( at 0 deg position )
# GPIO.cleanup() # Clean up all the ports we've used.
start = time.time()
while True:
if time.time() - start > 3:
break
target_pwm = 10.0*np.sin(2*np.pi*1*time.time()) + 10
pwm.ChangeDutyCycle(target_pwm)
time.sleep(0.02)
# # Set up the PWM on pin #16 at 50Hz
# pwm.ChangeDutyCycle(5) # Tells the servo to turn to the left ( -90 deg position )
# sleep(0.5) # Tells the servo to Delay for 5sec
# pwm.ChangeDutyCycle(7.5) # Tells the servo to turn to the neutral position ( at 0 deg position )
# sleep(0.5) # Tells the servo to Delay for 5sec
# pwm.ChangeDutyCycle(10) # Tells the servo to turn to the right ( +90 deg position )
# sleep(0.5) # Tells the servo to Delay for 5sec
pwm.stop(0) # Stop the servo with 0 duty cycle ( at 0 deg position )
GPIO.cleanup() # Clean up all the ports we've used.

View file

@ -2,9 +2,6 @@
Sets up the robot in init position, you control the head with the xbox controller Sets up the robot in init position, you control the head with the xbox controller
""" """
# from pypot.feetech import FeetechSTS3215IO
# from mini_bdx_runtime.hwi_feetech_pypot import HWI
from mini_bdx_runtime.rustypot_position_hwi import HWI from mini_bdx_runtime.rustypot_position_hwi import HWI
from mini_bdx_runtime.eyes import Eyes from mini_bdx_runtime.eyes import Eyes
import time import time

View file

@ -1,88 +0,0 @@
import socket
import time
import numpy as np
import pickle
from queue import Queue
from threading import Thread
from scipy.spatial.transform import Rotation as R
from FramesViewer.viewer import Viewer
from mini_bdx_runtime.rl_utils import quat_rotate_inverse
class IMUClient:
def __init__(self, host, port=1234, freq=30):
self.host = host
self.port = port
self.freq = freq
self.client_socket = socket.socket()
self.connected = False
while not self.connected:
try:
self.client_socket.connect((self.host, self.port))
self.connected = True
except Exception as e:
print(e)
time.sleep(0.5)
self.imu_queue = Queue(maxsize=1)
self.last_imu = [0, 0, 0, 0]
Thread(target=self.imu_worker, daemon=True).start()
def imu_worker(self):
while True:
try:
data = self.client_socket.recv(1024) # receive response
data = pickle.loads(data)
self.imu_queue.put(data)
except:
print("missed imu")
time.sleep(1 / self.freq)
def get_imu(self):
try:
self.last_imu = self.imu_queue.get(False)
except:
pass
return self.last_imu
if __name__ == "__main__":
client = IMUClient("192.168.248.253")
fv = Viewer()
fv.start()
pose = np.eye(4)
pose[:3, 3] = [0.1, 0.1, 0.1]
projected_gravities = []
try:
while True:
quat = client.get_imu()
try:
rot_mat = R.from_quat(quat).as_matrix()
pose[:3, :3] = rot_mat
fv.pushFrame(pose, "aze")
# euler = R.from_quat(quat).as_euler("xyz")
# euler[2] = 0
# quat = R.from_euler("xyz", euler).as_quat()
projected_gravity = quat_rotate_inverse(quat, [0, 0, -1])
projected_gravities.append(projected_gravity)
except Exception as e:
print("error", e)
pass
time.sleep(1 / 30)
except KeyboardInterrupt:
pass
# plot projected_gravities [[x, y, z], [x, y, z], ...]
# from matplotlib import pyplot as plt
# projected_gravities = np.array(projected_gravities)
# plt.plot(projected_gravities)
# plt.show()

View file

@ -1,62 +0,0 @@
import socket
import time
import pickle
from mini_bdx_runtime.raw_imu import Imu
from threading import Thread
import time
import argparse
class IMUServer:
def __init__(self, imu=None):
self.host = "0.0.0.0"
self.port = 1234
self.server_socket = socket.socket()
self.server_socket.setsockopt(
socket.SOL_SOCKET, socket.SO_REUSEADDR, 1
) # enable address reuse
self.server_socket.bind((self.host, self.port))
if imu is None:
self.imu = Imu(50, user_pitch_bias=args.pitch_bias)
else:
self.imu = imu
self.stop = False
Thread(target=self.run, daemon=True).start()
def run(self):
while not self.stop:
self.server_socket.listen(1)
conn, address = self.server_socket.accept() # accept new connection
print("Connection from: " + str(address))
try:
while True:
data = self.imu.get_data()
data = pickle.dumps(data)
conn.send(data) # send data to the client
time.sleep(1 / 30)
except:
pass
self.server_socket.close()
print("thread closed")
time.sleep(1)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--pitch_bias", type=float, default=0, help="deg")
args = parser.parse_args()
imu_server = IMUServer()
try:
while True:
time.sleep(0.01)
except KeyboardInterrupt:
print("Closing server")
imu_server.stop = True
time.sleep(2)

View file

@ -1,39 +0,0 @@
import RPi.GPIO as GPIO #Importe la bibliothèque pour contrôler les GPIOs
import numpy as np
import time
GPIO.setmode(GPIO.BCM) # Use physical pin numbering
# GPIO.setmode(GPIO.BOARD) #Définit le mode de numérotation (Board)
GPIO.setwarnings(False) #On désactive les messages d'alerte
LED = 24 #Définit le numéro du port GPIO qui alimente la led
GPIO.setup(LED, GPIO.OUT) #Active le contrôle du GPIO
# state = GPIO.input(LED) #Lit l'état actuel du GPIO, vrai si allumé, faux si éteint
GPIO.output(LED, GPIO.HIGH) #On l'allume
clignottement_time = 0.1
cli_s = time.time()
low = False
while True:
if not low and np.random.rand() > 0.99:
print("cli")
GPIO.output(LED, GPIO.LOW)
cli_s = time.time()
low = True
if time.time() - cli_s > clignottement_time:
GPIO.output(LED, GPIO.HIGH)
low = False
time.sleep(0.01)
# if state : #Si GPIO allumé
# GPIO.output(LED, GPIO.LOW) #On léteint
# else : #Sinon
# GPIO.output(LED, GPIO.HIGH) #On l'allume

View file

@ -1,14 +0,0 @@
import pickle
imu_data = pickle.load(open("imu_data.pkl", "rb"))
gyros = imu_data["gyros"]
acceleros = imu_data["accels"]
import matplotlib.pyplot as plt
plt.plot(gyros)
plt.show()
plt.plot(acceleros)
plt.show()

View file

@ -1,62 +0,0 @@
import RPi.GPIO as GPIO
import time
class ServoController:
def __init__(self, pin1, pin2):
self.pin1 = pin1
self.pin2 = pin2
GPIO.setmode(GPIO.BCM)
GPIO.setup(self.pin1, GPIO.OUT)
GPIO.setup(self.pin2, GPIO.OUT)
# Create PWM objects for both servos (50Hz frequency)
self.pwm1 = GPIO.PWM(self.pin1, 50)
self.pwm2 = GPIO.PWM(self.pin2, 50)
self.pwm1.start(0)
self.pwm2.start(0)
def map_input_to_angle(self, value):
"""
Maps an input range of [-1, 1] to an angle range of [0°, 180°].
"""
return 90 + (value * 90) # Maps -1 to 0°, 0 to 90°, and 1 to 180°
def set_position(self, servo, value):
"""
Moves the servo based on an input value in the range [-1, 1].
:param servo: 1 for the first servo, 2 for the second servo
:param value: A float between -1 and 1
"""
if -1 <= value <= 1:
angle = self.map_input_to_angle(value)
duty = 2 + (angle / 18) # Convert angle to duty cycle (1ms-2ms)
if servo == 1:
self.pwm1.ChangeDutyCycle(duty)
elif servo == 2:
self.pwm2.ChangeDutyCycle(duty)
else:
print("Invalid servo number!")
# time.sleep(0.3) # Allow time for movement
else:
print("Invalid input! Enter a value between -1 and 1.")
def stop(self):
"""Stops PWM and cleans up GPIO."""
self.pwm1.stop()
self.pwm2.stop()
GPIO.cleanup()
# Initialize the ServoController for GPIO12 and GPIO13
servo_control = ServoController(pin1=12, pin2=13)
try:
while True:
servo_num = int(input("Enter servo number (1 or 2): "))
value = float(input("Enter position (-1 to 1): "))
servo_control.set_position(servo_num, value)
except KeyboardInterrupt:
print("Stopping servos...")
servo_control.stop()

View file

@ -1,75 +0,0 @@
''' pg_midi_sound101.py
play midi music files (also mp3 files) using pygame
tested with Python273/331 and pygame192 by vegaseat
'''
#code modified by James DeVito from here: https://www.daniweb.com/programming/software-development/code/454835/let-pygame-play-your-midi-or-mp3-files
import sys
import pygame as pg
import os
import time
def play_music(music_file):
'''
stream music with mixer.music module in blocking manner
this will stream the sound from disk while playing
'''
clock = pg.time.Clock()
try:
pg.mixer.music.load(music_file)
print("Music file {} loaded!".format(music_file))
except pygame.error:
print("File {} not found! {}".format(music_file, pg.get_error()))
return
pg.mixer.music.play()
# If you want to fade in the audio...
# for x in range(0,100):
# pg.mixer.music.set_volume(float(x)/100.0)
# time.sleep(.0075)
# # check if playback has finished
while pg.mixer.music.get_busy():
clock.tick(30)
freq = 44100 # audio CD quality
bitsize = -16 # unsigned 16 bit
channels = 1 # 1 is mono, 2 is stereo
buffer = 2048 # number of samples (experiment to get right sound)
pg.mixer.init(freq, bitsize, channels, buffer)
if len(sys.argv) > 1:
try:
user_volume = float(sys.argv[1])
except ValueError:
print("Volume argument invalid. Please use a float (0.0 - 1.0)")
pg.mixer.music.fadeout(1000)
pg.mixer.music.stop()
raise SystemExit
print("Playing at volume: " + str(user_volume)+ "\n")
pg.mixer.music.set_volume(user_volume)
mp3s = []
for file in os.listdir("."):
if file.endswith(".wav"):
mp3s.append(file)
print(mp3s)
for x in mp3s:
try:
play_music(x)
time.sleep(.25)
except KeyboardInterrupt:
# if user hits Ctrl/C then exit
# (works only in console mode)
pg.mixer.music.fadeout(1000)
pg.mixer.music.stop()
raise SystemExit
else:
print("Please specify volume as a float! (0.0 - 1.0)")

View file

@ -1,15 +0,0 @@
import RPi.GPIO as GPIO
LEFT_FOOT_PIN = 22
RIGHT_FOOT_PIN = 27
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BCM) # Use physical pin numbering
GPIO.setup(LEFT_FOOT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(RIGHT_FOOT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True: # Run forever
print("=")
if GPIO.input(LEFT_FOOT_PIN) == GPIO.LOW:
print("LEFT!")
if GPIO.input(RIGHT_FOOT_PIN) == GPIO.LOW:
print("RIGHT! ")

View file

@ -1,7 +0,0 @@
from mini_bdx_runtime.xbox_controller import XBoxController
import time
xbox = XBoxController(50)
while True:
print(xbox.get_last_command())
time.sleep(0.1)

View file

@ -1,4 +1,3 @@
# from mini_bdx_runtime.hwi_feetech_pypot import HWI
from mini_bdx_runtime.rustypot_control_hwi import HWI from mini_bdx_runtime.rustypot_control_hwi import HWI
hwi = HWI() hwi = HWI()

View file

@ -1,4 +1,3 @@
# from mini_bdx_runtime.hwi_feetech_pypot import HWI
from mini_bdx_runtime.rustypot_position_hwi import HWI from mini_bdx_runtime.rustypot_position_hwi import HWI
import time import time

View file

@ -1,11 +1,8 @@
import time import time
import pickle import pickle
# import pygame
import numpy as np import numpy as np
# from mini_bdx_runtime.hwi_feetech_pwm_control import HWI
# from mini_bdx_runtime.rustypot_control_hwi import HWI
from mini_bdx_runtime.rustypot_position_hwi import HWI from mini_bdx_runtime.rustypot_position_hwi import HWI
from mini_bdx_runtime.onnx_infer import OnnxInfer from mini_bdx_runtime.onnx_infer import OnnxInfer
from mini_bdx_runtime.rl_utils import make_action_dict, LowPassActionFilter from mini_bdx_runtime.rl_utils import make_action_dict, LowPassActionFilter