@wandelbots/nova-js
Version:
Official JS client for the Wandelbots API
1,469 lines (1,459 loc) • 65.3 kB
JavaScript
import {
AutoReconnectingWebsocket,
__async,
__spreadProps,
__spreadValues,
availableStorage,
loginWithAuth0,
tryParseJson
} from "../../chunk-V3NJLR6P.js";
// src/lib/v2/index.ts
export * from "@wandelbots/nova-api/v2";
// src/lib/v2/ConnectedMotionGroup.ts
import { AxiosError } from "axios";
import { makeAutoObservable, runInAction } from "mobx";
// src/lib/v2/motionStateUpdate.ts
function jointValuesEqual(oldJointValues, newJointValues, changeDeltaThreshold) {
if (newJointValues.length !== oldJointValues.length) {
return true;
}
for (let jointIndex = 0; jointIndex < newJointValues.length; jointIndex++) {
if (Math.abs(newJointValues[jointIndex] - oldJointValues[jointIndex]) > changeDeltaThreshold) {
return false;
}
}
return true;
}
function tcpPoseEqual(oldTcp, newTcp, changeDeltaThreshold) {
if (oldTcp === void 0 && newTcp || oldTcp && newTcp === void 0) {
return false;
}
if (oldTcp === void 0 || newTcp === void 0) {
return true;
}
let changedDelta = 0;
changedDelta += Math.abs(oldTcp.orientation[0] - newTcp.orientation[0]);
changedDelta += Math.abs(oldTcp.orientation[1] - newTcp.orientation[1]);
changedDelta += Math.abs(oldTcp.orientation[2] - newTcp.orientation[2]);
changedDelta += Math.abs(oldTcp.position[0] - newTcp.position[0]);
changedDelta += Math.abs(oldTcp.position[1] - newTcp.position[1]);
changedDelta += Math.abs(oldTcp.position[2] - newTcp.position[2]);
if (changedDelta > changeDeltaThreshold) {
return false;
}
return oldTcp.coordinate_system === newTcp.coordinate_system && oldTcp.tcp === newTcp.tcp;
}
// src/lib/v2/ConnectedMotionGroup.ts
var MOTION_DELTA_THRESHOLD = 1e-4;
var ConnectedMotionGroup = class _ConnectedMotionGroup {
constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, motionGroupSpecification, safetySetup) {
this.nova = nova;
this.controller = controller;
this.motionGroup = motionGroup;
this.initialMotionState = initialMotionState;
this.motionStateSocket = motionStateSocket;
this.isVirtual = isVirtual;
this.tcps = tcps;
this.motionGroupSpecification = motionGroupSpecification;
this.safetySetup = safetySetup;
this.connectedJoggingCartesianSocket = null;
this.connectedJoggingJointsSocket = null;
// tmp
this.joggingVelocity = 10;
this.rapidlyChangingMotionState = initialMotionState;
motionStateSocket.addEventListener("message", (event) => {
var _a;
const motionStateResponse = (_a = tryParseJson(event.data)) == null ? void 0 : _a.result;
if (!motionStateResponse) {
throw new Error(
`Failed to get motion state for ${this.motionGroupId}: ${event.data}`
);
}
if (!jointValuesEqual(
this.rapidlyChangingMotionState.joint_position.joints,
motionStateResponse.joint_position.joints,
MOTION_DELTA_THRESHOLD
)) {
runInAction(() => {
this.rapidlyChangingMotionState = motionStateResponse;
});
}
if (!tcpPoseEqual(
this.rapidlyChangingMotionState.tcp_pose,
motionStateResponse.tcp_pose,
MOTION_DELTA_THRESHOLD
)) {
runInAction(() => {
this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose;
});
}
});
makeAutoObservable(this);
}
static connect(nova, motionGroupId, controllers) {
return __async(this, null, function* () {
var _a;
const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
const controller = controllers.find((c) => c.controller === controllerId);
const motionGroup = controller == null ? void 0 : controller.motion_groups.find(
(mg) => mg.motion_group === motionGroupId
);
if (!controller || !motionGroup) {
throw new Error(
`Controller ${controllerId} or motion group ${motionGroupId} not found`
);
}
const motionStateSocket = nova.openReconnectingWebsocket(
`/motion-groups/${motionGroupId}/state-stream`
);
const firstMessage = yield motionStateSocket.firstMessage();
const initialMotionState = (_a = tryParseJson(firstMessage.data)) == null ? void 0 : _a.result;
if (!initialMotionState) {
throw new Error(
`Unable to parse initial motion state message ${firstMessage.data}`
);
}
console.log(
`Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:
`,
initialMotionState
);
let isVirtual = false;
try {
const opMode = yield nova.api.virtualRobotMode.getOperationMode(controllerId);
if (opMode) isVirtual = true;
} catch (err) {
if (err instanceof AxiosError) {
console.log(
`Received ${err.status} from getOperationMode, concluding that ${controllerId} is physical`
);
} else {
throw err;
}
}
const { tcps } = yield nova.api.motionGroupInfos.listTcps(motionGroupId);
const motionGroupSpecification = yield nova.api.motionGroupInfos.getMotionGroupSpecification(motionGroupId);
const safetySetup = yield nova.api.motionGroupInfos.getSafetySetup(motionGroupId);
return new _ConnectedMotionGroup(
nova,
controller,
motionGroup,
initialMotionState,
motionStateSocket,
isVirtual,
tcps,
motionGroupSpecification,
safetySetup
);
});
}
get motionGroupId() {
return this.motionGroup.motion_group;
}
get controllerId() {
return this.controller.controller;
}
get modelFromController() {
return this.motionGroup.model_from_controller;
}
get wandelscriptIdentifier() {
const num = this.motionGroupId.split("@")[0];
return `${this.controllerId.replaceAll("-", "_")}_${num}`;
}
/** Jogging velocity in radians for rotation and joint movement */
get joggingVelocityRads() {
return this.joggingVelocity * Math.PI / 180;
}
get joints() {
return this.initialMotionState.joint_position.joints.map((_, i) => {
return {
index: i
};
});
}
get dhParameters() {
return this.motionGroupSpecification.dh_parameters;
}
get safetyZones() {
return this.safetySetup.safety_zones;
}
dispose() {
this.motionStateSocket.close();
if (this.connectedJoggingCartesianSocket)
this.connectedJoggingCartesianSocket.close();
if (this.connectedJoggingJointsSocket)
this.connectedJoggingJointsSocket.close();
}
setJoggingVelocity(velocity) {
this.joggingVelocity = velocity;
}
};
// src/lib/v2/vectorUtils.ts
import * as THREE from "three";
function axisToIndex(axis) {
switch (axis) {
case "x":
return 0;
case "y":
return 1;
case "z":
return 2;
}
}
function vector3ToArray(vector) {
return [vector.x, vector.y, vector.z];
}
// src/lib/v2/JoggerConnection.ts
var JoggerConnection = class _JoggerConnection {
constructor(nova, cell, motionGroupId, motionGroupState, opts) {
this.nova = nova;
this.cell = cell;
this.motionGroupId = motionGroupId;
this.motionGroupState = motionGroupState;
this.opts = opts;
// Currently a separate websocket is needed for each mode, pester API people
// to merge these for simplicity
this.joggingWebsocket = null;
this.lastVelocityRequest = null;
this.lastResponse = null;
this.joggingWebsocket = nova.openReconnectingWebsocket(
`/cells/${cell}/execution/jogging`
);
this.joggingWebsocket.addEventListener("message", (ev) => {
const data = tryParseJson(ev.data);
if (data && "error" in data) {
if (this.opts.onError) {
this.opts.onError(ev.data);
} else {
throw new Error(ev.data);
}
}
});
this.joggingWebsocket.addEventListener("message", (ev) => {
const data = tryParseJson(ev.data);
if (data && "error" in data) {
if (this.opts.onError) {
this.opts.onError(ev.data);
} else {
throw new Error(ev.data);
}
}
});
}
static open(nova, cell, motionGroupId, opts) {
return __async(this, null, function* () {
const motionGroupState = yield nova.api.motionGroupInfos.getCurrentMotionGroupState(motionGroupId);
return new _JoggerConnection(
nova,
cell,
motionGroupId,
motionGroupState,
opts
);
});
}
get jointCount() {
var _a;
return (_a = this.motionGroupState.joint_current) == null ? void 0 : _a.joints.length;
}
get activeWebsocket() {
return this.joggingWebsocket;
}
stop() {
return __async(this, null, function* () {
var _a, _b;
if (!this.joggingWebsocket) {
return;
}
if (((_a = this.lastVelocityRequest) == null ? void 0 : _a.message_type) === "JointVelocityRequest") {
this.joggingWebsocket.sendJson({
message_type: "JointVelocityRequest",
velocity: {
joints: Array.from(new Array(this.jointCount).keys()).map(() => 0)
}
});
}
if (((_b = this.lastVelocityRequest) == null ? void 0 : _b.message_type) === "TcpVelocityRequest") {
this.joggingWebsocket.sendJson({
message_type: "TcpVelocityRequest",
rotation: [0, 0, 0],
translation: [0, 0, 0]
});
}
});
}
dispose() {
if (this.joggingWebsocket) {
this.joggingWebsocket.dispose();
}
}
/**
* Start rotation of a single robot joint at the specified velocity
*/
startJointRotation(_0) {
return __async(this, arguments, function* ({
joint,
velocityRadsPerSec
}) {
if (!this.joggingWebsocket) {
throw new Error(
"Joint jogging websocket not connected. Wait for reconnect or open new jogging connection"
);
}
const jointVelocities = new Array(this.jointCount).fill(0);
jointVelocities[joint] = velocityRadsPerSec;
this.joggingWebsocket.sendJson({
message_type: "JointVelocityRequest",
velocity: {
joints: jointVelocities
}
});
});
}
/**
* Start the TCP moving along a specified axis at a given velocity
*/
startTCPTranslation(_0) {
return __async(this, arguments, function* ({
axis,
velocityMmPerSec,
useToolCoordinateSystem
}) {
if (!this.joggingWebsocket) {
throw new Error(
"Cartesian jogging websocket not connected. Wait for reconnect or open new jogging connection"
);
}
const joggingVector = [0, 0, 0];
joggingVector[axisToIndex(axis)] = velocityMmPerSec;
this.joggingWebsocket.sendJson({
message_type: "TcpVelocityRequest",
translation: joggingVector,
rotation: [0, 0, 0],
use_tool_coordinate_system: useToolCoordinateSystem
});
});
}
/**
* Start the TCP rotating around a specified axis at a given velocity
*/
startTCPRotation(_0) {
return __async(this, arguments, function* ({
axis,
velocityRadsPerSec,
useToolCoordinateSystem
}) {
if (!this.joggingWebsocket) {
throw new Error(
"Cartesian jogging websocket not connected. Wait for reconnect or open new jogging connection"
);
}
const joggingVector = [0, 0, 0];
joggingVector[axisToIndex(axis)] = velocityRadsPerSec;
this.joggingWebsocket.sendJson({
message_type: "TcpVelocityRequest",
rotation: joggingVector,
translation: [0, 0, 0],
use_tool_coordinate_system: useToolCoordinateSystem
});
});
}
};
// src/lib/v2/MotionStreamConnection.ts
import { makeAutoObservable as makeAutoObservable2, runInAction as runInAction2 } from "mobx";
import * as THREE2 from "three";
var MOTION_DELTA_THRESHOLD2 = 1e-4;
function unwrapRotationVector(newRotationVectorApi, currentRotationVectorApi) {
const currentRotationVector = new THREE2.Vector3(
currentRotationVectorApi[0],
currentRotationVectorApi[1],
currentRotationVectorApi[2]
);
const newRotationVector = new THREE2.Vector3(
newRotationVectorApi[0],
newRotationVectorApi[1],
newRotationVectorApi[2]
);
const currentAngle = currentRotationVector.length();
const currentAxis = currentRotationVector.normalize();
let newAngle = newRotationVector.length();
let newAxis = newRotationVector.normalize();
if (newAxis.dot(currentAxis) < 0) {
newAngle = -newAngle;
newAxis = newAxis.multiplyScalar(-1);
}
let angleDifference = newAngle - currentAngle;
angleDifference -= 2 * Math.PI * Math.floor((angleDifference + Math.PI) / (2 * Math.PI));
newAngle = currentAngle + angleDifference;
return vector3ToArray(newAxis.multiplyScalar(newAngle));
}
var MotionStreamConnection = class _MotionStreamConnection {
constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket) {
this.nova = nova;
this.controller = controller;
this.motionGroup = motionGroup;
this.initialMotionState = initialMotionState;
this.motionStateSocket = motionStateSocket;
this.rapidlyChangingMotionState = initialMotionState;
motionStateSocket.addEventListener("message", (event) => {
var _a;
const motionState = (_a = tryParseJson(event.data)) == null ? void 0 : _a.result;
if (!motionState) {
throw new Error(
`Failed to get motion state for ${this.motionGroupId}: ${event.data}`
);
}
if (!jointValuesEqual(
this.rapidlyChangingMotionState.joint_position.joints,
motionState.joint_position.joints,
MOTION_DELTA_THRESHOLD2
)) {
runInAction2(() => {
this.rapidlyChangingMotionState = motionState;
});
}
if (!tcpPoseEqual(
this.rapidlyChangingMotionState.tcp_pose,
motionState.tcp_pose,
MOTION_DELTA_THRESHOLD2
)) {
runInAction2(() => {
if (this.rapidlyChangingMotionState.tcp_pose == void 0) {
this.rapidlyChangingMotionState.tcp_pose = motionState.tcp_pose;
} else {
this.rapidlyChangingMotionState.tcp_pose = {
position: motionState.tcp_pose.position,
orientation: unwrapRotationVector(
motionState.tcp_pose.orientation,
this.rapidlyChangingMotionState.tcp_pose.orientation
),
tcp: motionState.tcp_pose.tcp,
coordinate_system: motionState.tcp_pose.coordinate_system
};
}
});
}
});
makeAutoObservable2(this);
}
static open(nova, motionGroupId) {
return __async(this, null, function* () {
var _a;
const { controllers } = yield nova.api.controller.listControllers();
const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
const controller = controllers.find((c) => c.controller === controllerId);
const motionGroup = controller == null ? void 0 : controller.motion_groups.find(
(mg) => mg.motion_group === motionGroupId
);
if (!controller || !motionGroup) {
throw new Error(
`Controller ${controllerId} or motion group ${motionGroupId} not found`
);
}
const motionStateSocket = nova.openReconnectingWebsocket(
`/motion-groups/${motionGroupId}/state-stream`
);
const firstMessage = yield motionStateSocket.firstMessage();
console.log("got first message", firstMessage);
const initialMotionState = (_a = tryParseJson(firstMessage.data)) == null ? void 0 : _a.result;
if (!initialMotionState) {
throw new Error(
`Unable to parse initial motion state message ${firstMessage.data}`
);
}
console.log(
`Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:
`,
initialMotionState
);
return new _MotionStreamConnection(
nova,
controller,
motionGroup,
initialMotionState,
motionStateSocket
);
});
}
get motionGroupId() {
return this.motionGroup.motion_group;
}
get controllerId() {
return this.controller.controller;
}
get modelFromController() {
return this.motionGroup.model_from_controller;
}
get wandelscriptIdentifier() {
const num = this.motionGroupId.split("@")[0];
return `${this.controllerId.replaceAll("-", "_")}_${num}`;
}
get joints() {
return this.initialMotionState.joint_position.joints.map((_, i) => {
return {
index: i
};
});
}
dispose() {
this.motionStateSocket.close();
}
};
// src/lib/v2/NovaCellAPIClient.ts
import {
ApplicationApi,
CellApi,
ControllerApi,
ControllerInputsOutputsApi,
CoordinateSystemsApi,
JoggingApi,
MotionGroupApi,
MotionGroupInfoApi,
MotionGroupKinematicsApi,
ProgramApi,
ProgramOperatorApi,
StoreCollisionComponentsApi,
StoreCollisionScenesApi,
StoreObjectApi,
SystemApi,
TrajectoryExecutionApi,
TrajectoryPlanningApi,
VirtualRobotApi,
VirtualRobotBehaviorApi,
VirtualRobotModeApi,
VirtualRobotSetupApi
} from "@wandelbots/nova-api/v2";
import axios from "axios";
var NovaCellAPIClient = class {
constructor(cellId, opts) {
this.cellId = cellId;
this.opts = opts;
this.system = this.withUnwrappedResponsesOnly(SystemApi);
this.cell = this.withUnwrappedResponsesOnly(CellApi);
this.motionGroup = this.withCellId(MotionGroupApi);
this.motionGroupInfos = this.withCellId(MotionGroupInfoApi);
this.controller = this.withCellId(ControllerApi);
this.program = this.withCellId(ProgramApi);
this.programOperator = this.withCellId(ProgramOperatorApi);
this.controllerIOs = this.withCellId(ControllerInputsOutputsApi);
this.motionGroupKinematic = this.withCellId(MotionGroupKinematicsApi);
this.trajectoryPlanning = this.withCellId(TrajectoryPlanningApi);
this.trajectoryExecution = this.withCellId(TrajectoryExecutionApi);
this.coordinateSystems = this.withCellId(CoordinateSystemsApi);
this.application = this.withCellId(ApplicationApi);
this.applicationGlobal = this.withUnwrappedResponsesOnly(ApplicationApi);
this.jogging = this.withCellId(JoggingApi);
this.virtualRobot = this.withCellId(VirtualRobotApi);
this.virtualRobotSetup = this.withCellId(VirtualRobotSetupApi);
this.virtualRobotMode = this.withCellId(VirtualRobotModeApi);
this.virtualRobotBehavior = this.withCellId(VirtualRobotBehaviorApi);
this.storeObject = this.withCellId(StoreObjectApi);
this.storeCollisionComponents = this.withCellId(
StoreCollisionComponentsApi
);
this.storeCollisionScenes = this.withCellId(StoreCollisionScenesApi);
}
/**
* Some TypeScript sorcery which alters the API class methods so you don't
* have to pass the cell id to every single one, and de-encapsulates the
* response data
*/
withCellId(ApiConstructor) {
var _a, _b;
const apiClient = new ApiConstructor(
__spreadProps(__spreadValues({}, this.opts), {
isJsonMime: (mime) => {
return mime === "application/json";
}
}),
(_a = this.opts.basePath) != null ? _a : "",
(_b = this.opts.axiosInstance) != null ? _b : axios.create()
);
for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) {
if (key !== "constructor" && typeof apiClient[key] === "function") {
const originalFunction = apiClient[key];
apiClient[key] = (...args) => {
return originalFunction.apply(apiClient, [this.cellId, ...args]).then((res) => res.data);
};
}
}
return apiClient;
}
/**
* As withCellId, but only does the response unwrapping
*/
withUnwrappedResponsesOnly(ApiConstructor) {
var _a, _b;
const apiClient = new ApiConstructor(
__spreadProps(__spreadValues({}, this.opts), {
isJsonMime: (mime) => {
return mime === "application/json";
}
}),
(_a = this.opts.basePath) != null ? _a : "",
(_b = this.opts.axiosInstance) != null ? _b : axios.create()
);
for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) {
if (key !== "constructor" && typeof apiClient[key] === "function") {
const originalFunction = apiClient[key];
apiClient[key] = (...args) => {
return originalFunction.apply(apiClient, args).then((res) => res.data);
};
}
}
return apiClient;
}
};
// src/lib/v2/NovaClient.ts
import axios2, { isAxiosError } from "axios";
import urlJoin from "url-join";
// src/lib/v2/mock/MockNovaInstance.ts
import { AxiosError as AxiosError2 } from "axios";
import * as pathToRegexp from "path-to-regexp";
var MockNovaInstance = class {
constructor() {
this.connections = [];
}
handleAPIRequest(config) {
return __async(this, null, function* () {
var _a, _b, _c;
const apiHandlers = [
{
method: "GET",
path: "/cells/:cellId/controllers",
handle() {
return {
controllers: [
{
controller: "mock-ur5e",
model_name: "UniversalRobots::Controller",
host: "mock-ur5e",
allow_software_install_on_controller: true,
motion_groups: [
{
motion_group: "0@mock-ur5e",
name_from_controller: "UR5e",
active: false,
model_from_controller: "UniversalRobots_UR5e"
}
],
has_error: false,
error_details: ""
}
]
};
}
},
{
method: "GET",
path: "/cells/:cellId/controllers/:controllerId",
handle() {
return {
configuration: {
kind: "VirtualController",
manufacturer: "universalrobots",
position: "[0,-1.571,-1.571,-1.571,1.571,-1.571,0]",
type: "universalrobots-ur5e"
},
name: "mock-ur5"
};
}
},
{
method: "GET",
path: "/cells/:cellId/motion-groups/:motionGroupId/specification",
handle() {
return {
dh_parameters: [
{
alpha: 1.5707963267948966,
theta: 0,
a: 0,
d: 162.25,
reverse_rotation_direction: false
},
{
alpha: 0,
theta: 0,
a: -425,
d: 0,
reverse_rotation_direction: false
},
{
alpha: 0,
theta: 0,
a: -392.2,
d: 0,
reverse_rotation_direction: false
},
{
alpha: 1.5707963267948966,
theta: 0,
a: 0,
d: 133.3,
reverse_rotation_direction: false
},
{
alpha: -1.5707963267948966,
theta: 0,
a: 0,
d: 99.7,
reverse_rotation_direction: false
},
{
alpha: 0,
theta: 0,
a: 0,
d: 99.6,
reverse_rotation_direction: false
}
],
mechanical_joint_limits: [
{
joint: "JOINTNAME_AXIS_1",
lower_limit: -6.335545063018799,
upper_limit: 6.335545063018799,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_2",
lower_limit: -6.335545063018799,
upper_limit: 6.335545063018799,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_3",
lower_limit: -6.335545063018799,
upper_limit: 6.335545063018799,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_4",
lower_limit: -6.335545063018799,
upper_limit: 6.335545063018799,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_5",
lower_limit: -6.335545063018799,
upper_limit: 6.335545063018799,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_6",
lower_limit: -6.335545063018799,
upper_limit: 6.335545063018799,
unlimited: false
}
]
};
}
},
{
method: "GET",
path: "/cells/:cellId/motion-groups/:motionGroupId/safety-setup",
handle() {
return {
safety_settings: [
{
safety_state: "SAFETY_NORMAL",
settings: {
joint_position_limits: [
{
joint: "JOINTNAME_AXIS_1",
lower_limit: -2.96705961227417,
upper_limit: 2.96705961227417,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_2",
lower_limit: -1.7453292608261108,
upper_limit: 2.7925267219543457,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_3",
lower_limit: -3.3161256313323975,
upper_limit: 0.40142571926116943,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_4",
lower_limit: -3.4906585216522217,
upper_limit: 3.4906585216522217,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_5",
lower_limit: -2.4434609413146973,
upper_limit: 2.4434609413146973,
unlimited: false
},
{
joint: "JOINTNAME_AXIS_6",
lower_limit: -4.71238899230957,
upper_limit: 4.71238899230957,
unlimited: false
}
],
joint_velocity_limits: [
{
joint: "JOINTNAME_AXIS_1",
limit: 3.1415927410125732
},
{
joint: "JOINTNAME_AXIS_2",
limit: 3.1415927410125732
},
{
joint: "JOINTNAME_AXIS_3",
limit: 3.4906585216522217
},
{
joint: "JOINTNAME_AXIS_4",
limit: 6.108652591705322
},
{
joint: "JOINTNAME_AXIS_5",
limit: 6.108652591705322
},
{
joint: "JOINTNAME_AXIS_6",
limit: 6.981317043304443
}
],
joint_acceleration_limits: [],
joint_torque_limits: [],
tcp_velocity_limit: 1800
}
}
],
safety_zones: [
{
id: 1,
priority: 0,
geometry: {
compound: {
child_geometries: [
{
convex_hull: {
vertices: [
{ vertex: [-800, -1330, -1820] },
{ vertex: [1650, -1330, -1820] },
{ vertex: [1650, 1330, -1820] },
{ vertex: [-800, 1330, -1820] }
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "box"
},
{
convex_hull: {
vertices: [
{
vertex: [-800, -1330, -1820]
},
{
vertex: [1650, -1330, -1820]
},
{
vertex: [1650, -1330, 1500]
},
{
vertex: [-800, -1330, 1500]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "box"
},
{
convex_hull: {
vertices: [
{
vertex: [-800, -1330, -1820]
},
{
vertex: [-800, 1330, -1820]
},
{
vertex: [-800, 1330, 1500]
},
{
vertex: [-800, -1330, 1500]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "box"
},
{
convex_hull: {
vertices: [
{
vertex: [1650, 1330, 1500]
},
{
vertex: [-800, 1330, 1500]
},
{
vertex: [-800, -1330, 1500]
},
{
vertex: [1650, -1330, 1500]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "box"
},
{
convex_hull: {
vertices: [
{
vertex: [1650, 1330, 1500]
},
{
vertex: [-800, 1330, 1500]
},
{
vertex: [-800, 1330, -1820]
},
{
vertex: [1650, 1330, -1820]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "box"
},
{
convex_hull: {
vertices: [
{
vertex: [1650, 1330, 1500]
},
{
vertex: [1650, -1330, 1500]
},
{
vertex: [1650, -1330, -1820]
},
{
vertex: [1650, 1330, -1820]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "box"
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "Cell workzone"
},
motion_group_uid: 1
},
{
id: 2,
priority: 0,
geometry: {
convex_hull: {
vertices: [
{
vertex: [1650, 1330, -1850]
},
{
vertex: [865, 1330, -1850]
},
{
vertex: [865, -720, -1850]
},
{
vertex: [1650, -720, -1850]
},
{
vertex: [1650, 1330, -920]
},
{
vertex: [865, 1330, -920]
},
{
vertex: [865, -720, -920]
},
{
vertex: [1650, -720, -920]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "Transport"
},
motion_group_uid: 1
},
{
id: 3,
priority: 0,
geometry: {
convex_hull: {
vertices: [
{
vertex: [1650, 1330, -600]
},
{
vertex: [865, 1330, -600]
},
{
vertex: [865, 430, -600]
},
{
vertex: [1650, 430, -600]
},
{
vertex: [1650, 1330, -1250]
},
{
vertex: [865, 1330, -1250]
},
{
vertex: [865, 430, -1250]
},
{
vertex: [1650, 430, -1250]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "Tunel"
},
motion_group_uid: 1
},
{
id: 4,
priority: 0,
geometry: {
convex_hull: {
vertices: [
{
vertex: [1650, -760, -440]
},
{
vertex: [900, -760, -440]
},
{
vertex: [900, -1330, -440]
},
{
vertex: [1650, -1330, -440]
},
{
vertex: [1650, -760, -1800]
},
{
vertex: [900, -760, -1800]
},
{
vertex: [900, -1330, -1800]
},
{
vertex: [1650, -1330, -1800]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "Fanuc controller"
},
motion_group_uid: 1
},
{
id: 6,
priority: 0,
geometry: {
convex_hull: {
vertices: [
{
vertex: [-200, -200, -1900]
},
{
vertex: [200, -200, -1900]
},
{
vertex: [200, 200, -1900]
},
{
vertex: [-200, 200, -1900]
},
{
vertex: [-200, -200, -350]
},
{
vertex: [200, -200, -350]
},
{
vertex: [200, 200, -350]
},
{
vertex: [-200, 200, -350]
}
]
},
init_pose: {
position: [0, 0, 0],
orientation: [0, 0, 0, 1]
},
id: "Robot base"
},
motion_group_uid: 1
}
],
robot_model_geometries: [
{
link_index: 1,
geometry: {
sphere: {
radius: 270
},
init_pose: {
position: [-70, -70, -50],
orientation: [0, 0, 0, 1]
},
id: "link1_sphere"
}
},
{
link_index: 2,
geometry: {
capsule: {
radius: 160,
cylinder_height: 800
},
init_pose: {
position: [-450, 40, 170],
orientation: [
0,
-0.7071067811865475,
0,
0.7071067811865476
]
},
id: "link2_capsule"
}
},
{
link_index: 3,
geometry: {
sphere: {
radius: 270
},
init_pose: {
position: [-110, 10, -100],
orientation: [0, 0, 0, 1]
},
id: "link3_sphere"
}
},
{
link_index: 4,
geometry: {
capsule: {
radius: 110,
cylinder_height: 600
},
init_pose: {
position: [0, 300, 40],
orientation: [
-0.7071067811865475,
0,
0,
0.7071067811865476
]
},
id: "link4_capsule"
}
},
{
link_index: 5,
geometry: {
sphere: {
radius: 75
},
init_pose: {
position: [0, 0, -50],
orientation: [0, 0, 0, 1]
},
id: "link5_sphere"
}
}
],
tool_geometries: []
};
}
},
{
method: "GET",
path: "/cells/:cellId/coordinate-systems",
handle() {
return {
coordinatesystems: [
{
coordinate_system: "",
name: "world",
reference_uid: "",
position: [0, 0, 0],
rotation: {
angles: [0, 0, 0],
type: "ROTATION_VECTOR"
}
}
]
};
}
},
{
method: "GET",
path: "/cells/:cellId/motion-groups/:motionGroupId/tcps",
handle() {
return {
tcps: [
{
id: "Flange",
readable_name: "Default-Flange",
position: [0, 0, 0],
rotation: {
angles: [0, 0, 0, 0],
type: "ROTATION_VECTOR"
}
},
{
id: "complex-tcp-position",
readable_name: "Complex TCP Position",
position: [-200, 300, 150],
rotation: {
angles: [
-0.12139440409113832,
-0.06356210998212003,
-0.2023240068185639,
0
],
type: "ROTATION_VECTOR"
}
}
]
};
}
}
];
const method = ((_a = config.method) == null ? void 0 : _a.toUpperCase()) || "GET";
const path = "/cells" + ((_c = (_b = config.url) == null ? void 0 : _b.split("/cells")[1]) == null ? void 0 : _c.split("?")[0]);
for (const handler of apiHandlers) {
const match2 = pathToRegexp.match(handler.path)(path || "");
if (method === handler.method && match2) {
const json = handler.handle();
return {
status: 200,
statusText: "Success",
data: JSON.stringify(json),
headers: {},
config,
request: {
responseURL: config.url
}
};
}
}
throw new AxiosError2(
`No mock handler matched this request: ${method} ${path}`,
"404",
config
);
});
}
handleWebsocketConnection(socket) {
this.connections.push(socket);
setTimeout(() => {
socket.dispatchEvent(new Event("open"));
console.log("Websocket connection opened from", socket.url);
if (socket.url.includes("/state-stream")) {
socket.dispatchEvent(
new MessageEvent("message", {
data: JSON.stringify(defaultMotionState)
})
);
}
if (socket.url.includes("/move-joint")) {
socket.dispatchEvent(
new MessageEvent("message", {
data: JSON.stringify({
result: {
motion_group: "0@ur",
state: {
controller: "ur",
operation_mode: "OPERATION_MODE_AUTO",
safety_state: "SAFETY_STATE_NORMAL",
timestamp: "2024-09-18T12:48:26.096266444Z",
velocity_override: 100,
motion_groups: [
{
motion_group: "0@ur",
controller: "ur",
joint_position: {
joints: [
1.3492152690887451,
-1.5659207105636597,
1.6653711795806885,
-1.0991662740707397,
-1.829018235206604,
1.264623761177063
]
},
joint_velocity: {
joints: [0, 0, 0, 0, 0, 0]
},
flange_pose: {
position: [
6.437331889439328,
-628.4123774830913,
577.0569957147832
],
orientation: {
x: -1.683333649797158,
y: -1.9783363827298732,
z: -0.4928031860165713
},
coordinate_system: ""
},
tcp_pose: {
position: [
6.437331889439328,
-628.4123774830913,
577.0569957147832
],
orientation: {
x: -1.683333649797158,
y: -1.9783363827298732,
z: -0.4928031860165713
},
coordinate_system: "",
tcp: "Flange"
},
velocity: {
linear: {
x: 0,
y: 0,
z: 0
},
angular: {
x: -0,
y: 0,
z: 0
},
coordinate_system: ""
},
force: {
force: {
x: 0,
y: 0,
z: 0
},
moment: {
x: 0,
y: 0,
z: 0
},
coordinate_system: ""
},
joint_limit_reached: {
limit_reached: [
false,
false,
false,
false,
false,
false
]
},
joint_current: {
joints: [0, 0, 0, 0, 0, 0]
},
sequence_number: "671259"
}
],
sequence_number: "671259"
},
movement_state: "MOVEMENT_STATE_MOVING"
}
})
})
);
}
if (socket.url.includes("/move-tcp")) {
socket.dispatchEvent(
new MessageEvent("message", {
data: JSON.stringify({
result: {
motion_group: "0@ur",
state: {
controller: "ur",
operation_mode: "OPERATION_MODE_AUTO",
safety_state: "SAFETY_STATE_NORMAL",
timestamp: "2024-09-18T12:43:12.188335774Z",
velocity_override: 100,
motion_groups: [
{
motion_group: "0@ur",
controller: "ur",
joint_position: {
joints: [
1.3352527618408203,
-1.5659207105636597,
1.6653711795806885,
-1.110615611076355,
-1.829018235206604,
1.264623761177063
]
},
joint_velocity: {
joints: [0, 0, 0, 0, 0, 0]
},
flange_pose: {
position: [
-2.763015284002938,
-630.2151479701106,
577.524509114342
],
orientation: {
x: -1.704794877102097,
y: -1.9722372952861567,
z: -0.4852079204210754
},
coor