Skip to content

10 KB

Machine-translated by Robotheca from the original in Chinese (opens in a new tab). License: MIT (opens in a new tab).

mockway_lua_moveit

Wrap MoveIt and MoveIt Servo as Lua global functions using sol2 (opens in a new tab), enabling robotic arm control via Lua scripts.

Unit Conventions

All Lua API inputs/outputs use the following units:

QuantityUnit
Position (x, y, z)mm (millimeters)
Angle (joint, RPY, rotation increment)deg (degrees)
Linear velocity (Servo)mm/s
Angular velocity (Servo)deg/s
Pause time (Sleep)ms (milliseconds)
Interpolation step (linear motion)mm, default 10

Prerequisites

Before running, start one of the following nodes:

ScenarioLaunch Command
MoveIt Only (PTP / Linear Motion)ros2 launch moveit_mockway_config demo.launch.py
Servo Only (Manual Jogging)ros2 launch mockway_moveit_servo servo.launch.py
MoveIt + Servoros2 launch mockway_bringup mockway.launch.py

Quick Start

# Use built-in demo scripts (script name without .lua)
ros2 launch mockway_lua_moveit lua_moveit.launch.py script:=demo_ptp
ros2 launch mockway_lua_moveit lua_moveit.launch.py script:=demo_linear
ros2 launch mockway_lua_moveit lua_moveit.launch.py script:=demo_joint_servo
ros2 launch mockway_lua_moveit lua_moveit.launch.py script:=demo_cartesian_servo

# Use custom scripts
ros2 launch mockway_lua_moveit lua_moveit.launch.py script_path:=/path/to/my_script.lua

Launch Parameters

ParameterDefault ValueDescription
scriptdemo_joint_servoName of the script (excluding .lua) under the lua/ directory
script_path""Absolute path to the script; takes precedence over script
planning_groupmockway_groupMoveIt planning group
ee_framelink6End-effector frame
base_framebase_linkBase frame
launch_servofalseWhether to start the servo_node simultaneously

curl Call (HTTP API)

After the node is started, an HTTP server is built-in. You can send Lua scripts directly from the command line via the POST /api/lua interface without restarting the node.

Basic Usage

# Execute a single-line script
curl -s -X POST http://localhost:8080/api/lua \
  -H "Content-Type: application/json" \
  -d '{"script":"Log(\"hello\")"}'

# Response example
# {"success":true,"message":"Script executed successfully","output":""}

Execute multi-line script

curl -s -X POST http://localhost:8080/api/lua \
  -H "Content-Type: application/json" \
  -d '{
    "script": "SetVelScale(0.3)\nMoveNamed(\"home\")"
  }'

Execute from .lua file

# jq needs to be installed (sudo apt install jq)
curl -s -X POST http://localhost:8080/api/lua \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile s /path/to/my_script.lua '{script:$s}')"

Define Shell Shortcut Functions

Add the following functions to ~/.bashrc for direct invocation:

lua_exec() {
  curl -s -X POST http://localhost:8080/api/lua \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg s "$1" '{script:$s}')" | jq .
}

lua_file() {
  curl -s -X POST http://localhost:8080/api/lua \
    -H "Content-Type: application/json" \
    -d "$(jq -n --rawfile s "$1" '{script:$s}')" | jq .
}

Usage examples:

lua_exec 'MoveNamed("home")'
lua_exec 'local j = GetJoints(); print(j[1], j[2], j[3], j[4], j[5], j[6])'
lua_file /path/to/my_script.lua

Lua API Reference

All interfaces are global functions that can be called directly without the robot. prefix.

1. Servo Manual Jogging

Requires servo_node to be running. The message is published and returns immediately (non-blocking).

ServoMode(mode) → bool

Switches the Servo command type.

ParameterTypeDescription
modestring"joint_jog" or "twist"
ServoMode("joint_jog")
ServoMode("twist")
ServoJoint(index, velocity)

Single-joint speed jogging.

ParameterTypeDescription
indexstring | intJoint name "joint1" to "joint6" or index 1 to 6
velocitynumberTarget speed, unit deg/s
ServoJoint(1, 20.0)           -- Jog joint1 at 20 deg/s
ServoJoint("joint3", -15.0)   -- Jog joint3 in reverse
ServoJoints(velocities)

Simultaneous velocity jogging for all six axes.

ParameterTypeDescription
velocitiestable{v1, v2, v3, v4, v5, v6}, unit deg/s
ServoJoints({0.0, 0.0, 0.0, 20.0, 20.0, 0.0})
ServoCart(vx, vy, vz, rx, ry, rz [, frame_id])

Cartesian space velocity jogging (Twist).

ParameterTypeDescription
vx/vy/vznumberLinear velocity, unit mm/s
rx/ry/rznumberAngular velocity, unit deg/s
frame_idstringReference frame, default "base_link"
ServoCart(100, 0, 0,  0, 0, 0)                  -- Move forward along the X axis of the base frame
ServoCart(0, 0, 100,  0, 0, 0,  "link6")         -- Move along the Z axis of the end effector
ServoStop()

Publishes zero speed to both topics to stop the Servo motion.

ServoStop()

2. MoveIt Point-to-Point Motion (PTP)

Requires move_group to be running. Blocks until the motion is complete and returns a boolean.

MoveNamed(name) → bool

Move to a named state defined in the SRDF.

MoveNamed("home")
MoveNamed("ready")
MoveJ(positions) → bool

Perform a PTP motion using joint angles.

