Skip to content

Commit

Permalink
feat(RPS-976): added integration test CI (#25)
Browse files Browse the repository at this point in the history
Co-authored-by: cbiering <christoph.biering@wandelbots.com>
  • Loading branch information
biering and cbiering authored Jan 22, 2025
1 parent 6e3e672 commit 15fc353
Show file tree
Hide file tree
Showing 15 changed files with 520 additions and 219 deletions.
11 changes: 2 additions & 9 deletions .github/workflows/ci-dev.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Test, Lint and Format
name: Typecheck, Lint and Format

on:
pull_request:
Expand All @@ -15,7 +15,7 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.10
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
Expand All @@ -24,12 +24,6 @@ jobs:
run: |
pip install poetry
poetry install
mkdir envs
touch envs/.env.tests
echo "NOVA_API=test.instance.mock.io" > envs/.env.tests
echo "CELL_NAME=cell" >> envs/.env.tests
echo "MOTION_GROUP=virtual-robot" >> envs/.env.tests
echo "TCP=Flange" >> envs/.env.tests
- name: Check formatting with ruff
run: poetry run ruff format --check .
Expand All @@ -42,5 +36,4 @@ jobs:

- name: Run tests
run: |
cp envs/.env.tests envs/test_.env.tests
PYTHONPATH=. poetry run pytest -rs -v
85 changes: 0 additions & 85 deletions .github/workflows/integration-test.yaml

This file was deleted.

90 changes: 90 additions & 0 deletions .github/workflows/run-examples.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Run examples

on:
pull_request:
branches:
- main

jobs:
run-examples:
runs-on: ubuntu-latest

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true

strategy:
fail-fast: false
max-parallel: 1
matrix:
example_file:
- "01_basic.py"
- "02_plan_and_execute.py"
- "03_move_and_set_ios.py"
- "04_move_multiple_robots.py"
- "05_selection_motion_group_activation.py"
- "06_api_usage.py"

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Create NOVA instance and check connection
env:
PORTAL_STG_REFRESH_URL: ${{ secrets.PORTAL_STG_REFRESH_URL }}
PORTAL_STG_REFRESH_CLIENT_ID: ${{ secrets.PORTAL_STG_REFRESH_CLIENT_ID }}
PORTAL_STG_REFRESH_TOKEN: ${{ secrets.PORTAL_STG_REFRESH_TOKEN }}
API_VERSION: "v1"
# Optional
PROJECT_VERSION: "1.0.0"
GITHUB_RUN_ID: ${{ github.run_id }}
INSECURE_CURL: "true" # If you need to skip SSL verification
run: |
source ./scripts/create_nova_instance.sh
echo $PORTAL_STG_HOST
echo "PORTAL_STG_HOST=$PORTAL_STG_HOST" >> $GITHUB_ENV
echo "PORTAL_STG_INSTANCE_ID=$PORTAL_STG_INSTANCE_ID" >> $GITHUB_ENV
echo "PORTAL_STG_ACCESS_TOKEN=$PORTAL_STG_ACCESS_TOKEN" >> $GITHUB_ENV
- name: Set up Python environment
run: |
pip install poetry
poetry install
- name: "Run example: examples/${{ matrix.example_file }}"
run: |
touch ./.env
echo "NOVA_API=https://${{ env.PORTAL_STG_HOST }}" >> ./.env
echo "NOVA_ACCESS_TOKEN=${{ env.PORTAL_STG_ACCESS_TOKEN }}" >> ./.env
echo "CELL_NAME=cell" >> ./.env
n=0
max_retries=3
until [ $n -ge $max_retries ]
do
echo "Attempt $((n+1)) to run ${{ matrix.example_file }}..."
PYTHONPATH=. poetry run python examples/${{ matrix.example_file }} && break
n=$((n+1))
echo "Failed attempt $n. Retrying in 5s..."
sleep 5
done
if [ $n -ge $max_retries ]; then
echo "Failed after $max_retries attempts."
exit 1
fi
# Always run cleanup, whether success or failure
- name: Cleanup - Delete instance
if: always()
run: |
./scripts/delete_nova_instance.sh
env:
PORTAL_STG_INSTANCE_ID: ${{ env.PORTAL_STG_INSTANCE_ID }}
PORTAL_STG_ACCESS_TOKEN: ${{ env.PORTAL_STG_ACCESS_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
devportal.env
.devcontainer/devcontainer.env
# from Makefile generated
.formatted
Expand Down
4 changes: 4 additions & 0 deletions devportal.env.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export PORTAL_STG_REFRESH_URL=""
export PORTAL_STG_REFRESH_TOKEN=""
export PORTAL_STG_REFRESH_CLIENT_ID=""
export API_VERSION="v1"
39 changes: 20 additions & 19 deletions examples/01_basic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio

from nova import Nova
from nova.api import models

"""
Example: Getting the current state of a robot.
Expand All @@ -13,31 +14,31 @@
async def main():
async with Nova() as nova:
cell = nova.cell()
controllers = await cell.controllers()
controller = controllers[0]
controller = await cell.ensure_virtual_robot_controller(
"ur",
models.VirtualControllerTypes.UNIVERSALROBOTS_MINUS_UR10E,
models.Manufacturer.UNIVERSALROBOTS,
)

async with controller:
activated_motion_group_ids = await controller.activated_motion_group_ids()
print(activated_motion_group_ids)
async with controller[0] as motion_group:
tcp_names = await motion_group.tcp_names()
print(tcp_names)

motion_group = controller[0]
tcp = tcp_names[0]

tcp_names = await motion_group.tcp_names()
print(tcp_names)
# Current motion group state
state = await motion_group.get_state(tcp)
print(state)

tcp = tcp_names[0]
# Current joints positions
joints = await motion_group.joints()
print(joints)

# Current motion group state
state = await motion_group.get_state(tcp)
print(state)
# Current TCP pose
tcp_pose = await motion_group.tcp_pose(tcp)
print(tcp_pose)

# Current joints positions
joints = await motion_group.joints()
print(joints)

# Current TCP pose
tcp_pose = await motion_group.tcp_pose(tcp)
print(tcp_pose)
await cell.delete_robot_controller(controller.name)


if __name__ == "__main__":
Expand Down
58 changes: 31 additions & 27 deletions examples/02_plan_and_execute.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio

from nova.api import models
from nova import Nova, MotionSettings
from nova.actions import jnt, ptp
from nova.types import Pose
Expand All @@ -13,32 +14,35 @@


async def main():
nova = Nova()
cell = nova.cell()
controllers = await cell.controllers()
controller = controllers[0]

# Connect to the controller and activate motion groups
async with controller[0] as motion_group:
home_joints = await motion_group.joints()
tcp_names = await motion_group.tcp_names()
tcp = tcp_names[0]

# Get current TCP pose and offset it slightly along the x-axis
current_pose = await motion_group.tcp_pose(tcp)
target_pose = current_pose @ Pose((1, 0, 0, 0, 0, 0))

actions = [
jnt(home_joints),
ptp(target_pose),
jnt(home_joints),
ptp(target_pose @ [100, 0, 0, 0, 0, 0]),
jnt(home_joints),
ptp(target_pose @ (100, 100, 0, 0, 0, 0)),
jnt(home_joints),
ptp(target_pose @ Pose((0, 100, 0, 0, 0, 0))),
jnt(home_joints),
]
async with Nova() as nova:
cell = nova.cell()
controller = await cell.ensure_virtual_robot_controller(
"ur",
models.VirtualControllerTypes.UNIVERSALROBOTS_MINUS_UR10E,
models.Manufacturer.UNIVERSALROBOTS,
)

# Connect to the controller and activate motion groups
async with controller[0] as motion_group:
home_joints = await motion_group.joints()
tcp_names = await motion_group.tcp_names()
tcp = tcp_names[0]

# Get current TCP pose and offset it slightly along the x-axis
current_pose = await motion_group.tcp_pose(tcp)
target_pose = current_pose @ Pose((1, 0, 0, 0, 0, 0))

actions = [
jnt(home_joints),
ptp(target_pose),
jnt(home_joints),
ptp(target_pose @ [50, 0, 0, 0, 0, 0]),
jnt(home_joints),
ptp(target_pose @ (50, 100, 0, 0, 0, 0)),
jnt(home_joints),
ptp(target_pose @ Pose((0, 50, 0, 0, 0, 0))),
jnt(home_joints),
]

# you can update the settings of the action
for action in actions:
Expand All @@ -47,7 +51,7 @@ async def main():
joint_trajectory = await motion_group.plan(actions, tcp)
await motion_group.execute(joint_trajectory, tcp, actions=actions)

await nova.close()
await cell.delete_robot_controller(controller.name)


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit 15fc353

Please sign in to comment.