Skip to content

Commit 73bd30c

Browse files
authored
feat(api): G-Code CLI (#8156)
* feat(api): Add dash separator * feat(api): Change to correct settings type * feat(api): Add CLI and tests * feat(api): Add more saving options * feat(api): Change incorrect variable name * feat(api): Provide example Bash command * feat(api): Add saving HTML to file * feat(api): README * feat(api): Fix call * feat(api): Fix review requests
1 parent 79778e7 commit 73bd30c

File tree

10 files changed

+734
-11
lines changed

10 files changed

+734
-11
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# G-Code Parser
2+
3+
Framework supporting the following:
4+
* Running protocols against emulation
5+
* Capturing called G-Codes of emulated protocols
6+
* Parsing captured G-Codes into human-readable text or JSON format
7+
* Diffing human-readable text or JSON format
8+
* CLI access to all the above features
9+
10+
## Python Framework
11+
12+
### G-Code Parser
13+
14+
Using the `ProtocolRunner` you can run a Python protocol file against emulation.
15+
The `ProtocolRunner` instance will return a `GCodeProgram` instance
16+
17+
**Example:**
18+
```python
19+
"""
20+
Using default settings, run protocol at /my/absolute/path/to/my/protocol.py
21+
against emulation.
22+
In "Concise" format store parsed G-Code to /where/I/want/to/store/my/output.txt
23+
"""
24+
import os.path
25+
from opentrons.hardware_control.g_code_parsing.protocol_runner import ProtocolRunner
26+
from opentrons.hardware_control.g_code_parsing.g_code_program.supported_text_modes \
27+
import SupportedTextModes
28+
from opentrons.hardware_control.emulation.settings import Settings
29+
30+
PROTOCOL_PATH = os.path.join('my', 'absolute', 'path', 'to', 'my', 'protocol.py')
31+
OUTPUT_PATH = os.path.join('where', 'I', 'want', 'to', 'store', 'my', 'output.txt')
32+
33+
settings = Settings() # Using default settings defined in class
34+
with ProtocolRunner(settings).run_protocol(PROTOCOL_PATH) as program:
35+
program.save_text_explanation_to_file(OUTPUT_PATH, SupportedTextModes.CONCISE)
36+
```
37+
38+
### G-Code Differ
39+
40+
Using the `GCodeDiffer` you can compare 2 files and return the differences between
41+
them in HTML format.
42+
43+
**Example:**
44+
```python
45+
"""
46+
Compare 2 files and save the diff to a file
47+
"""
48+
import os.path
49+
from opentrons.hardware_control.g_code_parsing.g_code_differ import GCodeDiffer
50+
FILE_1_PATH = os.path.join('tmp', 'file_1.txt')
51+
FILE_2_PATH = os.path.join('tmp', 'file_2.txt')
52+
HTML_PATH = os.path.join('home', 'derek_maggio', 'Desktop', 'my_diff.html')
53+
54+
with open(FILE_1_PATH, 'r') as file_1, open(FILE_2_PATH, 'r') as file_2:
55+
file_1_content = '\n'.join(file_1.readlines())
56+
file_2_content = '\n'.join(file_2.readlines())
57+
GCodeDiffer(file_1_content, file_2_content).save_html_diff_to_file(HTML_PATH)
58+
```
59+
60+
## CLI
61+
62+
Using the CLI you can access the above functionality through the command line.
63+
It currently supports 2 commands `run` and `diff`.
64+
65+
## Viewing Help Message
66+
67+
To view available commands run:
68+
```shell
69+
python cli.py -h
70+
```
71+
72+
To view help for specific command run:
73+
```shell
74+
python cli.py <your_command> -h
75+
```
76+
For example,
77+
```shell
78+
python cli.py run -h
79+
```
80+
81+
## Running Protocol
82+
83+
To run a protocol with the CLI use the `run` command.
84+
It has the format of
85+
```
86+
cli.py run [-h] [--text-mode Concise | Default | G-Code]
87+
[--left-pipette left_pipette_config]
88+
[--right-pipette right_pipette_config]
89+
protocol_file_path
90+
```
91+
92+
Usage Example:
93+
```shell
94+
python cli.py run \
95+
--text-mode G-Code \
96+
--left-pipette '{"model": "p20_single_v2.0", "id": "P20SV202020070101"}' \
97+
$HOME/Documents/repos/opentrons/api/tests/opentrons/data/g_code_validation_protocols/smoothie_protocol.py
98+
```
99+
100+
### Command Breakdown
101+
102+
#### --text-mode
103+
The `--text-mode` option determines the output format of running the protocol.
104+
105+
It has 3 choices for text modes: Default, Concise, and G-Code.
106+
107+
* **Default** - The most verbose format. Provides raw G-Code, an explanation of what the G-Code
108+
does, and an explanation of the response.
109+
110+
* **Concise** - Contains all the same information as `Default` but condenses it to a single line.
111+
Instead of headers it uses `->` to delimit the G-Code, explanation, and response.
112+
113+
* **G-Code** - Contains only the raw G-Code and the raw response. Delimited by `->`.
114+
115+
Default Output Example:
116+
```
117+
Code: M114.2
118+
Explanation: Getting current position for all axes
119+
Response: The current position of the robot is:
120+
A Axis: 105.29
121+
B Axis: -8.5
122+
C Axis: 19.0
123+
X Axis: 113.38
124+
Y Axis: 11.24
125+
Z Axis: 218.0
126+
-----------------------------------------
127+
Code: M400
128+
Explanation: Waiting for motors to stop moving
129+
Response:
130+
-----------------------------------------
131+
Code: M907 A0.1 B0.05 C1.0 X0.3 Y0.3 Z0.1
132+
Explanation: Setting the current (in amps) to:
133+
X-Axis Motor: 0.3
134+
Y-Axis Motor: 0.3
135+
Z-Axis Motor: 0.1
136+
A-Axis Motor: 0.1
137+
B-Axis Motor: 0.05
138+
C-Axis Motor: 1.0
139+
Response:
140+
-----------------------------------------
141+
Code: G4 P0.005
142+
Explanation: Pausing movement for 0.005ms
143+
Response:
144+
```
145+
146+
Concise Output Example:
147+
```
148+
M114.2 -> Getting current position for all axes -> The current position of the robot is: A Axis: 105.29 B Axis: -8.5 C Axis: 19.0 X Axis: 113.38 Y Axis: 11.24 Z Axis: 218.0
149+
M400 -> Waiting for motors to stop moving ->
150+
M907 A0.1 B0.05 C1.0 X0.3 Y0.3 Z0.1 -> Setting the current (in amps) to: X-Axis Motor: 0.3 Y-Axis Motor: 0.3 Z-Axis Motor: 0.1 A-Axis Motor: 0.1 B-Axis Motor: 0.05 C-Axis Motor: 1.0 ->
151+
G4 P0.005 -> Pausing movement for 0.005ms ->
152+
```
153+
154+
G-Code Output Example:
155+
```
156+
M114.2 -> M114.2 MCS: A:105.29 B:-8.5 C:19.0 X:113.38 Y:11.24 Z:218.0
157+
M400 ->
158+
M907 A0.1 B0.05 C1.0 X0.3 Y0.3 Z0.1 ->
159+
G4 P0.005 ->
160+
```
161+
162+
Option Usage Example:
163+
```shell
164+
--text-mode Default
165+
```
166+
167+
#### --left-pipette --right-pipette
168+
169+
The `--left-pipette` and `--right-pipette` options are the way to provide the configuration
170+
of the pipettes for the OT-2 Emulator. The expected format is JSON.
171+
172+
The JSON expects 2 keys `id` and `model`.
173+
174+
Option Usage Example:
175+
```shell
176+
--left-pipette '{"model": "p20_single_v2.0", "id": "P20SV202020070101"}'
177+
```
178+
179+
#### protocol_file_path
180+
181+
The protocol file path can either be an absolute or relative file path to the
182+
Python protocol file that you want to run.
183+
184+
Argument Usage Example:
185+
```
186+
/absolute/path/to/my/file.py
187+
188+
OR
189+
190+
../relative/path/to/my/file.py
191+
```
192+
193+
## Diffing Output Files
194+
195+
To diff 2 output files with the CLI use the `diff` command.
196+
197+
The command will return an HTML encoded diff.
198+
199+
It has the format of
200+
```
201+
usage: cli.py diff [-h] file_path_1 file_path_2
202+
```
203+
204+
Usage Example:
205+
```shell
206+
python cli.py diff /file/path/one.txt /file/path/two.txt
207+
```
208+
209+
### Command Breakdown
210+
211+
#### file_path_1 file_path_2
212+
The paths to the files you want to diff
213+
214+
Argument Usage Example:
215+
```
216+
/absolute/path/to/my/file.py
217+
218+
OR
219+
220+
../relative/path/to/my/file.py
221+
```

0 commit comments

Comments
 (0)