movemaster-robot
Version:
A module to control a Mitsubishi Movemaster EX RV-M1 robotic arm via USB
1 lines • 18.9 kB
Source Map (JSON)
{"version":3,"sources":["../src/Robot.ts","../src/utils.ts","../src/defaults.ts"],"sourcesContent":["import { SerialPort } from \"serialport\";\nimport { type Position, ROBOT_ERRORS } from \"./types\";\nimport { delay, fmt } from \"./utils\";\nimport { portDefaults } from \"./defaults\";\n\nclass Robot {\n port: SerialPort | null = null;\n position: Position | null = null;\n toolIsOpen = false;\n toolLength = -1; // Default tool length\n speed = -1;\n portIsOpen = false;\n\n async connect(comPortName: string): Promise<void> {\n return new Promise((resolve, _error) => {\n this.port = new SerialPort({\n path: comPortName.trim(),\n ...portDefaults,\n });\n\n this.port.on(\"open\", () => {\n console.log(`Connected to port: ${comPortName}`);\n resolve();\n });\n this.port.on(\"data\", (data) => {\n console.log(\"Data received:\", data.toString());\n });\n this.port.on(\"error\", (err) => {\n console.error(\"Error on port:\", err);\n });\n });\n }\n\n isConnected(): boolean {\n return !!this.port?.isOpen;\n }\n\n private checkPortOpen(): asserts this is this & { port: SerialPort } {\n if (!this.port || !this.port.isOpen) {\n throw new Error(\"Port is not open\");\n }\n }\n\n async sendCommandNoAnswer(command: string): Promise<void> {\n this.checkPortOpen();\n\n console.log(`Sending command: ${command}`);\n this.port.write(command + \"\\r\\n\");\n await delay(100);\n }\n\n sendCommandWithAnswer(command: string): Promise<string> {\n return new Promise((resolve, reject) => {\n this.checkPortOpen();\n\n console.log(`Sending command with answer: ${command}`);\n\n let stringBuffer = \"\";\n this.port.write(command + \"\\r\\n\", (err) => {\n if (err) {\n console.error(\"Error writing to port:\", err);\n return reject(err);\n }\n });\n\n this.port.on(\"data\", (data) => {\n stringBuffer += data.toString();\n if (stringBuffer.endsWith(\"\\r\\n\")) {\n const response = stringBuffer.trim();\n console.log(\"Response received:\", response);\n resolve(response);\n stringBuffer = \"\"; // Reset buffer after processing\n }\n });\n });\n }\n\n async checkRobotErrorCode(): Promise<\n { ok: true } | { ok: false; error: ROBOT_ERRORS }\n > {\n this.checkPortOpen();\n const res = await this.sendCommandWithAnswer(\"ER\");\n console.log(\"Error code response:\", res);\n const errorCode = parseInt(res, 10);\n\n if (Number.isNaN(errorCode)) {\n console.error(\"Invalid error code received:\", res);\n return { ok: false, error: ROBOT_ERRORS.UNKNOWN_ERROR };\n }\n\n switch (errorCode) {\n case 0:\n console.log(\"No error detected.\");\n return { ok: true };\n case 1:\n console.error(\"Hardware error: 1\");\n return { ok: false, error: ROBOT_ERRORS.HARDWARE_ERROR };\n case 2:\n console.error(\"Position or format error: 2\");\n return { ok: false, error: ROBOT_ERRORS.COMMAND_ERROR };\n }\n return { ok: false, error: ROBOT_ERRORS.UNKNOWN_ERROR };\n }\n\n async moveTo(position: Position, interpolatePoints = 0): Promise<void> {\n this.checkPortOpen();\n\n const { x, y, z, p, r } = position;\n\n if (interpolatePoints === 0) {\n await this.sendCommandNoAnswer(\n `MP ${fmt(x)}, ${fmt(y)}, ${fmt(z)}, ${fmt(p)}, ${fmt(r)}`\n );\n } else {\n await this.sendCommandNoAnswer(\"PC 1\");\n await this.sendCommandNoAnswer(\n `PD 1, ${fmt(x)}, ${fmt(y)}, ${fmt(z)}, ${fmt(p)}, ${fmt(r)}`\n );\n await this.sendCommandNoAnswer(\n `MS 1, ${interpolatePoints}, ${this.toolIsOpen ? \"C\" : \"O\"}`\n );\n }\n\n // Update cached position\n this.position = { x, y, z, p, r };\n }\n\n /**\n * Moves the robot arm to the given absolute x-y-z coordinates using current P and R values\n */\n async moveToXYZ(\n x: number,\n y: number,\n z: number,\n interpolatePoints = 0\n ): Promise<void> {\n if (!this.position) {\n throw new Error(\"Actual position not set\");\n }\n\n return this.moveTo(\n {\n x,\n y,\n z,\n p: this.position.p,\n r: this.position.r,\n },\n interpolatePoints\n );\n }\n\n async getActualPosition(\n forceUpdateByHardware: boolean = true\n ): Promise<Position> {\n if (!forceUpdateByHardware && this.position) {\n // Return cached position (cloned to prevent mutation)\n return { ...this.position };\n }\n\n // Update from hardware\n const response = await this.sendCommandWithAnswer(\"WH\");\n\n const parts = response.split(\",\").map((part) => {\n let cleaned = part.trim().replace(\"+\", \"\");\n\n if (cleaned.startsWith(\".\")) {\n cleaned = `0${cleaned}`;\n }\n return parseFloat(cleaned);\n });\n if (parts.length < 5) {\n throw new Error(\"Invalid position response format\");\n }\n\n const position = {\n x: parts[0],\n y: parts[1],\n z: parts[2],\n p: parts[3],\n r: parts[4],\n };\n this.position = position;\n\n return { ...position }; // Return cloned position\n }\n\n async setGripper(open: boolean): Promise<void> {\n this.checkPortOpen();\n\n if (open) {\n await this.sendCommandNoAnswer(\"GO\");\n } else {\n await this.sendCommandNoAnswer(\"GC\");\n }\n\n this.toolIsOpen = open;\n }\n async setSpeed(speed: number): Promise<void> {\n this.checkPortOpen();\n\n const roundedSpeed = Math.floor(speed);\n if (roundedSpeed < 0 || roundedSpeed > 9) {\n return Promise.reject(new Error(\"Speed must be between 0 and 9\"));\n }\n this.speed = roundedSpeed;\n await this.sendCommandNoAnswer(`SP ${roundedSpeed}`);\n }\n\n async setToolLength(length: number): Promise<void> {\n this.checkPortOpen();\n this.toolLength = length;\n await this.sendCommandNoAnswer(`TL ${Math.floor(length)}`);\n }\n\n async withCheck<T>(result: Promise<T>): Promise<T> {\n const cbResult = await result;\n const errResult = await this.checkRobotErrorCode();\n if (errResult.ok) {\n return cbResult;\n } else {\n throw new Error(`Command errored: ${errResult.error}`);\n }\n }\n\n async movePath(points: Position[]): Promise<void> {\n const positionOffset = 1;\n this.checkPortOpen();\n\n for (let i = 0; i < points.length; i++) {\n const point = points[i];\n await this.sendCommandNoAnswer(\n `PD ${i + positionOffset}, ${fmt(point.x)}, ${fmt(point.y)}, ${fmt(\n point.z\n )}, ${fmt(point.p)}, ${fmt(point.r)}`\n );\n await delay(100); // Delay between commands\n }\n\n await this.sendCommandNoAnswer(\n `MC ${positionOffset}, ${points.length - 1 + positionOffset}`\n );\n }\n\n /**\n * Moves all axes to zero position\n */\n async moveToHomePosition(): Promise<void> {\n this.checkPortOpen();\n await this.sendCommandNoAnswer(\"OG\");\n }\n\n /**\n * Moves the robot to its mechanical origin position\n * Must be performed immediately after power on\n */\n async nest(): Promise<void> {\n this.checkPortOpen();\n await this.sendCommandNoAnswer(\"NT\");\n }\n\n /**\n * Resets the control box\n */\n async reset(): Promise<void> {\n this.checkPortOpen();\n await this.sendCommandNoAnswer(\"RS\");\n }\n\n /**\n * Defines the pressure of the robot arm gripper\n * @param startingGripForce Starting gripping force (0-15)\n * @param retainedGrippingForce Retained gripping force (0-15)\n * @param startGrippingForceRetentionTime Start gripping force retention time (0-99)\n */\n async setGripPressure(\n startingGripForce: number,\n retainedGrippingForce: number,\n startGrippingForceRetentionTime: number\n ): Promise<void> {\n this.checkPortOpen();\n\n if (startingGripForce < 0 || startingGripForce > 15) {\n throw new Error(\"Starting grip force must be between 0 and 15\");\n }\n if (retainedGrippingForce < 0 || retainedGrippingForce > 15) {\n throw new Error(\"Retained gripping force must be between 0 and 15\");\n }\n if (\n startGrippingForceRetentionTime < 0 ||\n startGrippingForceRetentionTime > 99\n ) {\n throw new Error(\n \"Start gripping force retention time must be between 0 and 99\"\n );\n }\n\n await this.sendCommandNoAnswer(\n `GP ${startingGripForce}, ${retainedGrippingForce}, ${startGrippingForceRetentionTime}`\n );\n }\n\n /**\n * Rotates the axes relative to the actual position\n */\n async rotateAxis(\n x: number,\n y: number,\n z: number,\n p: number,\n r: number\n ): Promise<void> {\n this.checkPortOpen();\n\n await this.sendCommandNoAnswer(\n `MJ ${fmt(x)}, ${fmt(y)}, ${fmt(z)}, ${fmt(p)}, ${fmt(r)}`\n );\n\n // Update position from hardware after rotation\n await this.getActualPosition(true);\n }\n\n /**\n * Moves the robot arm to the given relative position/axis values\n * @param interpolatePoints when != 0: use linear calculated path points\n */\n async moveDelta(\n x: number,\n y: number,\n z: number,\n interpolatePoints?: number\n ): Promise<void>;\n async moveDelta(\n x: number,\n y: number,\n z: number,\n p: number,\n r: number,\n interpolatePoints?: number\n ): Promise<void>;\n async moveDelta(\n x: number,\n y: number,\n z: number,\n pOrInterpolatePoints?: number,\n r?: number,\n interpolatePoints?: number\n ): Promise<void> {\n if (!this.position) {\n throw new Error(\"Actual position not set\");\n }\n\n // Handle overloads\n let p: number, actualInterpolatePoints: number;\n if (r === undefined && interpolatePoints === undefined) {\n // 3-parameter version: moveDelta(x, y, z, interpolatePoints?)\n p = this.position.p;\n r = this.position.r;\n actualInterpolatePoints = pOrInterpolatePoints ?? 0;\n } else {\n // 5-parameter version: moveDelta(x, y, z, p, r, interpolatePoints?)\n p = pOrInterpolatePoints ?? this.position.p;\n r = r ?? this.position.r;\n actualInterpolatePoints = interpolatePoints ?? 0;\n }\n\n return this.moveTo(\n {\n x: this.position.x + x,\n y: this.position.y + y,\n z: this.position.z + z,\n p: this.position.p + p,\n r: this.position.r + r,\n },\n actualInterpolatePoints\n );\n }\n\n /**\n * Utility function to clean up R value based on X and Y coordinates\n */\n cleanUpRValue(x: number, y: number, rTarget: number): number {\n return rTarget + (Math.atan2(x, y) * 180) / Math.PI;\n }\n\n /**\n * Gets if the tool gripper is closed\n */\n getGripperClosed(): boolean {\n return !this.toolIsOpen;\n }\n\n disconnect(): void {\n if (this.port) {\n this.port.close((err) => {\n if (err) {\n console.error(\"Error closing port:\", err);\n } else {\n console.log(\"Port closed successfully.\");\n }\n });\n this.port = null;\n } else {\n console.log(\"No port to close.\");\n }\n }\n\n getPosition() {\n return this.position;\n }\n\n getToolLength() {\n return this.toolLength;\n }\n getSpeed() {\n return this.speed;\n }\n\n async listPorts(): Promise<string[]> {\n const ports = await SerialPort.list();\n return ports.map((port) => port.path);\n }\n}\n\nexport default Robot;\n","export const fmt = (value: number): string => {\n return value.toFixed(1);\n};\n\nexport const delay = (ms: number): Promise<void> => {\n return new Promise((resolve) => setTimeout(resolve, ms));\n};\n","export const portDefaults = {\n baudRate: 9600,\n dataBits: 7,\n stopBits: 2,\n parity: \"even\",\n rts: true,\n dtr: true,\n handshake: \"xOnXOff\",\n};\n"],"mappings":"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","names":[]}