ParameterTypeDescription
positionstable{j1, j2, j3, j4, j5, j6}, unit deg
MoveJ({0, -45, -90, 60, 90, 0})
MovePose(x, y, z, roll, pitch, yaw) → bool

Perform PTP motion based on end-effector pose (RPY Euler angles). Units: mm for x/y/z, deg for angles.

MovePose(250, 100, 300,  180, 0, 0)
MovePose(250, -100, 300, 180, 0, 30)   -- yaw rotated by 30°

3. Linear Motion in MoveIt (Linear)

Requires the move_group to be running. Implemented using computeCartesianPath, blocking until the motion is complete, and returns a boolean. If the planning success rate is less than 90%, the execution is canceled and false is returned.

MoveL(x, y, z, roll, pitch, yaw [, step]) → bool

Absolute pose linear motion. Units: x/y/z mm, angles deg, step mm (default 10).

MoveL(300, 0, 400,  180, 0, 0)
MoveL(300, 0, 400,  180, 0, 0,  5)   -- Fine step size 5 mm
MoveLRel(dx, dy, dz, drx, dry, drz [, step]) → bool

Incremental linear motion relative to the current end-effector position (the increment is expressed in the base coordinate system).

ParameterTypeDescription
dx/dy/dznumberPosition offset, unit mm
drx/dry/drznumberOrientation offset (RPY increment), unit deg
MoveLRel(0.0,  0.0, 50.0,  0.0, 0.0,  0.0)   -- Move up 50 mm along the base Z-axis
MoveLRel(30.0, 0.0, 0.0,   0.0, 0.0, 10.0)   -- Move forward 30 mm in X + rotate 10° around Z
MoveLRelTool(dx, dy, dz, drx, dry, drz [, step]) → bool

Incremental linear motion relative to the current end-effector position (expressed as increments in the tool coordinate system).

The translation is first rotated by the tool orientation into the base coordinate system and then added; the rotation is applied in the tool coordinate system (q_new = q_cur * q_delta).

MoveLRelTool(0.0, 0.0, 50.0,  0.0, 0.0, 0.0)    -- Move forward 50 mm along the tool Z axis (feed direction)
MoveLRelTool(20.0, 0.0, 0.0,  0.0, 0.0, 15.0)   -- Translate along the tool X axis + rotate 15° around the tool Z axis

4. Planning Parameters

Requires move_group to be running. Settings apply to all subsequent plans.

SetVelScale(factor)

Sets the maximum speed scaling factor, range [0.01, 1.0].

SetVelScale(0.3)   -- 30% maximum speed
SetAccScale(factor)

Sets the maximum acceleration scaling factor, range [0.01, 1.0].

SetAccScale(0.1)
SetPlanTime(seconds)

Sets the planning timeout duration.

SetPlanTime(5.0)
SetPlanner(planner_id)

Switches the motion planner.

SetPlanner("RRTConnect")
SetPlanner("LIN")   -- Pilz linear planner

V. Status Query

Requires move_group to be running.

GetJoints() → table

Returns the current joint angles {j1..j6} in degrees.

local j = GetJoints()
-- j[1]~j[6], in degrees
print(j[1])
GetPose() → table

Returns the current end-effector pose {x, y, z, roll, pitch, yaw}, with x/y/z in mm and angles in deg.

local p = GetPose()
-- p[1]=x  p[2]=y  p[3]=z     (mm)
-- p[4]=roll  p[5]=pitch  p[6]=yaw  (deg)
print(string.format("x=%.1f  y=%.1f  z=%.1f mm", p[1], p[2], p[3]))

VI. Utility Functions

Sleep(ms)

Pause execution, unit: milliseconds.

Sleep(500)    -- Pause for 500ms
Sleep(1000)   -- Pause for 1s
Log(msg) / LogWarn(msg) / LogError(msg)

Output ROS logs.

Log("Motion completed")
LogWarn("Speed too high")
LogError("Planning failed")
Ok() → bool

Returns whether the ROS node is still running, which can be used as an exit condition for loops.

while Ok() do
  ServoJoint(1, 20.0)
  Sleep(20)
end
DegRad(deg) / RadDeg(rad)

Convert between degrees and radians.

DegRad(90)    -- → 1.5708
RadDeg(1.57)  -- → 89.95

Built-in demonstration scripts

ScriptFunctionRequired Node
demo_joint_servo.luaSingle-axis / multi-axis joint point movement demonstration (deg/s)servo_node
demo_cartesian_servo.luaCartesian translation (mm/s) / rotation (deg/s) / combined joggingservo_node
demo_ptp.luaPTP named state / joint angle (deg) / pose target (mm) / speed scalingmove_group
demo_linear.luaAbsolute / relative (base coordinate system & tool coordinate system) / multi-waypoint linear motionmove_group

Writing Custom Scripts

-- my_script.lua

-- Initial parameters
SetVelScale(0.3)
SetAccScale(0.1)

-- Move to home
assert(MoveNamed("home"), "Failed to return to home")

-- Linear ascent of 50mm (Z-axis of base coordinate system)
MoveLRel(0, 0, 50,  0, 0, 0)

-- Print current status
local p = GetPose()
print(string.format("Reached: x=%.1f  y=%.1f  z=%.1f mm", p[1], p[2], p[3]))

Launch:

ros2 launch mockway_lua_moveit lua_moveit.launch.py \
  script_path:=/path/to/my_script.lua

Files by @Jelatine, at commit a0e2f59, read from GitHub in your browser. Hardware license: MIT; software license: MIT. Robotheca doesn't review code: read it before running it.