1010import  time 
1111from  typing  import  List 
1212from  typing  import  Union 
13+ import  csv 
14+ import  os 
1315
1416from  pslab .instrument .waveform_generator  import  PWMGenerator 
17+ from  datetime  import  datetime 
1518
1619MICROSECONDS  =  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 }  
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