Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
47 changes: 40 additions & 7 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
id: check-codeowner
run: |
if grep -q "${{ github.actor }}" .github/CODEOWNERS; then
echo "::set-output name=is_codeowner::true"
echo "is_codeowner=true" >> "$GITHUB_OUTPUT"
echo "${{ github.actor }} is a codeowner, proceeding with release"
else
echo "::set-output name=is_codeowner::false"
echo "is_codeowner=false" >> "$GITHUB_OUTPUT"
echo "${{ github.actor }} is not a codeowner, aborting"
exit 1
fi
Expand All @@ -42,22 +42,55 @@ jobs:
with:
python-version: '3.10'

- name: Install and Configure Poetry
- name: Install and configure Poetry
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}
run: |
curl -sSL https://install.python-poetry.org | python3 -
export PATH="$HOME/.local/bin:$PATH"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
poetry config virtualenvs.create false
poetry config pypi-token.pypi $POETRY_PYPI_TOKEN_PYPI
poetry config pypi-token.pypi "$POETRY_PYPI_TOKEN_PYPI"

- name: Install dependencies
- name: Install root dependencies
run: |
poetry install --no-interaction --no-root

- name: Build package
- name: Build ir-support
run: |
poetry build

- name: Publish to PyPI
- name: Build extra robot package
working-directory: ir_support_extra_robots
run: |
poetry build

- name: Build extra parts package
working-directory: ir_support_extra_parts
run: |
poetry build

- name: Build full meta-package
working-directory: ir_support_full
run: |
poetry build

- name: Publish ir-support
run: |
poetry publish --no-interaction --verbose

- name: Publish extra robot package
working-directory: ir_support_extra_robots
run: |
poetry publish --no-interaction --verbose

- name: Publish extra parts package
working-directory: ir_support_extra_parts
run: |
poetry publish --no-interaction --verbose

- name: Publish full meta-package
working-directory: ir_support_full
run: |
poetry publish --no-interaction --verbose

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ env/
.venv/
venv/
ENV/
tests/_swift_screenshots/
123 changes: 123 additions & 0 deletions docs/extra_model_import_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Importing Extra Robot and Part Models

This note records the repeatable process for moving useful student-created models into the optional IR Support model packages. It is intended for maintainers who need to review a new assignment cohort without keeping the temporary batch scripts that were used during the first large import.

## Package Targets

Use the packages consistently:

- `ir_support`: core package for code and lab-required models.
- `ir_support_extra_robots`: optional robot models that are useful but not required for lab exercises.
- `ir_support_extra_parts`: optional parts, props, fixtures, safety items, and workcell objects.
- `ir_support_full`: meta-package that installs the core package and both extra model packages.

Avoid adding one-off assignment review scripts to the package permanently. Keep reusable inspection tools in `tests/` and put repeatable mesh-processing utilities in `tools/`.

## Source Audit

Search only the explicitly named assignment folders. Do not search upward from a OneDrive or network parent folder because that can accidentally hydrate cloud-only files or traverse thousands of unrelated files.

For robots, shortlist only models that are likely to be real commercial, educational, or open-source robot arms. Reject custom student-invented arms unless there is a strong reason to keep them. Also reject duplicates that are already available in Peter Corke's Robotics Toolbox, core `ir_support`, or `ir_support_extra_robots`, unless the new mesh is clearly better.

For parts, search common mesh types such as `.dae`, `.ply`, `.stl`, `.obj`, and `.blend`, but reject robot link meshes, whole environments, scene layouts, and objects that are too specific to one assignment. Prefer useful industrial robotics objects: workcell fixtures, safety equipment, controls and sensors, packaging, and manipulable objects.

Record accepted and rejected models in the relevant `MODEL_PROVENANCE.md` file so future maintainers do not re-check the same poor candidates.

## Candidate Checks

For each candidate, check:

