Skip to content
← Mockway Robot

Project files

README.md

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.