adxc 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
adxc-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CEAD
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
adxc-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,117 @@
1
+ Metadata-Version: 2.4
2
+ Name: adxc
3
+ Version: 0.1.0
4
+ Summary: Create cell files for AdaOne
5
+ Requires-Python: >=3.14
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: blackboxprotobuf>=1.0.1
9
+ Requires-Dist: pyyaml>=6.0
10
+ Dynamic: license-file
11
+
12
+ # adxc
13
+
14
+ `adxc` is a small Python library for creating AdaOne cell definition files (`.adxc`) and zipped cell packages (`.adxczip`). It makes it easy to define a robot cell programmatically: select a robot, add external equipment, create workframes, attach heads, and add cell elements such as fixtures or process parts.
15
+
16
+ The library is centered on the `Cell` object, which stores the robot, equipment, workframes, kinematics, and resources needed for a complete cell definition.
17
+
18
+ ## Features
19
+
20
+ - Add a robot to a cell with `Cell.add_robot()`
21
+ - Add linear tracks and other external axes with `Cell.add_track()`
22
+ - Add gantry and positioner equipment
23
+ - Create named workframes and work offsets
24
+ - Attach tool heads and toolframes
25
+ - Add cell elements with mesh file references and optional workframe placement
26
+ - Save the result as a `.adxc` file or bundled `.adxczip` archive
27
+
28
+ ## Usage
29
+
30
+ ```python
31
+ from pathlib import Path
32
+ import adxc
33
+ from adxc import Cell, Robot, Track, Process
34
+
35
+ cell = Cell(name="Example")
36
+
37
+ cell.add_robot(Robot.Comau.NJ165_30)
38
+ cell.add_track(Track.VanSichen.Comau(length=4000, rotation=90, riser=0))
39
+
40
+ cell.add_head(
41
+ model="Extruder",
42
+ filepath=Path("meshes/Extruder.stl").resolve()
43
+ ).add_toolframe(
44
+ name="TCP1",
45
+ process=Process.PELLET,
46
+ translation=[100, 200, 300],
47
+ rotation=[0, 0, 0]
48
+ )
49
+
50
+ cell.add_workframe(
51
+ name="G54",
52
+ translation=[1000, -1000, 340],
53
+ rotation=[0, 0, 90],
54
+ min_x=0, min_y=0, max_x=2000, max_y=4000,
55
+ grid_spacing=100,
56
+ workoffset_index=1,
57
+ )
58
+
59
+ cell.add_element(
60
+ name="Printbed",
61
+ translation=[1000, -1000, 340],
62
+ rotation=[0, 0, 90],
63
+ workframe=cell.work_frames[1],
64
+ filepath=Path("meshes/Printbed.stl").resolve(),
65
+ )
66
+
67
+ adxc.save(cell, "output")
68
+ # or: adxc.savezip(cell, "output")
69
+ ```
70
+
71
+ This creates a simple robot cell with a linear track, a process head, a workframe definition, and a physical element placed in the cell.
72
+
73
+ ## Equipment types
74
+
75
+ The library exposes convenience methods for the main equipment categories used in robot cells:
76
+
77
+ - `add_robot(robot)`: Adds a robot model (from `Robot` enum) and its default home position, kinematic chain, and work offsets.
78
+ - `add_track(track)`: Adds a linear motion axis or rail (from `Track` enum). This is the method for linear equipment attached to the robot or cell.
79
+ - `add_gantry(gantry)`: Adds a gantry-style equipment unit (from `Gantry` enum), typically used for multi-axis motion or large work envelopes.
80
+ - `add_positioner(positioner)`: Adds a rotating or positioning table (from `Positioner` enum), often used for workpiece orientation or part handling.
81
+
82
+ Equipment types are accessed through enums (e.g., `Robot.Comau.NJ165_30`, `Track.VanSichen.Comau()`) and support named parameters for configuration. These methods insert equipment into the cell and also register any required external-axis kinematics so the robot and attached motion devices are represented consistently in the exported cell definition.
83
+
84
+ ## Workframes
85
+
86
+ A workframe is a named coordinate system in the cell. Workframes are used to define where robot motion is relative to the fixture, machine, or workpiece. In `adxc`, each workframe has a name, translation, rotation, and optional limits for the grid used by the controller.
87
+
88
+ `Cell.add_workframe()` creates a new workframe and can assign it to a specific work offset index such as `G54`, `G55`, and so on (workoffset_index 1-4 for G54-G57, 5-24 for G505-G524). Grid parameters like `min_x`, `min_y`, `max_x`, `max_y`, and `grid_spacing` can be optionally specified to define motion boundaries. The first workframe is treated as the default cell work object, while additional workframes represent additional aligned coordinate systems.
89
+
90
+ ## Cell elements
91
+
92
+ A cell element is a physical item in the cell, such as a machine bed, fixture, conveyor component, or other object that should be positioned in the same coordinate system as the robot. These are represented with `CellElement` objects and are typically given a name, filepath (for an STL or mesh), translation, rotation, and an optional workframe reference.
93
+
94
+ `Cell.add_element()` is the normal way to create these objects and attach them to the cell.
95
+
96
+ ## Heads
97
+
98
+ A head represents the process tool or end-effector mounted on the robot. It can include the TCP definition, payload, file path to the tool geometry, and one or more `toolframes` describing tool offsets. `Cell.add_head()` registers the head on the robot with an optional `model` name, and `Head.add_toolframe()` adds tool definitions such as a TCP frame or process-specific tool orientation.
99
+
100
+ Toolframes support a `process` parameter (from the `Process` enum) to specify the type of process the tool performs, such as `Process.PELLET` for extrusion or other predefined processes.
101
+
102
+ Heads are important because they describe how the robot interacts with the workpiece or process, not just the robot body itself.
103
+
104
+ ## Saving a cell
105
+
106
+ After the cell is assembled, you can save it to disk using the module-level `save()` and `savezip()` functions:
107
+
108
+ ```python
109
+ adxc.save(cell, "output_dir")
110
+ adxc.savezip(cell, "output_dir")
111
+ ```
112
+
113
+ `save()` writes a `.adxc` cell file. `savezip()` packages the cell and any referenced resource files into a `.adxczip` archive.
114
+
115
+ ## Project status
116
+
117
+ This repository is made by reverse engineering .adxc files. Properties may difffer from actual implementation. Equipment GUIDs are created by reading cells created using AdaOne.
adxc-0.1.0/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # adxc
2
+
3
+ `adxc` is a small Python library for creating AdaOne cell definition files (`.adxc`) and zipped cell packages (`.adxczip`). It makes it easy to define a robot cell programmatically: select a robot, add external equipment, create workframes, attach heads, and add cell elements such as fixtures or process parts.
4
+
5
+ The library is centered on the `Cell` object, which stores the robot, equipment, workframes, kinematics, and resources needed for a complete cell definition.
6
+
7
+ ## Features
8
+
9
+ - Add a robot to a cell with `Cell.add_robot()`
10
+ - Add linear tracks and other external axes with `Cell.add_track()`
11
+ - Add gantry and positioner equipment
12
+ - Create named workframes and work offsets
13
+ - Attach tool heads and toolframes
14
+ - Add cell elements with mesh file references and optional workframe placement
15
+ - Save the result as a `.adxc` file or bundled `.adxczip` archive
16
+
17
+ ## Usage
18
+
19
+ ```python
20
+ from pathlib import Path
21
+ import adxc
22
+ from adxc import Cell, Robot, Track, Process
23
+
24
+ cell = Cell(name="Example")
25
+
26
+ cell.add_robot(Robot.Comau.NJ165_30)
27
+ cell.add_track(Track.VanSichen.Comau(length=4000, rotation=90, riser=0))
28
+
29
+ cell.add_head(
30
+ model="Extruder",
31
+ filepath=Path("meshes/Extruder.stl").resolve()
32
+ ).add_toolframe(
33
+ name="TCP1",
34
+ process=Process.PELLET,
35
+ translation=[100, 200, 300],
36
+ rotation=[0, 0, 0]
37
+ )
38
+
39
+ cell.add_workframe(
40
+ name="G54",
41
+ translation=[1000, -1000, 340],
42
+ rotation=[0, 0, 90],
43
+ min_x=0, min_y=0, max_x=2000, max_y=4000,
44
+ grid_spacing=100,
45
+ workoffset_index=1,
46
+ )
47
+
48
+ cell.add_element(
49
+ name="Printbed",
50
+ translation=[1000, -1000, 340],
51
+ rotation=[0, 0, 90],
52
+ workframe=cell.work_frames[1],
53
+ filepath=Path("meshes/Printbed.stl").resolve(),
54
+ )
55
+
56
+ adxc.save(cell, "output")
57
+ # or: adxc.savezip(cell, "output")
58
+ ```
59
+
60
+ This creates a simple robot cell with a linear track, a process head, a workframe definition, and a physical element placed in the cell.
61
+
62
+ ## Equipment types
63
+
64
+ The library exposes convenience methods for the main equipment categories used in robot cells:
65
+
66
+ - `add_robot(robot)`: Adds a robot model (from `Robot` enum) and its default home position, kinematic chain, and work offsets.
67
+ - `add_track(track)`: Adds a linear motion axis or rail (from `Track` enum). This is the method for linear equipment attached to the robot or cell.
68
+ - `add_gantry(gantry)`: Adds a gantry-style equipment unit (from `Gantry` enum), typically used for multi-axis motion or large work envelopes.
69
+ - `add_positioner(positioner)`: Adds a rotating or positioning table (from `Positioner` enum), often used for workpiece orientation or part handling.
70
+
71
+ Equipment types are accessed through enums (e.g., `Robot.Comau.NJ165_30`, `Track.VanSichen.Comau()`) and support named parameters for configuration. These methods insert equipment into the cell and also register any required external-axis kinematics so the robot and attached motion devices are represented consistently in the exported cell definition.
72
+
73
+ ## Workframes
74
+
75
+ A workframe is a named coordinate system in the cell. Workframes are used to define where robot motion is relative to the fixture, machine, or workpiece. In `adxc`, each workframe has a name, translation, rotation, and optional limits for the grid used by the controller.
76
+
77
+ `Cell.add_workframe()` creates a new workframe and can assign it to a specific work offset index such as `G54`, `G55`, and so on (workoffset_index 1-4 for G54-G57, 5-24 for G505-G524). Grid parameters like `min_x`, `min_y`, `max_x`, `max_y`, and `grid_spacing` can be optionally specified to define motion boundaries. The first workframe is treated as the default cell work object, while additional workframes represent additional aligned coordinate systems.
78
+
79
+ ## Cell elements
80
+
81
+ A cell element is a physical item in the cell, such as a machine bed, fixture, conveyor component, or other object that should be positioned in the same coordinate system as the robot. These are represented with `CellElement` objects and are typically given a name, filepath (for an STL or mesh), translation, rotation, and an optional workframe reference.
82
+
83
+ `Cell.add_element()` is the normal way to create these objects and attach them to the cell.
84
+
85
+ ## Heads
86
+
87
+ A head represents the process tool or end-effector mounted on the robot. It can include the TCP definition, payload, file path to the tool geometry, and one or more `toolframes` describing tool offsets. `Cell.add_head()` registers the head on the robot with an optional `model` name, and `Head.add_toolframe()` adds tool definitions such as a TCP frame or process-specific tool orientation.
88
+
89
+ Toolframes support a `process` parameter (from the `Process` enum) to specify the type of process the tool performs, such as `Process.PELLET` for extrusion or other predefined processes.
90
+
91
+ Heads are important because they describe how the robot interacts with the workpiece or process, not just the robot body itself.
92
+
93
+ ## Saving a cell
94
+
95
+ After the cell is assembled, you can save it to disk using the module-level `save()` and `savezip()` functions:
96
+
97
+ ```python
98
+ adxc.save(cell, "output_dir")
99
+ adxc.savezip(cell, "output_dir")
100
+ ```
101
+
102
+ `save()` writes a `.adxc` cell file. `savezip()` packages the cell and any referenced resource files into a `.adxczip` archive.
103
+
104
+ ## Project status
105
+
106
+ This repository is made by reverse engineering .adxc files. Properties may difffer from actual implementation. Equipment GUIDs are created by reading cells created using AdaOne.
@@ -0,0 +1,17 @@
1
+ [project]
2
+ name = "adxc"
3
+ version = "0.1.0"
4
+ description = "Create cell files for AdaOne"
5
+ readme = "README.md"
6
+ requires-python = ">=3.14"
7
+ dependencies = [
8
+ "blackboxprotobuf>=1.0.1",
9
+ "pyyaml>=6.0",
10
+ ]
11
+
12
+ [build-system]
13
+ requires = ["setuptools>=68"]
14
+ build-backend = "setuptools.build_meta"
15
+
16
+ [tool.setuptools.packages.find]
17
+ where = ["src"]
adxc-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,103 @@
1
+ import tempfile
2
+ import zipfile
3
+ from pathlib import Path
4
+
5
+ import copy
6
+
7
+ from .fields import SensorField
8
+ from .library import Robot, Track, Gantry, Positioner, Process, WireArcMode, SensorShape, Sensor
9
+ from .cell import Cell, _build_adxc, _uri_to_path
10
+ from .nozzle import Nozzle
11
+
12
+
13
+ def _validate_meshes(cell):
14
+ objects = list(cell.robot.heads if cell.robot is not None else ())
15
+ objects.extend(cell.unknown_pending_heads)
16
+ objects.extend(cell.cell_elements)
17
+ for obj in objects:
18
+ filepath = getattr(obj, "filepath", "")
19
+ if filepath:
20
+ source = _uri_to_path(filepath)
21
+ if not source.is_file():
22
+ raise FileNotFoundError(f"Mesh file not found: {source}")
23
+
24
+
25
+ def save(value, output_dir="."):
26
+ """Save one cell or nozzle using a default path in the current directory."""
27
+ output_dir = Path(output_dir)
28
+ if isinstance(value, Cell):
29
+ _validate_meshes(value)
30
+ file_stem = value.name.replace(" ", "_")
31
+ output_dir = output_dir / value.name
32
+ output_dir.mkdir(parents=True, exist_ok=True)
33
+ path = output_dir / f"{file_stem}.adxc"
34
+ path.write_bytes(_build_adxc(value))
35
+ return path
36
+ if isinstance(value, Nozzle):
37
+ path = output_dir if output_dir.suffix == ".adxn" else output_dir / value.filename
38
+ return value.write(path)
39
+ raise TypeError("value must be a Cell or Nozzle")
40
+
41
+
42
+ def savezip(value, output_dir="."):
43
+ """Save a cell or one or more nozzles as an archive."""
44
+ output_dir = Path(output_dir)
45
+
46
+ if isinstance(value, Cell):
47
+
48
+ _validate_meshes(value)
49
+ cell = copy.deepcopy(value)
50
+ resources = {}
51
+ for obj in ([*cell.robot.heads] if cell.robot is not None else []) + cell.unknown_pending_heads + cell.cell_elements:
52
+ if obj.filepath:
53
+ source = _uri_to_path(obj.filepath)
54
+ resources[source.name] = source
55
+ obj.filepath = f"./resource/{source.name}"
56
+ stem = value.name
57
+ output_dir.mkdir(parents=True, exist_ok=True)
58
+ zip_path = output_dir / f"{stem}.adxczip"
59
+
60
+ with tempfile.TemporaryDirectory() as tmp:
61
+ folder = Path(tmp) / stem
62
+ resource_folder = folder / "resource"
63
+ resource_folder.mkdir(parents=True, exist_ok=True)
64
+ file_stem = stem.replace(" ", "_")
65
+ (folder / f"{file_stem}.adxc").write_bytes(_build_adxc(cell))
66
+ for name, source in resources.items():
67
+ (resource_folder / name).write_bytes(source.read_bytes())
68
+ with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as archive:
69
+ for file in folder.rglob("*"):
70
+ if file.is_file():
71
+ archive.write(file, file.relative_to(folder))
72
+ return zip_path
73
+
74
+ if isinstance(value, Nozzle):
75
+ nozzles = [value]
76
+
77
+ elif isinstance(value, (list, tuple)) and all(isinstance(item, Nozzle) for item in value):
78
+ nozzles = list(value)
79
+
80
+ else:
81
+ raise TypeError("value must be a Cell, Nozzle, or list of Nozzle objects")
82
+
83
+ if not nozzles:
84
+ raise ValueError("at least one nozzle is required")
85
+
86
+ path = output_dir if output_dir.suffix == ".zip" else output_dir / "nozzles.zip"
87
+ path.parent.mkdir(parents=True, exist_ok=True)
88
+ with tempfile.TemporaryDirectory() as temporary_directory:
89
+ temporary_directory = Path(temporary_directory)
90
+ files = []
91
+ for nozzle in nozzles:
92
+ temporary_path = temporary_directory / nozzle.filename
93
+ nozzle.write(temporary_path)
94
+ files.append(temporary_path)
95
+ with zipfile.ZipFile(path, "w", zipfile.ZIP_DEFLATED) as archive:
96
+ for temporary_path in files:
97
+ archive.write(temporary_path, temporary_path.name)
98
+ return path
99
+
100
+ __all__ = [
101
+ "Cell", "Process", "SensorShape", "Sensor", "SensorField", "WireArcMode", "Robot", "Track",
102
+ "Gantry", "Positioner", "save", "savezip",
103
+ ]