Skip to content

Commit b97ee9a

Browse files
authored
feat: Added RoboticArm (#255)
1 parent c12fb51 commit b97ee9a

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

pslab/external/motor.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
>>> servo.angle = 30 # Turn motor to 30 degrees position.
88
"""
99

10+
import time
11+
from typing import List
1012
from typing import Union
1113

1214
from pslab.instrument.waveform_generator import PWMGenerator
@@ -70,3 +72,40 @@ def _get_duty_cycle(self, angle):
7072
angle *= self._max_angle_pulse - self._min_angle_pulse # Scale
7173
angle += self._min_angle_pulse # Offset
7274
return angle / (self._frequency**-1 * MICROSECONDS)
75+
76+
77+
class RoboticArm:
78+
"""Robotic arm controller for up to 4 servos."""
79+
80+
MAX_SERVOS = 4
81+
82+
def __init__(self, servos: List[Servo]) -> None:
83+
if len(servos) > RoboticArm.MAX_SERVOS:
84+
raise ValueError(
85+
f"At most {RoboticArm.MAX_SERVOS} servos can be used, got {len(servos)}"
86+
)
87+
self.servos = servos
88+
89+
def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> None:
90+
"""Run a time-based schedule to move servos.
91+
92+
Parameters
93+
----------
94+
timeline : List[List[int]]
95+
A list of timesteps,where each sublist represents one timestep,
96+
with angles corresponding to each servo.
97+
98+
time_step : float, optional
99+
Delay in seconds between each timestep. Default is 1.0.
100+
"""
101+
if len(timeline[0]) != len(self.servos):
102+
raise ValueError("Each timestep must specify an angle for every servo")
103+
104+
tl_len = len(timeline[0])
105+
if not all(len(tl) == tl_len for tl in timeline):
106+
raise ValueError("All timeline entries must have the same length")
107+
108+
for tl in timeline:
109+
for i, s in enumerate(self.servos):
110+
s.angle = tl[i]
111+
time.sleep(time_step)

0 commit comments

Comments
 (0)