mirror of
https://github.com/apirrone/Open_Duck_Mini_Runtime.git
synced 2025-09-02 19:23:54 +00:00
cleaning up
This commit is contained in:
parent
1bc8ba2d1f
commit
cdfb571479
24 changed files with 9 additions and 2855 deletions
|
@ -21,3 +21,12 @@ class FeetContacts:
|
|||
if GPIO.input(RIGHT_FOOT_PIN) == GPIO.LOW:
|
||||
right = True
|
||||
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
|
@ -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()
|
|
@ -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()
|
|
@ -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())
|
|
@ -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))
|
|
@ -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))
|
|
@ -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)
|
|
@ -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)
|
|
@ -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))
|
|
@ -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")
|
|
@ -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.
|
|
@ -2,9 +2,6 @@
|
|||
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.eyes import Eyes
|
||||
import time
|
||||
|
|
|
@ -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()
|
|
@ -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)
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
|
@ -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)")
|
|
@ -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! ")
|
|
@ -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)
|
|
@ -1,4 +1,3 @@
|
|||
# from mini_bdx_runtime.hwi_feetech_pypot import HWI
|
||||
from mini_bdx_runtime.rustypot_control_hwi import HWI
|
||||
|
||||
hwi = HWI()
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# from mini_bdx_runtime.hwi_feetech_pypot import HWI
|
||||
from mini_bdx_runtime.rustypot_position_hwi import HWI
|
||||
import time
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import time
|
||||
import pickle
|
||||
|
||||
# import pygame
|
||||
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.onnx_infer import OnnxInfer
|
||||
from mini_bdx_runtime.rl_utils import make_action_dict, LowPassActionFilter
|
||||
|
|
Loading…
Reference in a new issue