@@ -39,7 +39,9 @@ Edit the ``config.yml`` file to have the following for user_dir, labs, and exper
3939 Sample Usage
4040------------
41411. ``cd `` into the ``eos `` directory
42- 2. Run ``python3 user/eos_examples/color_lab/device_drivers.py `` to start the fluid simulation and simulated device drivers.
42+ 2. Run ``python3 user/eos_examples/color_lab/device_drivers.py `` to start the fluid simulation and simulated device drivers. Browser windows will open automatically.
43+
44+ On dual-GPU systems (e.g., NVIDIA + integrated GPU on Wayland), pass ``--browser chrome --nvidia `` to launch the browser with NVIDIA GPU offload and X11 mode for correct WebGL rendering.
43453. Start EOS.
44464. Submit tasks, experiments, or campaigns through the REST API.
4547
@@ -79,6 +81,7 @@ The top-level structure of the ``color_lab`` package is as follows:
7981 ├── common/ <-- contains shared code
8082 ├── devices/ <-- contains the device implementations
8183 ├── experiments/ <-- contains the color mixing experiment definitions
84+ ├── labs/ <-- contains the laboratory definition
8285 ├── tasks/ <-- contains the task definitions
8386 ├── fluid_simulation/ <-- contains the source code for the fluid simulation web app
8487 └── device_drivers.py <-- a script for starting the fluid simulation and socket servers for the devices
@@ -88,12 +91,11 @@ Devices
8891-------
8992The package contains the following device implementations:
9093
91- * **Color mixer **: Sends commands to the fluid simulation to dispense and mix colors.
92- * **Color analyzer **: Queries the fluid simulation to get the average fluid color.
94+ * **Color station **: Sends commands to the fluid simulation to dispense and mix colors, and queries it to get the average fluid color.
9395* **Robot arm **: Moves sample containers between other devices.
9496* **Cleaning station **: Cleans sample containers (by erasing their stored metadata).
9597
96- This is the Python code for the color analyzer device:
98+ This is the Python code for the color station device:
9799
98100:bdg-primary: `device.py `
99101
@@ -106,7 +108,7 @@ This is the Python code for the color analyzer device:
106108 from user.eos_examples.color_lab.common.device_client import DeviceClient
107109
108110
109- class ColorAnalyzer (BaseDevice ):
111+ class ColorStation (BaseDevice ):
110112 async def _initialize (self , init_parameters : dict[str , Any]) -> None :
111113 port = int (init_parameters[" port" ])
112114 self .client = DeviceClient(port)
@@ -118,41 +120,59 @@ This is the Python code for the color analyzer device:
118120 async def _report (self ) -> dict[str , Any]:
119121 return {}
120122
123+ def mix (
124+ self ,
125+ container : Resource,
126+ cyan_volume : float ,
127+ cyan_strength : float ,
128+ magenta_volume : float ,
129+ magenta_strength : float ,
130+ yellow_volume : float ,
131+ yellow_strength : float ,
132+ black_volume : float ,
133+ black_strength : float ,
134+ mixing_time : int ,
135+ mixing_speed : int ,
136+ ) -> Resource:
137+ ...
138+
121139 def analyze (self , container : Resource) -> tuple[Resource, tuple[int , int , int ]]:
122140 rgb = self .client.send_command(" analyze" , {})
123141 return container, rgb
124142
125- You will notice that there is little code here.
126- In fact, the device implementation communicates with another process over a socket.
143+ You will notice that the color station combines both mixing and analysis into a single device.
144+ This ensures that a single allocation connects to a single fluid simulation window, so the
145+ color that is mixed is the same one that gets analyzed.
146+
147+ The device implementation communicates with another process over a socket.
127148This is a common pattern when integrating devices in the laboratory, as device drivers are usually provided by a 3rd
128149party, such as the device manufacturer.
129150So often the device implementation simply uses the existing driver.
130151In some cases, the device implementation may include a full driver implementation.
131152
132153The device implementation initializes a client that connects to the device driver over a socket.
133- The device implements one function called `` analyze ``, which accepts a beaker resource and returns the resource and the average
134- RGB value of the fluid color from the fluid simulation.
154+ The device implements a `` mix `` function for dispensing and mixing colors, and an `` analyze `` function
155+ that returns the average RGB value of the fluid color from the fluid simulation.
135156
136- The device YAML file for the color analyzer device is:
157+ The device YAML file for the color station device is:
137158
138159:bdg-primary: `device.yml `
139160
140161.. code-block :: yaml
141162
142- type : color_analyzer
143- desc : Analyzes the RGB value of a color mixture
163+ type : color_station
164+ desc : Color mixing and analysis station backed by a fluid simulation
144165
145166 init_parameters :
146- port : 5002
167+ port : 5003
147168
148169 Tasks
149170-----
150171The package contains the following tasks:
151172
152- * **Retrieve container **: Retrieves a beaker from storage and moves it to a color mixer using the robot arm.
153- * **Mix colors **: Dispenses and mixes colors using a color mixer (fluid simulation).
154- * **Move container to analyzer **: Moves the beaker from the color mixer to a color analyzer using the robot arm.
155- * **Analyze color **: Analyzes the color of the fluid using a color analyzer (fluid simulation).
173+ * **Retrieve container **: Retrieves a beaker from storage and moves it to a color station using the robot arm.
174+ * **Mix colors **: Dispenses and mixes colors using a color station (fluid simulation).
175+ * **Analyze color **: Analyzes the color of the fluid using a color station (fluid simulation).
156176* **Score color **: Calculates a loss function taking into account how close the mixed color is to the target color and
157177 how much color ingredients were used.
158178* **Empty container **: Empties a beaker with the robot arm.
@@ -175,9 +195,9 @@ This is the Python code for the "Analyze color" task:
175195 parameters : BaseTask.ParametersType,
176196 resources : BaseTask.ResourcesType,
177197 ) -> BaseTask.OutputType:
178- color_analyzer = devices[" color_analyzer " ]
198+ color_station = devices[" color_station " ]
179199
180- resources[" beaker" ], rgb = color_analyzer .analyze(resources[" beaker" ])
200+ resources[" beaker" ], rgb = color_station .analyze(resources[" beaker" ])
181201
182202 output_parameters = {
183203 " red" : rgb[0 ],
@@ -187,8 +207,8 @@ This is the Python code for the "Analyze color" task:
187207
188208 return output_parameters, resources, None
189209
190- The task implementation is straightforward. We first get a reference to the color analyzer device.
191- Then, we call the ``analyze `` function from the color analyzer device we saw earlier. Finally, we construct
210+ The task implementation is straightforward. We first get a reference to the color station device.
211+ Then, we call the ``analyze `` function from the color station device we saw earlier. Finally, we construct
192212and return the dict of output parameters and the resources.
193213
194214The task YAML file is the following:
@@ -201,8 +221,8 @@ The task YAML file is the following:
201221 desc : Analyze the color of a solution
202222
203223 devices :
204- color_analyzer :
205- type : color_analyzer
224+ color_station :
225+ type : color_station
206226
207227 input_resources :
208228 beaker :
@@ -227,7 +247,7 @@ Laboratory
227247The laboratory YAML definition is shown below.
228248
229249We define the devices we discussed earlier.
230- Note that we define three color mixers and three color analyzers so the laboratory can support up to three simultaneous color mixing experiments.
250+ Note that we define three color stations so the laboratory can support up to three simultaneous color mixing experiments.
231251
232252We also define the resource types and the actual resources (beakers) with their initial locations.
233253
@@ -247,12 +267,9 @@ We also define the resource types and the actual resources (beakers) with their
247267 init_parameters :
248268 locations :
249269 - container_storage
250- - color_mixer_1
251- - color_mixer_2
252- - color_mixer_3
253- - color_analyzer_1
254- - color_analyzer_2
255- - color_analyzer_3
270+ - color_station_1
271+ - color_station_2
272+ - color_station_3
256273 - cleaning_station
257274 - emptying_location
258275
@@ -264,71 +281,38 @@ We also define the resource types and the actual resources (beakers) with their
264281 meta :
265282 location : cleaning_station
266283
267- color_mixer_1 :
268- desc : Color mixing apparatus for incrementally dispensing and mixing color solutions
269- type : color_mixer
270- computer : eos_computer
271-
272- init_parameters :
273- port : 5004
274-
275- meta :
276- location : color_mixer_1
277-
278- color_mixer_2 :
279- desc : Color mixing apparatus for incrementally dispensing and mixing color solutions
280- type : color_mixer
281- computer : eos_computer
282-
283- init_parameters :
284- port : 5006
285-
286- meta :
287- location : color_mixer_2
288-
289- color_mixer_3 :
290- desc : Color mixing apparatus for incrementally dispensing and mixing color solutions
291- type : color_mixer
292- computer : eos_computer
293-
294- init_parameters :
295- port : 5008
296-
297- meta :
298- location : color_mixer_3
299-
300- color_analyzer_1 :
301- desc : Analyzer for color solutions
302- type : color_analyzer
284+ color_station_1 :
285+ desc : Color mixing and analysis station backed by a fluid simulation
286+ type : color_station
303287 computer : eos_computer
304288
305289 init_parameters :
306290 port : 5003
307291
308292 meta :
309- location : color_analyzer_1
293+ location : color_station_1
310294
311- color_analyzer_2 :
312- desc : Analyzer for color solutions
313- type : color_analyzer
295+ color_station_2 :
296+ desc : Color mixing and analysis station backed by a fluid simulation
297+ type : color_station
314298 computer : eos_computer
315299
316300 init_parameters :
317- port : 5005
301+ port : 5004
318302
319303 meta :
320- location : color_analyzer_2
304+ location : color_station_2
321305
322- color_analyzer_3 :
323- desc : Analyzer for color solutions
324- type : color_analyzer
306+ color_station_3 :
307+ desc : Color mixing and analysis station backed by a fluid simulation
308+ type : color_station
325309 computer : eos_computer
326310
327311 init_parameters :
328- port : 5007
312+ port : 5005
329313
330314 meta :
331- location : color_analyzer_3
315+ location : color_station_3
332316
333317
334318 resource_types :
@@ -362,9 +346,8 @@ Experiment
362346----------
363347The color mixing experiment is a linear sequence of the following tasks:
364348
365- #. **retrieve_container **: Get a beaker from storage and move it to a color mixer .
349+ #. **retrieve_container **: Get a beaker from storage and move it to a color station .
366350#. **mix_colors **: Iteratively dispense and mix the colors in the beaker.
367- #. **move_container_to_analyzer **: Move the beaker from the color mixer to a color analyzer.
368351#. **analyze_color **: Analyze the color of the solution in the beaker and output the RGB values.
369352#. **score_color **: Score the color (compute the loss function) based on the RGB values.
370353#. **empty_container **: Empty the beaker and move it to the cleaning station.
@@ -392,10 +375,9 @@ The YAML definition of the experiment is shown below:
392375 robot_arm :
393376 lab_name : color_lab
394377 name : robot_arm
395- color_mixer :
378+ color_station :
396379 allocation_type : dynamic
397- device_type : color_mixer
398- allowed_labs : [color_lab]
380+ device_type : color_station
399381 resources :
400382 beaker :
401383 allocation_type : dynamic
@@ -407,7 +389,7 @@ The YAML definition of the experiment is shown below:
407389 desc : Mix the colors in the container
408390 duration : 20
409391 devices :
410- color_mixer : retrieve_container.color_mixer
392+ color_station : retrieve_container.color_station
411393 resources :
412394 beaker : retrieve_container.beaker
413395 parameters :
@@ -423,32 +405,15 @@ The YAML definition of the experiment is shown below:
423405 mixing_speed : eos_dynamic
424406 dependencies : [retrieve_container]
425407
426- - name : move_container_to_analyzer
427- type : Move Container to Analyzer
428- desc : Move the container to the color analyzer
429- duration : 5
430- devices :
431- robot_arm :
432- lab_name : color_lab
433- name : robot_arm
434- color_mixer : mix_colors.color_mixer
435- color_analyzer :
436- allocation_type : dynamic
437- device_type : color_analyzer
438- allowed_labs : [color_lab]
439- resources :
440- beaker : mix_colors.beaker
441- dependencies : [mix_colors]
442-
443408 - name : analyze_color
444409 type : Analyze Color
445410 desc : Analyze the color of the solution in the container and output the RGB values
446411 duration : 2
447412 devices :
448- color_analyzer : move_container_to_analyzer.color_analyzer
413+ color_station : mix_colors.color_station
449414 resources :
450- beaker : move_container_to_analyzer .beaker
451- dependencies : [move_container_to_analyzer ]
415+ beaker : mix_colors .beaker
416+ dependencies : [mix_colors ]
452417
453418 - name : score_color
454419 type : Score Color
@@ -528,13 +493,13 @@ Example:
528493
529494 - name : mix_colors
530495 devices :
531- color_mixer : retrieve_container.color_mixer
496+ color_station : retrieve_container.color_station
532497
533498 - name : analyze_color
534499 devices :
535- color_analyzer : move_container_to_analyzer.color_analyzer
500+ color_station : mix_colors.color_station
536501
537- In the first snippet, the mix_colors task uses the exact color_mixer allocated during retrieve_container. In the second, analyze_color uses the color_analyzer allocated during move_container_to_analyzer .
502+ In the first snippet, the mix_colors task uses the exact color_station allocated during retrieve_container. In the second, analyze_color uses the same color_station, ensuring that the mixed color is analyzed on the same simulation window .
538503
539504**Resource references **: pass the same physical resource instance (e.g., a beaker) downstream.
540505
@@ -548,9 +513,9 @@ Example:
548513
549514 - name : analyze_color
550515 resources :
551- beaker : move_container_to_analyzer .beaker
516+ beaker : mix_colors .beaker
552517
553- The beaker chosen (dynamically) in retrieve_container is reused by mix_colors, then moved by the robot and reused by analyze_color .
518+ The beaker chosen (dynamically) in retrieve_container is reused by mix_colors, then reused by analyze_color on the same station .
554519
555520**Parameter references **: feed outputs from one task as inputs to another by referencing output parameters.
556521
0 commit comments