- The name identifies the actual make and model where possible.
- The model is unique compared with the existing core and extra packages.
- Meshes have useful geometry and are not only simple placeholder cylinders or boxes.
- Meshes have sensible colours or materials, or can be recoloured without too much hand work.
- Dimensions are plausible in metres.
- The total DAE size is reasonable: aim for less than about 15 MB for a robot and less than about 4 MB for a single part.
- The object or robot sits on the ground plane in the expected orientation.
- Triangles render from both sides where the model would otherwise appear hollow.

If a mesh is invisible, extremely large, or tiny in Swift, inspect its vertex bounding box. Many student meshes are in millimetres and need a `0.001` scale conversion.

## Robot Model Checks

Before accepting a robot:

1. Confirm the robot appears to be a real model from a manufacturer or recognised open-source project.
2. Check the expected number of joints and broad reach against manufacturer information or a trusted model.
3. Compare DH parameters with similar robots already in the library.
4. Load the model in Swift and animate all joints, not only the first three.
5. Check the base pose, link order, joint axes, wrist links, and end-effector mounting face.
6. Remove non-standard grippers, suction cups, linear rails, or assignment tools unless they are part of the standard robot.
7. Add an explicit warning in the model docstring and provenance if a robot is useful but has a known visual limitation.

Use the general viewer for a single robot:

```bash
python tests/view_robot_model_swift.py --package extra --robot DensoVP6242
python tests/view_robot_model_swift.py --package core --robot UR3e
```

The viewer can be run with no arguments and then used through the Swift side-panel dropdown, or started with --package and --robot to choose an initial model. It cache-busts DAE files, animates every joint, prints basic diagnostics, and adds camera buttons for isometric, front, side, top, and wrist views.

## Part Model Checks

Before accepting a part:

1. Check the object is generally useful for industrial robotics teaching or assignments.
2. Check the bounding box is plausible in metres.
3. Put the object on the ground plane in its normal resting orientation.
4. Recolour plain white objects with simple, believable materials.
5. Put labels on the actual surface of the object, not floating nearby.
6. For labelled boxes and bottles, check the text is not mirrored or upside down from the main viewing directions.
7. Use double-sided geometry where thin signs, labels, cartons, or people appear hollow from one side.
8. Add the accepted object to `parts/categories.py` so it appears in the category viewer.

Use the category viewer for review:

```bash
python tests/view_extra_parts_by_category_swift.py --category "Safety Objects"
python tests/view_extra_parts_by_category_swift.py --category "Controls And Sensors"
```

## Blender and Mesh Processing

The most common Blender cleanup tasks are:

- Convert `.ply` or `.stl` files to `.dae` when Swift needs a Collada mesh.
- Scale millimetre models to metres.
- Apply transforms before export so the mesh origin and local axes are meaningful.
- Move each robot link mesh close to its own local joint frame.
- Remove assignment-specific grippers, rails, fixtures, or floating labels.
- Decimate large meshes until the visual quality is acceptable and the file size is reasonable.
- Recalculate normals and add double-sided faces where Swift shows see-through triangles.
- Use simple material colours rather than high-frequency noisy vertex colours.

STL files usually do not contain colour. If an STL import looks plain grey or white, recolour it manually or use manufacturer/reference images for guidance.

## Swift Review Notes

Swift and the browser can cache DAE assets. When reviewing edited meshes, use viewers that copy the meshes to a temporary cache-bust folder before adding them to Swift. This makes file names unique for each run and avoids old geometry appearing after a mesh has been fixed.

For efficient review, add camera buttons beside the viewer. A useful minimum set is isometric, front, side, top, and wrist or close-up. Move robots through repeated joint-space trajectories so disconnected links, wrong joint axes, and bad mesh origins become obvious.

## Provenance and Documentation

For every accepted model:

- Add the source and review notes to `MODEL_PROVENANCE.md`.
- Add the model to the package `__init__.py` or category registry.
- Update the relevant package README when the public list or category counts change.
- Update the Canvas simulated models page when the student-facing catalogue changes.

For every rejected model that took meaningful review time, add a short rejected note so it is not revisited later.

## Validation Before Commit

Run the relevant tests from the repository root:

