|
| 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