From e13d60061acf76e88924152dde9ca4f059b5c7ef Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 20 Dec 2024 10:47:20 +0100 Subject: [PATCH 1/7] feat: handle https, add some convenience methods --- .env.template | 7 ++- .github/workflows/ci-dev.yaml | 4 +- README.md | 2 +- examples/01_basic.py | 6 +-- examples/02_plan_and_execute.py | 3 +- examples/03_move_and_set_ios.py | 3 +- nova/core/motion_group.py | 92 +++++++++++++++++++-------------- nova/core/nova.py | 21 ++++++-- nova/gateway.py | 15 ++++-- 9 files changed, 96 insertions(+), 57 deletions(-) diff --git a/.env.template b/.env.template index 180308b..a6d5e84 100644 --- a/.env.template +++ b/.env.template @@ -1,9 +1,12 @@ +# The endpoint where the API is reachable from the container serving the Application. +NOVA_API="http://api-gateway.wandelbots.svc.cluster.local:8080" +# The name of the cell to be used for the Application. +CELL_NAME="cell" + # Using username/password authentication -NOVA_HOST="https://nova.example.com" NOVA_USERNAME="my_username" NOVA_PASSWORD="my_password" # NOVA_ACCESS_TOKEN="" # Leave empty if not using token-based authentication # Using token-based authentication (comment out username/password lines) -# NOVA_HOST="https://nova.example.com" # NOVA_ACCESS_TOKEN="eyJhbGciOi..." diff --git a/.github/workflows/ci-dev.yaml b/.github/workflows/ci-dev.yaml index 3e9be1b..0b50618 100644 --- a/.github/workflows/ci-dev.yaml +++ b/.github/workflows/ci-dev.yaml @@ -26,8 +26,8 @@ jobs: poetry install mkdir envs touch envs/.env.tests - echo "NOVA_HOST=test.instance.mock.io" > envs/.env.tests - echo "CELL_ID=cell" >> 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 diff --git a/README.md b/README.md index 84f2504..932d743 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ poetry install | Variable | Description | Required | Default | Example | |---------------------|---------------------------------------------------------------------------|----------|---------|----------------------------| -| `NOVA_HOST` | The base URL or hostname of the NOVA server instance. | Yes | None | `https://nova.example.com` | +| `NOVA_API` | The base URL or hostname of the NOVA server instance. | Yes | None | `https://nova.example.com` | | `NOVA_USERNAME` | The username credential used for authentication with the NOVA service. | Yes* | None | `my_username` | | `NOVA_PASSWORD` | The password credential used in conjunction with `NOVA_USERNAME`. | Yes* | None | `my_password` | | `NOVA_ACCESS_TOKEN` | A pre-obtained access token for NOVA if using token-based authentication. | Yes* | None | `eyJhbGciOi...` | diff --git a/examples/01_basic.py b/examples/01_basic.py index 8dd33ce..02fcd73 100644 --- a/examples/01_basic.py +++ b/examples/01_basic.py @@ -4,10 +4,10 @@ async def main(): - nova = Nova() + nova = Nova(host="172.30.0.135") cell = nova.cell() - controller = await cell.controller("ur") - + controllers = await cell.controllers() + controller = controllers[0] motion_group = controller[0] # Current motion group state diff --git a/examples/02_plan_and_execute.py b/examples/02_plan_and_execute.py index 513db27..2ed5c02 100644 --- a/examples/02_plan_and_execute.py +++ b/examples/02_plan_and_execute.py @@ -10,7 +10,8 @@ async def main(): nova = Nova() cell = nova.cell() - controller = await cell.controller("ur") + controllers = await cell.controllers() + controller = controllers[0] # Define a home position home_joints = (0, -pi / 4, -pi / 4, -pi / 4, pi / 4, 0) diff --git a/examples/03_move_and_set_ios.py b/examples/03_move_and_set_ios.py index 6542f43..82a9073 100644 --- a/examples/03_move_and_set_ios.py +++ b/examples/03_move_and_set_ios.py @@ -10,7 +10,8 @@ async def main(): nova = Nova() cell = nova.cell() - controller = await cell.controller("ur") + controllers = await cell.controllers() + controller = controllers[0] # Define a home position home_joints = (0, -pi / 4, -pi / 4, -pi / 4, pi / 4, 0) diff --git a/nova/core/motion_group.py b/nova/core/motion_group.py index 7828ce4..4b896c6 100644 --- a/nova/core/motion_group.py +++ b/nova/core/motion_group.py @@ -44,6 +44,32 @@ def current_motion(self) -> str: # raise ValueError("No MotionId attached. There is no planned motion available.") return self._current_motion + async def plan(self, actions: list[Action], tcp: str) -> wb.models.JointTrajectory: + current_joints = await self.joints(tcp=tcp) + robot_setup = await self._get_optimizer_setup(tcp=tcp) + motion_commands = CombinedActions(items=actions).to_motion_command() + + request = wb.models.PlanTrajectoryRequest( + robot_setup=robot_setup, + motion_group=self.motion_group_id, + start_joint_position=current_joints.joints, + motion_commands=motion_commands, + tcp=tcp, + ) + + motion_api_client = self._api_gateway.motion_api + plan_response = await motion_api_client.plan_trajectory( + cell=self._cell, plan_trajectory_request=request + ) + + if isinstance( + plan_response.response.actual_instance, wb.models.PlanTrajectoryFailedResponse + ): + failed_response = plan_response.response.actual_instance + raise PlanTrajectoryFailed(failed_response) + + return plan_response.response.actual_instance + async def run( self, actions: list[Action] | Action, @@ -80,20 +106,6 @@ async def run( _movement_controller = movement_controller(movement_controller_context) await self._api_gateway.motion_api.execute_trajectory(self._cell, _movement_controller) - async def get_state(self, tcp: str) -> wb.models.MotionGroupStateResponse: - response = await self._api_gateway.motion_group_infos_api.get_current_motion_group_state( - cell=self._cell, motion_group=self.motion_group_id, tcp=tcp - ) - return response - - async def joints(self, tcp: str) -> wb.models.Joints: - state = await self.get_state(tcp=tcp) - return state.state.joint_position - - async def tcp_pose(self, tcp: str) -> Pose: - state = await self.get_state(tcp=tcp) - return Pose(state.state.tcp_pose) - async def _get_number_of_joints(self) -> int: spec = await self._api_gateway.motion_group_infos_api.get_motion_group_specification( cell=self._cell, motion_group=self.motion_group_id @@ -105,32 +117,6 @@ async def _get_optimizer_setup(self, tcp: str) -> wb.models.OptimizerSetup: cell=self._cell, motion_group=self._motion_group_id, tcp=tcp ) - async def plan(self, actions: list[Action], tcp: str) -> wb.models.JointTrajectory: - current_joints = await self.joints(tcp=tcp) - robot_setup = await self._get_optimizer_setup(tcp=tcp) - motion_commands = CombinedActions(items=actions).to_motion_command() - - request = wb.models.PlanTrajectoryRequest( - robot_setup=robot_setup, - motion_group=self.motion_group_id, - start_joint_position=current_joints.joints, - motion_commands=motion_commands, - tcp=tcp, - ) - - motion_api_client = self._api_gateway.motion_api - plan_response = await motion_api_client.plan_trajectory( - cell=self._cell, plan_trajectory_request=request - ) - - if isinstance( - plan_response.response.actual_instance, wb.models.PlanTrajectoryFailedResponse - ): - failed_response = plan_response.response.actual_instance - raise PlanTrajectoryFailed(failed_response) - - return plan_response.response.actual_instance - async def _load_planned_motion( self, joint_trajectory: wb.models.JointTrajectory, tcp: str ) -> wb.models.PlanSuccessfulResponse: @@ -176,3 +162,29 @@ async def stop(self): logger.debug(f"Motion {self.current_motion} stopped.") except ValueError as e: logger.debug(f"No motion to stop for {self}: {e}") + + async def get_state(self, tcp: str | None) -> wb.models.MotionGroupStateResponse: + """Get the current state of the motion group + + Args: + tcp (str): The identifier of the tool center point (TCP) to be used for tcp_pose in response. If not set, + the flange pose is returned as tcp_pose. + """ + response = await self._api_gateway.motion_group_infos_api.get_current_motion_group_state( + cell=self._cell, motion_group=self.motion_group_id, tcp=tcp + ) + return response + + async def joints(self, tcp: str) -> wb.models.Joints: + state = await self.get_state(tcp=tcp) + return state.state.joint_position + + async def tcp_pose(self, tcp: str) -> Pose: + state = await self.get_state(tcp=tcp) + return Pose(state.state.tcp_pose) + + async def tcps(self) -> list[wb.models.RobotTcp]: + return (await self._api_gateway.motion_group_infos_api.list_tcps()).tcps + + async def tcp_names(self) -> list[str]: + return [tcp.id for tcp in await self.tcps()] diff --git a/nova/core/nova.py b/nova/core/nova.py index 169e50a..2d1dc18 100644 --- a/nova/core/nova.py +++ b/nova/core/nova.py @@ -1,6 +1,8 @@ from nova.core.controller import Controller from nova.core.exceptions import ControllerNotFoundException from nova.gateway import ApiGateway +import wandelbots_api_client as wb +from decouple import config class Nova: @@ -21,7 +23,7 @@ def __init__( version=version, ) - def cell(self, cell_id: str = "cell") -> "Cell": + def cell(self, cell_id: str = config("CELL_NAME", "cell")) -> "Cell": return Cell(self._api_client, cell_id) @@ -30,11 +32,22 @@ def __init__(self, api_gateway: ApiGateway, cell_id: str): self._api_gateway = api_gateway self._cell_id = cell_id - async def controller(self, controller_host: str = None) -> "Controller": + async def _get_controllers(self) -> list[wb.models.ControllerInstance]: controller_api = self._api_gateway.controller_api - controller_list = await controller_api.list_controllers(cell=self._cell_id) + response = await controller_api.list_controllers(cell=self._cell_id) + return response.instances + + async def controllers(self) -> list["Controller"]: + controllers = await self._get_controllers() + return [ + Controller(api_gateway=self._api_gateway, cell=self._cell_id, controller_host=c.host) + for c in controllers + ] + + async def controller(self, controller_host: str = None) -> "Controller": + controllers = await self._get_controllers() found_controller = next( - (c for c in controller_list.instances if c.host == controller_host), None + (c for c in controllers if c.host == controller_host), None ) if found_controller is None: diff --git a/nova/gateway.py b/nova/gateway.py index 15184c0..fd7511a 100644 --- a/nova/gateway.py +++ b/nova/gateway.py @@ -54,18 +54,23 @@ def sync_wrapper(*args, **kwargs): return Interceptor(api_instance) +def _validate_host(host: str) -> str: + """Remove any trailing slashes and validate scheme""" + _url = host.rstrip("/") + return _url + class ApiGateway: def __init__( self, *, - host: str | None = None, + host: str = "http://api-gateway.wandelbots.svc.cluster.local:8080", username: str | None = None, password: str | None = None, access_token: str | None = None, version: str = "v1", ): if host is None: - host = config("NOVA_HOST") + host = config("NOVA_API") if username is None: username = config("NOVA_USERNAME", default=None) @@ -76,8 +81,12 @@ def __init__( if access_token is None: access_token = config("NOVA_ACCESS_TOKEN", default=None) + if (username is None or password is None) and access_token is None: + raise ValueError("Please provide either username and password or an access token") + + stripped_host = host.rstrip("/") api_client_config = wb.Configuration( - host=f"http://{host}/api/{version}", + host=f"{stripped_host}/api/{version}", username=username, password=password, access_token=access_token, From bbff5db5123bf6fb3e9e4ac8c58e6ef335f68a6b Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 20 Dec 2024 10:55:29 +0100 Subject: [PATCH 2/7] fix --- examples/01_basic.py | 2 +- nova/core/nova.py | 6 ++---- nova/gateway.py | 13 ++++++------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/examples/01_basic.py b/examples/01_basic.py index 02fcd73..b8c9191 100644 --- a/examples/01_basic.py +++ b/examples/01_basic.py @@ -4,7 +4,7 @@ async def main(): - nova = Nova(host="172.30.0.135") + nova = Nova() cell = nova.cell() controllers = await cell.controllers() controller = controllers[0] diff --git a/nova/core/nova.py b/nova/core/nova.py index 2d1dc18..7488d9f 100644 --- a/nova/core/nova.py +++ b/nova/core/nova.py @@ -23,7 +23,7 @@ def __init__( version=version, ) - def cell(self, cell_id: str = config("CELL_NAME", "cell")) -> "Cell": + def cell(self, cell_id: str = config("CELL_NAME", default="cell")) -> "Cell": return Cell(self._api_client, cell_id) @@ -46,9 +46,7 @@ async def controllers(self) -> list["Controller"]: async def controller(self, controller_host: str = None) -> "Controller": controllers = await self._get_controllers() - found_controller = next( - (c for c in controllers if c.host == controller_host), None - ) + found_controller = next((c for c in controllers if c.host == controller_host), None) if found_controller is None: raise ControllerNotFoundException(controller=controller_host) diff --git a/nova/gateway.py b/nova/gateway.py index fd7511a..e34d8e1 100644 --- a/nova/gateway.py +++ b/nova/gateway.py @@ -9,6 +9,8 @@ T = TypeVar("T") +INTERNAL_CLUSTER_NOVA_API = "http://api-gateway.wandelbots.svc.cluster.local:8080" + def intercept(api_instance: T) -> T: class Interceptor: @@ -54,23 +56,20 @@ def sync_wrapper(*args, **kwargs): return Interceptor(api_instance) -def _validate_host(host: str) -> str: - """Remove any trailing slashes and validate scheme""" - _url = host.rstrip("/") - return _url - class ApiGateway: def __init__( self, *, - host: str = "http://api-gateway.wandelbots.svc.cluster.local:8080", + host: str | None = None, username: str | None = None, password: str | None = None, access_token: str | None = None, version: str = "v1", ): if host is None: - host = config("NOVA_API") + host = config("NOVA_API", default=INTERNAL_CLUSTER_NOVA_API) + + print() if username is None: username = config("NOVA_USERNAME", default=None) From 66a526b1764f1458b05e3e74f67215abdedb06e0 Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 20 Dec 2024 11:02:17 +0100 Subject: [PATCH 3/7] fix --- examples/01_basic.py | 12 ++++++++---- nova/core/motion_group.py | 7 +++++-- nova/gateway.py | 3 +-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/examples/01_basic.py b/examples/01_basic.py index b8c9191..d627e33 100644 --- a/examples/01_basic.py +++ b/examples/01_basic.py @@ -1,5 +1,4 @@ import asyncio - from nova import Nova @@ -10,16 +9,21 @@ async def main(): controller = controllers[0] motion_group = controller[0] + tcp_names = await motion_group.tcp_names() + print(tcp_names) + + tcp = tcp_names[0] + # Current motion group state - state = await motion_group.get_state("Flange") + state = await motion_group.get_state(tcp) print(state) # Current joints positions - joints = await motion_group.joints("Flange") + joints = await motion_group.joints() print(joints) # Current TCP pose - tcp_pose = await motion_group.tcp_pose("Flange") + tcp_pose = await motion_group.tcp_pose(tcp) print(tcp_pose) diff --git a/nova/core/motion_group.py b/nova/core/motion_group.py index 4b896c6..9f00b88 100644 --- a/nova/core/motion_group.py +++ b/nova/core/motion_group.py @@ -175,7 +175,7 @@ async def get_state(self, tcp: str | None) -> wb.models.MotionGroupStateResponse ) return response - async def joints(self, tcp: str) -> wb.models.Joints: + async def joints(self, tcp: str | None = None) -> wb.models.Joints: state = await self.get_state(tcp=tcp) return state.state.joint_position @@ -184,7 +184,10 @@ async def tcp_pose(self, tcp: str) -> Pose: return Pose(state.state.tcp_pose) async def tcps(self) -> list[wb.models.RobotTcp]: - return (await self._api_gateway.motion_group_infos_api.list_tcps()).tcps + response = await self._api_gateway.motion_group_infos_api.list_tcps( + cell=self._cell, motion_group=self.motion_group_id + ) + return response.tcps async def tcp_names(self) -> list[str]: return [tcp.id for tcp in await self.tcps()] diff --git a/nova/gateway.py b/nova/gateway.py index e34d8e1..720ee3a 100644 --- a/nova/gateway.py +++ b/nova/gateway.py @@ -69,8 +69,6 @@ def __init__( if host is None: host = config("NOVA_API", default=INTERNAL_CLUSTER_NOVA_API) - print() - if username is None: username = config("NOVA_USERNAME", default=None) @@ -93,6 +91,7 @@ def __init__( ) self._api_client = wb.ApiClient(api_client_config) + self._host = host # Use the intercept function to wrap each API client self.controller_api = intercept(wb.ControllerApi(api_client=self._api_client)) From 5f6a0795f6b88226b9e7db52c8e3b8e729c9262e Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 20 Dec 2024 11:13:18 +0100 Subject: [PATCH 4/7] fix --- examples/02_plan_and_execute.py | 9 ++++++--- examples/03_move_and_set_ios.py | 14 +++++++------- examples/04_move_multiple_robots.py | 9 ++++++--- examples/05_selection_motion_group_activation.py | 11 ++++++----- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/examples/02_plan_and_execute.py b/examples/02_plan_and_execute.py index 2ed5c02..deb5e87 100644 --- a/examples/02_plan_and_execute.py +++ b/examples/02_plan_and_execute.py @@ -17,9 +17,12 @@ async def main(): home_joints = (0, -pi / 4, -pi / 4, -pi / 4, pi / 4, 0) # Connect to the controller and activate motion groups - async with controller[0] as mg: + async with controller[0] as motion_group: + 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 mg.tcp_pose("Flange") + current_pose = await motion_group.tcp_pose(tcp) target_pose = current_pose @ Pose((1, 0, 0, 0, 0, 0)) actions = [ @@ -36,7 +39,7 @@ async def main(): jnt(home_joints), ] - await mg.run(actions, tcp="Flange", movement_controller=move_forward) + await motion_group.run(actions, tcp=tcp, movement_controller=move_forward) if __name__ == "__main__": diff --git a/examples/03_move_and_set_ios.py b/examples/03_move_and_set_ios.py index 82a9073..821834d 100644 --- a/examples/03_move_and_set_ios.py +++ b/examples/03_move_and_set_ios.py @@ -11,17 +11,17 @@ async def main(): nova = Nova() cell = nova.cell() controllers = await cell.controllers() - controller = controllers[0] # Define a home position home_joints = (0, -pi / 4, -pi / 4, -pi / 4, pi / 4, 0) # Connect to the controller and activate motion groups - async with controller: - motion_group = controller.motion_group() + async with controllers[0] as motion_group: + 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("Flange") + current_pose = await motion_group.tcp_pose(tcp) target_pose = current_pose @ Pose((100, 0, 0, 0, 0, 0)) actions = [ jnt(home_joints), @@ -39,9 +39,9 @@ async def main(): def print_motion(motion): print(motion) - await motion_group.run(actions, tcp="Flange", initial_movement_consumer=print_motion) - await motion_group.run(actions, tcp="Flange") - await motion_group.run(ptp(target_pose), tcp="Flange") + await motion_group.run(actions, tcp=tcp, initial_movement_consumer=print_motion) + await motion_group.run(actions, tcp=tcp) + await motion_group.run(ptp(target_pose), tcp=tcp) if __name__ == "__main__": diff --git a/examples/04_move_multiple_robots.py b/examples/04_move_multiple_robots.py index b0938d5..f85c230 100644 --- a/examples/04_move_multiple_robots.py +++ b/examples/04_move_multiple_robots.py @@ -7,12 +7,15 @@ async def move_robot(controller: Controller): home_joints = (0, -pi / 4, -pi / 4, -pi / 4, pi / 4, 0) - async with controller[0] as mg: - current_pose = await mg.tcp_pose("Flange") + async with controller[0] as motion_group: + tcp_names = await motion_group.tcp_names() + tcp = tcp_names[0] + + current_pose = await motion_group.tcp_pose(tcp) target_pose = current_pose @ (100, 0, 0, 0, 0, 0) actions = [jnt(home_joints), ptp(target_pose), jnt(home_joints)] - await mg.run(actions, tcp="Flange", movement_controller=speed_up_movement_controller) + await motion_group.run(actions, tcp=tcp, movement_controller=speed_up_movement_controller) async def main(): diff --git a/examples/05_selection_motion_group_activation.py b/examples/05_selection_motion_group_activation.py index 29c7e3d..aaf7138 100644 --- a/examples/05_selection_motion_group_activation.py +++ b/examples/05_selection_motion_group_activation.py @@ -16,7 +16,7 @@ import asyncio -async def move_robot(motion_group: MotionGroup): +async def move_robot(motion_group: MotionGroup, tcp: str): home_pose = Pose((200, 200, 600, 0, pi, 0)) target_pose = home_pose @ (100, 0, 0, 0, 0, 0) actions = [ @@ -27,7 +27,7 @@ async def move_robot(motion_group: MotionGroup): ptp(home_pose), ] - await motion_group.run(actions, tcp="Flange") + await motion_group.run(actions, tcp=tcp) async def main(): @@ -35,8 +35,9 @@ async def main(): cell = nova.cell() ur = await cell.controller("ur") kuka = await cell.controller("kuka") + tcp = "Flange" - flange_state = await ur[0].get_state("Flange") + flange_state = await ur[0].get_state(tcp=tcp) print(flange_state) # activate all motion groups @@ -53,13 +54,13 @@ async def main(): # activate motion group 0 from two different controllers async with ur[0] as ur_0_mg, kuka[0] as kuka_0_mg: - await asyncio.gather(move_robot(ur_0_mg), move_robot(kuka_0_mg)) + await asyncio.gather(move_robot(ur_0_mg, tcp), move_robot(kuka_0_mg, tcp)) # activate motion group 0 from two different controllers mg_0 = ur.motion_group(0) mg_1 = kuka.motion_group(0) async with mg_0, mg_1: - await asyncio.gather(move_robot(mg_0), move_robot(mg_1)) + await asyncio.gather(move_robot(mg_0, tcp), move_robot(mg_1, tcp)) if __name__ == "__main__": From 4a186d07f67df1cc603848de2561f34c8cf5b152 Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 20 Dec 2024 11:16:35 +0100 Subject: [PATCH 5/7] fix --- nova/core/motion_group.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nova/core/motion_group.py b/nova/core/motion_group.py index 9f00b88..5f65c16 100644 --- a/nova/core/motion_group.py +++ b/nova/core/motion_group.py @@ -176,18 +176,22 @@ async def get_state(self, tcp: str | None) -> wb.models.MotionGroupStateResponse return response async def joints(self, tcp: str | None = None) -> wb.models.Joints: + """Get the current joint positions""" state = await self.get_state(tcp=tcp) return state.state.joint_position - async def tcp_pose(self, tcp: str) -> Pose: + async def tcp_pose(self, tcp: str | None = None) -> Pose: + """Get the current TCP pose""" state = await self.get_state(tcp=tcp) return Pose(state.state.tcp_pose) async def tcps(self) -> list[wb.models.RobotTcp]: + """Get the available tool center points (TCPs)""" response = await self._api_gateway.motion_group_infos_api.list_tcps( cell=self._cell, motion_group=self.motion_group_id ) return response.tcps async def tcp_names(self) -> list[str]: + """Get the names of the available tool center points (TCPs)""" return [tcp.id for tcp in await self.tcps()] From 390e91471db89db175cd9f73dfe707837caaf6d9 Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 20 Dec 2024 11:38:34 +0100 Subject: [PATCH 6/7] fix --- nova/core/nova.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nova/core/nova.py b/nova/core/nova.py index 7488d9f..f0b3a9e 100644 --- a/nova/core/nova.py +++ b/nova/core/nova.py @@ -33,8 +33,7 @@ def __init__(self, api_gateway: ApiGateway, cell_id: str): self._cell_id = cell_id async def _get_controllers(self) -> list[wb.models.ControllerInstance]: - controller_api = self._api_gateway.controller_api - response = await controller_api.list_controllers(cell=self._cell_id) + response = await self._api_gateway.controller_api.list_controllers(cell=self._cell_id) return response.instances async def controllers(self) -> list["Controller"]: From c9636098e3daba91f9c8294ad3040a7a5fdc7d2a Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 20 Dec 2024 16:10:41 +0100 Subject: [PATCH 7/7] review --- nova/core/motion_group.py | 6 +++--- nova/gateway.py | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/nova/core/motion_group.py b/nova/core/motion_group.py index 5f65c16..a58c4c2 100644 --- a/nova/core/motion_group.py +++ b/nova/core/motion_group.py @@ -163,7 +163,7 @@ async def stop(self): except ValueError as e: logger.debug(f"No motion to stop for {self}: {e}") - async def get_state(self, tcp: str | None) -> wb.models.MotionGroupStateResponse: + async def get_state(self, tcp: str | None = None) -> wb.models.MotionGroupStateResponse: """Get the current state of the motion group Args: @@ -175,9 +175,9 @@ async def get_state(self, tcp: str | None) -> wb.models.MotionGroupStateResponse ) return response - async def joints(self, tcp: str | None = None) -> wb.models.Joints: + async def joints(self) -> wb.models.Joints: """Get the current joint positions""" - state = await self.get_state(tcp=tcp) + state = await self.get_state() return state.state.joint_position async def tcp_pose(self, tcp: str | None = None) -> Pose: diff --git a/nova/gateway.py b/nova/gateway.py index 720ee3a..a42a6a1 100644 --- a/nova/gateway.py +++ b/nova/gateway.py @@ -81,13 +81,18 @@ def __init__( if (username is None or password is None) and access_token is None: raise ValueError("Please provide either username and password or an access token") + # Access token has more prio than username and password if both are provided at the same time, set username and + # password to None + if access_token is not None: + username = None + password = None + stripped_host = host.rstrip("/") api_client_config = wb.Configuration( host=f"{stripped_host}/api/{version}", username=username, password=password, access_token=access_token, - ssl_ca_cert=False, ) self._api_client = wb.ApiClient(api_client_config)