Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions pslab/external/motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Consider validating timeline dimensions in run_schedule.

Currently, run_schedule may raise an IndexError or ignore extra values if a sublist's length doesn't match self.servos. Adding a check for sublist length would improve robustness.

Suggested change
class RoboticArm:
MAX_SERVOS = 4
class RoboticArm:
MAX_SERVOS = 4
def run_schedule(self, timeline: List[List[Union[int, float]]]):
"""
Run a schedule of servo positions.
Args:
timeline: A list of lists, where each sublist contains positions for each servo at a time step.
Raises:
ValueError: If any sublist does not match the number of servos.
"""
for idx, positions in enumerate(timeline):
if len(positions) != len(self.servos):
raise ValueError(
f"Timeline entry at index {idx} has {len(positions)} positions, "
f"but {len(self.servos)} servos are configured."
)
# Existing logic for running the schedule goes here
# for positions in timeline:
# self.set_positions(positions)
# time.sleep(self.step_delay)

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)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider making the sleep duration configurable.

Allow users to set the sleep interval via a parameter or class attribute for greater flexibility.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Replace index in for loop with direct reference (for-index-replacement)

Loading