```bash
python -m pytest tests/test_extra_robots.py tests/test_extra_parts.py tests/test_extra_part_categories.py tests/test_named_robot_model.py
```

Then visually inspect any newly imported models with the Swift viewers. Keep the final commit focused on accepted package assets, provenance, documentation, reusable tools, and tests. Do not commit temporary batch review scripts or screenshots.

3 changes: 3 additions & 0 deletions ir_support/robots/DensoVM6083/DensoVM6083.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
class DensoVM6083(UTSMeshRobot):
"""Denso VM6083 model ported from the UTS MATLAB toolbox."""


manufacturer_url = "https://www.denso-wave.com/en/robot/product/five-six/vm.html"
def __init__(self, base=None):
links = [
rtb.RevoluteDH(d=0.475, a=0.180, alpha=-pi / 2, qlim=self._qlim(-170, 170)),
Expand All @@ -27,3 +29,4 @@ def __init__(self, base=None):
home_q=[0.0] * 6,
base=base,
)

2 changes: 2 additions & 0 deletions ir_support/robots/DensoVS060/DensoVS060.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ def DensoVS060(base_offset=0.2):
robot = Robot(links, name=name)
robot.q = [0.0] * robot.n
robot.base = robot.base @ SE3(0, 0, base_offset)
robot.manufacturer_url = "https://www.denso-wave.com/en/robot/product/five-six/vs.html"
return robot

3 changes: 3 additions & 0 deletions ir_support/robots/DobotMagician/DobotMagician.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
class DobotMagician(UTSMeshRobot):
"""Dobot Magician model ported from the UTS MATLAB toolbox."""


manufacturer_url = "https://www.dobot-robots.com/products/education/magician.html"
def __init__(self, base=None):
links = [
rtb.RevoluteDH(d=0.1392, a=0.0, alpha=-pi / 2, qlim=self._qlim(-135, 135)),
Expand All @@ -26,3 +28,4 @@ def __init__(self, base=None):
home_q=[0.0] * 5,
base=base,
)

3 changes: 3 additions & 0 deletions ir_support/robots/Fetch/Fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
class Fetch(UTSMeshRobot):
"""Fetch arm model ported from the UTS MATLAB toolbox."""


reference_url = "https://docs.fetchrobotics.com/"
def __init__(self, base=None):
links = [
rtb.RevoluteDH(d=0.05, a=0.117, alpha=-pi / 2, qlim=self._qlim(-92, 92)),
Expand All @@ -32,3 +34,4 @@ def __init__(self, base=None):
base=base_transform,
)
self.tool = SE3.Rx(pi)

3 changes: 3 additions & 0 deletions ir_support/robots/HansCute/HansCute.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
class HansCute(UTSMeshRobot):
"""Hans Cute model ported from the UTS MATLAB toolbox."""


manufacturer_url = "https://www.hansrobot.net/"
def __init__(self, base=None):
links = [
rtb.RevoluteDH(d=0.15, a=0.0, alpha=pi / 2, offset=-pi / 2, qlim=self._qlim(-360, 360)),
Expand All @@ -28,3 +30,4 @@ def __init__(self, base=None):
home_q=[0.0] * 7,
base=base,
)

23 changes: 17 additions & 6 deletions ir_support/robots/LinearUR3/LinearUR3.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
import roboticstoolbox as rtb
import spatialmath.base as spb
from spatialmath import SE3
from ir_support.robots.DHRobot3D import DHRobot3D
from ir_support.robots.UTSMeshRobot import UTSMeshRobot
import time
import os

# Useful variables
from math import pi

# -----------------------------------------------------------------------------------#
class LinearUR3(DHRobot3D):
def __init__(self):
class LinearUR3(UTSMeshRobot):
reference_url = "https://www.universal-robots.com/products/ur3-robot/"

def __init__(self, base=None):
"""
UR3 Robot on a Linear Rail.
See the use of `UR3` and base class `DHRobot3D`
See the use of `UR3` and base class `UTSMeshRobot`

"""
# DH links
Expand Down Expand Up @@ -47,9 +49,17 @@ def __init__(self):
spb.transl(0.08535,0.603,-0.1225) @ spb.rpy2tr(0,pi/2,-pi/2, order='xyz')]

