-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathservos.py
76 lines (61 loc) · 2.69 KB
/
servos.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from typing import List, Dict
from servo import Servo
from tabulate import tabulate
import os
class Servos:
def __init__(self, servos: List[Servo]):
self.servos = servos
self._last_table_lines = 0 # Track number of lines in last printed table
def __getitem__(self, index: int) -> Servo:
"""Get a servo by its position in the array (0-based indexing)"""
try:
return self.servos[index]
except IndexError:
raise IndexError(f"Servo index {index} is out of range. Valid indices are 0-{len(self.servos)-1}")
def __len__(self) -> int:
return len(self.servos)
def __iter__(self):
return iter(self.servos)
def print_status(self) -> None:
"""Print a formatted table with the status of all servos"""
# Clear previous output if it exists
if self._last_table_lines > 0:
# Move cursor up and clear lines
print(f"\033[{self._last_table_lines}A\033[J", end="")
headers = ["ID", "Name", "Position", "Target", "Min", "Max", "Default", "Range %", "Torque"]
data = []
for servo in self.servos:
data.append([
servo.id,
servo.name,
servo.current_position,
servo.target_position,
servo.limits.min_pos,
servo.limits.max_pos,
servo.limits.default_pos,
f"{servo.get_movement_range():.1f}%",
servo.current_torque
])
table = tabulate(data, headers=headers, tablefmt="grid")
print(table)
# Update line count (add 1 for the print statement itself)
self._last_table_lines = len(table.split('\n'))
def reset_all(self) -> None:
"""Reset all servos to their default positions"""
for servo in self.servos:
servo.reset_to_default()
def get_positions_dict(self) -> Dict[int, int]:
"""Get a dictionary of servo IDs to current positions"""
return {servo.id: servo.current_position for servo in self.servos}
def get_servo_by_id(self, servo_id: int) -> Servo:
"""Get a servo by its logical ID (not array position).
This is useful when you need to find a specific servo by its hardware ID.
Args:
servo_id: The hardware/logical ID of the servo
Raises:
ValueError: If no servo with the given ID exists
"""
for servo in self.servos:
if servo.id == servo_id:
return servo
raise ValueError(f"No servo found with ID {servo_id}")