From 7666182780942e7f207fd4b20f84550668421ee9 Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Thu, 10 Jul 2025 20:37:28 +0530 Subject: [PATCH 1/5] robotic arm --- pslab/external/motor.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 71cff0c..67924ef 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -7,6 +7,8 @@ >>> servo.angle = 30 # Turn motor to 30 degrees position. """ +import time +from typing import List from typing import Union from pslab.instrument.waveform_generator import PWMGenerator @@ -70,3 +72,21 @@ def _get_duty_cycle(self, angle): angle *= self._max_angle_pulse - self._min_angle_pulse # Scale angle += self._min_angle_pulse # Offset return angle / (self._frequency**-1 * MICROSECONDS) + + +class RoboticArm: + MAX_SERVOS = 4 + + def __init__(self, servos: List[Servo]) -> None: + if len(servos) > RoboticArm.MAX_SERVOS: + raise ValueError( + f"At most {RoboticArm.MAX_SERVOS} servos can be used, got {len(servos)}" + ) + self.servos = servos + + def run_schedule(self, timeline: List[List[int]]) -> None: + for i in range(len(timeline)): + for j in range(len(self.servos)): + angle = timeline[i][j] + self.servos[j].angle = angle + time.sleep(1) From d4daf52abc9b8299adf40ef0ef1af74df86eb06c Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Thu, 10 Jul 2025 21:07:43 +0530 Subject: [PATCH 2/5] docstring --- pslab/external/motor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 67924ef..4538dc2 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -75,6 +75,8 @@ def _get_duty_cycle(self, angle): class RoboticArm: + """Robotic arm controller for up to 4 servos.""" + MAX_SERVOS = 4 def __init__(self, servos: List[Servo]) -> None: @@ -85,6 +87,7 @@ def __init__(self, servos: List[Servo]) -> None: self.servos = servos def run_schedule(self, timeline: List[List[int]]) -> None: + """Move servos based on a time-based angle schedule.""" for i in range(len(timeline)): for j in range(len(self.servos)): angle = timeline[i][j] From 7e5a8dde16319f71478b54a135cc01924ee01e85 Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Sat, 12 Jul 2025 14:49:37 +0530 Subject: [PATCH 3/5] Changes --- pslab/external/motor.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 4538dc2..5d8b891 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -86,10 +86,13 @@ def __init__(self, servos: List[Servo]) -> None: ) self.servos = servos - def run_schedule(self, timeline: List[List[int]]) -> None: - """Move servos based on a time-based angle schedule.""" - for i in range(len(timeline)): - for j in range(len(self.servos)): - angle = timeline[i][j] - self.servos[j].angle = angle - time.sleep(1) + def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> None: + """Move servos based on a time-based angle schedule.""" + tl_len = len(timeline[0]) + if not all(len(tl) == tl_len for tl in timeline): + raise ValueError("All timeline entries must have the same length") + + for tl in timeline: + for i, s in enumerate(self.servos): + s.angle = tl[i] + time.sleep(time_step) From 258aa036e8150246617d276757f87d719aa36b58 Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Sat, 12 Jul 2025 14:54:15 +0530 Subject: [PATCH 4/5] format --- pslab/external/motor.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 5d8b891..a20ef7b 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -87,12 +87,12 @@ def __init__(self, servos: List[Servo]) -> None: self.servos = servos def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> None: - """Move servos based on a time-based angle schedule.""" - tl_len = len(timeline[0]) - if not all(len(tl) == tl_len for tl in timeline): - raise ValueError("All timeline entries must have the same length") - - for tl in timeline: - for i, s in enumerate(self.servos): - s.angle = tl[i] - time.sleep(time_step) + """Move servos based on a time-based angle schedule.""" + tl_len = len(timeline[0]) + if not all(len(tl) == tl_len for tl in timeline): + raise ValueError("All timeline entries must have the same length") + + for tl in timeline: + for i, s in enumerate(self.servos): + s.angle = tl[i] + time.sleep(time_step) From b1dfa143bd1a9df13a2d75c547c651e5036c0cd6 Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Mon, 14 Jul 2025 18:51:37 +0530 Subject: [PATCH 5/5] Changes --- pslab/external/motor.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index a20ef7b..f6caee1 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -87,7 +87,20 @@ def __init__(self, servos: List[Servo]) -> None: self.servos = servos def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> None: - """Move servos based on a time-based angle schedule.""" + """Run a time-based schedule to move servos. + + Parameters + ---------- + timeline : List[List[int]] + A list of timesteps,where each sublist represents one timestep, + with angles corresponding to each servo. + + time_step : float, optional + Delay in seconds between each timestep. Default is 1.0. + """ + if len(timeline[0]) != len(self.servos): + raise ValueError("Each timestep must specify an angle for every servo") + tl_len = len(timeline[0]) if not all(len(tl) == tl_len for tl in timeline): raise ValueError("All timeline entries must have the same length")