current_path = os.path.abspath(os.path.dirname(__file__))
super().__init__(links, link3D_names, name = 'LinearUR3', link3d_dir = current_path, qtest = qtest, qtest_transforms = qtest_transforms)
super().__init__(
links=links,
mesh_stem="LinearUR3",
mesh_dir=current_path,
name="LinearUR3",
home_q=qtest,
base=base,
link3d_names=link3D_names,
qtest_transforms=qtest_transforms,
)
self.base = self.base * SE3.Rx(pi/2) * SE3.Ry(pi/2)
self.q = qtest

# -----------------------------------------------------------------------------------#
def _create_DH(self):
Expand Down Expand Up @@ -96,3 +106,4 @@ def test(self):
input("Press enter to test movement of LinearUR3")
r.test()


23 changes: 17 additions & 6 deletions ir_support/robots/LinearUR5/LinearUR5.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
import roboticstoolbox as rtb
import spatialmath.base as spb
from spatialmath import SE3
from ir_support.robots.DHRobot3D import DHRobot3D
from ir_support.robots.UTSMeshRobot import UTSMeshRobot
import time
import os

# Useful variables
from math import pi

# -----------------------------------------------------------------------------------#
class LinearUR5(DHRobot3D):
def __init__(self):
class LinearUR5(UTSMeshRobot):
reference_url = "https://www.universal-robots.com/products/ur5-robot/"

def __init__(self, base=None):
"""
UR5 Robot on a Linear Rail.
See the use of `UR3`, `UR5` and base class `DHRobot3D`
See the use of `UR3`, `UR5` and base class `UTSMeshRobot`

"""
# DH links
Expand Down Expand Up @@ -47,9 +49,17 @@ def __init__(self):
spb.transl(-0.093429,0.97552,0.10818) @ spb.rpy2tr(0,0,-pi/2, order = 'xyz')]

current_path = os.path.abspath(os.path.dirname(__file__))
super().__init__(links, link3D_names, name = 'LinearUR5', link3d_dir = current_path, qtest = qtest, qtest_transforms = qtest_transforms)
super().__init__(
links=links,
mesh_stem="LinearUR5",
mesh_dir=current_path,
name="LinearUR5",
home_q=qtest,
base=base,
link3d_names=link3D_names,
qtest_transforms=qtest_transforms,
)
self.base = self.base * SE3.Rx(pi/2) * SE3.Ry(pi/2)
self.q = qtest

# -----------------------------------------------------------------------------------#
def _create_DH(self):
Expand Down Expand Up @@ -95,3 +105,4 @@ def test(self):
r.test()



3 changes: 3 additions & 0 deletions ir_support/robots/Sawyer/Sawyer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
class Sawyer(UTSMeshRobot):
"""Sawyer model ported from the UTS MATLAB toolbox."""


manufacturer_url = "https://www.rethinkrobotics.com/sawyer"
def __init__(self, base=None):
links = [
rtb.RevoluteDH(d=0.317, a=0.081, alpha=-pi / 2, qlim=self._qlim(-175, 175)),
Expand All @@ -28,3 +30,4 @@ def __init__(self, base=None):
home_q=[0.0, -pi / 2, 0.0, -pi / 2, 0.0, pi / 2, 0.0],
base=base,
)

3 changes: 3 additions & 0 deletions ir_support/robots/UR10/UR10.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
class UR10(UTSMeshRobot):
"""Universal Robots UR10 model ported from the UTS MATLAB toolbox."""


manufacturer_url = "https://www.universal-robots.com/products/ur10-robot/"
def __init__(self, base=None):
links = [
rtb.RevoluteDH(d=0.128, a=0.0, alpha=pi / 2, qlim=self._qlim(-360, 360)),
Expand All @@ -27,3 +29,4 @@ def __init__(self, base=None):
home_q=[0.0, -pi / 2, 0.0, 0.0, 0.0, 0.0],
base=base,
)

Loading
Loading