Skip to content

Commit 8ae580e

Browse files
authored
feat: RoboticArm CSV import/export (#256)
1 parent b97ee9a commit 8ae580e

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

pslab/external/motor.py

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
import time
1111
from typing import List
1212
from typing import Union
13+
import csv
14+
import os
1315

1416
from pslab.instrument.waveform_generator import PWMGenerator
17+
from datetime import datetime
1518

1619
MICROSECONDS = 1e6
1720

@@ -96,7 +99,7 @@ def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> Non
9699
with angles corresponding to each servo.
97100
98101
time_step : float, optional
99-
Delay in seconds between each timestep. Default is 1.0.
102+
Delay in seconds between each timestep. Default is 1.0.
100103
"""
101104
if len(timeline[0]) != len(self.servos):
102105
raise ValueError("Each timestep must specify an angle for every servo")
@@ -107,5 +110,60 @@ def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> Non
107110

108111
for tl in timeline:
109112
for i, s in enumerate(self.servos):
110-
s.angle = tl[i]
113+
if tl[i] is not None:
114+
s.angle = tl[i]
111115
time.sleep(time_step)
116+
117+
def import_timeline_from_csv(self, filepath: str) -> List[List[int]]:
118+
"""Import timeline from a CSV file.
119+
120+
Parameters
121+
----------
122+
filepath : str
123+
Absolute or relative path to the CSV file to be read.
124+
125+
Returns
126+
-------
127+
List[List[int]]
128+
A timeline consisting of servo angle values per timestep.
129+
"""
130+
timeline = []
131+
132+
with open(filepath, mode="r", newline="") as csvfile:
133+
reader = csv.DictReader(csvfile)
134+
for row in reader:
135+
angles = []
136+
for key in ["Servo1", "Servo2", "Servo3", "Servo4"]:
137+
value = row[key]
138+
if value == "null":
139+
angles.append(None)
140+
else:
141+
angles.append(int(value))
142+
timeline.append(angles)
143+
144+
return timeline
145+
146+
def export_timeline_to_csv(
147+
self, timeline: List[List[Union[int, None]]], folderpath: str
148+
) -> None:
149+
"""Export timeline to a CSV file.
150+
151+
Parameters
152+
----------
153+
timeline : List[List[Union[int, None]]]
154+
A list of timesteps where each sublist contains servo angles.
155+
156+
folderpath : str
157+
Directory path where the CSV file will be saved. The filename
158+
will include a timestamp to ensure uniqueness.
159+
"""
160+
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
161+
filename = f"Robotic_Arm{timestamp}.csv"
162+
filepath = os.path.join(folderpath, filename)
163+
164+
with open(filepath, mode="w", newline="") as csvfile:
165+
writer = csv.writer(csvfile)
166+
writer.writerow(["Timestep", "Servo1", "Servo2", "Servo3", "Servo4"])
167+
for i, row in enumerate(timeline):
168+
pos = ["null" if val is None else val for val in row]
169+
writer.writerow([i] + pos)

0 commit comments

Comments
 (0)