From b818e43f8d975a000c581e4defdf35d04ea0887f Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Wed, 16 Jul 2025 21:54:09 +0530 Subject: [PATCH 1/4] CSV import/export --- pslab/external/motor.py | 62 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index f6caee1..62dfa74 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -10,8 +10,11 @@ import time from typing import List from typing import Union +import csv +import os from pslab.instrument.waveform_generator import PWMGenerator +from datetime import datetime MICROSECONDS = 1e6 @@ -96,7 +99,7 @@ def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> Non with angles corresponding to each servo. time_step : float, optional - Delay in seconds between each timestep. Default is 1.0. + 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") @@ -107,5 +110,60 @@ def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> Non for tl in timeline: for i, s in enumerate(self.servos): - s.angle = tl[i] + if tl[i] is not None: + s.angle = tl[i] time.sleep(time_step) + + def import_timeline_from_csv(self, filepath: str) -> List[List[int]]: + """Import timeline from a CSV file. + + Parameters + ---------- + filepath : str + Absolute or relative path to the CSV file to be read. + + Returns + ------- + List[List[int]] + A timeline consisting of servo angle values per timestep. + """ + timeline = [] + + with open(filepath, mode="r", newline="") as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + angles = [] + for key in ["Servo1", "Servo2", "Servo3", "Servo4"]: + value = row.get(key, "").strip().lower() + if value in ("", "null", "none"): + angles.append(None) + else: + angles.append(int(value)) + timeline.append(angles) + + return timeline + + def export_timeline_to_csv( + self, timeline: List[List[Union[int, None]]], folderpath: str + ) -> None: + """Export timeline to a CSV file. + + Parameters + ---------- + timeline : List[List[Union[int, None]]] + A list of timesteps where each sublist contains servo angles. + + folderpath : str + Directory path where the CSV file will be saved. The filename + will include a timestamp to ensure uniqueness. + """ + timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + filename = f"Robotic_Arm{timestamp}.csv" + filepath = os.path.join(folderpath, filename) + + with open(filepath, mode="w", newline="") as csvfile: + writer = csv.writer(csvfile) + writer.writerow(["Timestamp", "Servo1", "Servo2", "Servo3", "Servo4"]) + for i, row in enumerate(timeline): + pos = ["null" if val is None else val for val in row] + writer.writerow([i] + pos) From da23f8888de18914327472920b564e0025b92c7e Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Wed, 16 Jul 2025 22:18:12 +0530 Subject: [PATCH 2/4] Header name --- pslab/external/motor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 62dfa74..773e7a8 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -163,7 +163,7 @@ def export_timeline_to_csv( with open(filepath, mode="w", newline="") as csvfile: writer = csv.writer(csvfile) - writer.writerow(["Timestamp", "Servo1", "Servo2", "Servo3", "Servo4"]) + writer.writerow(["Timestemp", "Servo1", "Servo2", "Servo3", "Servo4"]) for i, row in enumerate(timeline): pos = ["null" if val is None else val for val in row] writer.writerow([i] + pos) From cf2c370e6107c40b1d5d544133de22dfdcc9f32e Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Wed, 16 Jul 2025 22:19:48 +0530 Subject: [PATCH 3/4] header name --- pslab/external/motor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 773e7a8..5cd79e4 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -163,7 +163,7 @@ def export_timeline_to_csv( with open(filepath, mode="w", newline="") as csvfile: writer = csv.writer(csvfile) - writer.writerow(["Timestemp", "Servo1", "Servo2", "Servo3", "Servo4"]) + writer.writerow(["Timestep", "Servo1", "Servo2", "Servo3", "Servo4"]) for i, row in enumerate(timeline): pos = ["null" if val is None else val for val in row] writer.writerow([i] + pos) From 7edfdff63cce36e7453615fe37d0c46fec4ba888 Mon Sep 17 00:00:00 2001 From: rahul31124 Date: Thu, 17 Jul 2025 17:52:02 +0530 Subject: [PATCH 4/4] import-null --- pslab/external/motor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 5cd79e4..1fba065 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -134,8 +134,8 @@ def import_timeline_from_csv(self, filepath: str) -> List[List[int]]: for row in reader: angles = [] for key in ["Servo1", "Servo2", "Servo3", "Servo4"]: - value = row.get(key, "").strip().lower() - if value in ("", "null", "none"): + value = row[key] + if value == "null": angles.append(None) else: angles.append(int(value))