Skip to content

Repository files navigation

Hiwonder MasterPi, MuJoCo model

There is no official URDF, USD or MJCF for the MasterPi. Hiwonder ships a STEP file on request (support@hiwonder.com, quote your order number) and nothing else.

This MJCF is built from first party numbers rather than eyeballed dimensions:

source what it gave
ArmIK/InverseKinematics.py on the robot image l1 8.00, l2 6.50, l3 6.20, l4 10.00 cm
ArmIK/ArmMoveIK.py l1 gets +1.3 cm, so 9.30 cm effective; servo channels 3,4,5,6
HiwonderSDK/mecanum.py a 67 mm, b 59 mm, wheel diameter 65 mm
product page 185 x 162 x 343 mm, 1100 g, LD-1501MG + LFD-01M servos

preview

Files

  • CLAUDE_CODE_PROMPT.md : paste this into Claude Code and it sets the whole thing up
  • build_model.py : generates masterpi.xml from a table of measured numbers
  • masterpi.xml : the model, includes floor and lighting, loads standalone
  • masterpi_simple.xml : the earlier primitive only version, kept for diffing
  • view.py : the model in a viewer with nothing driving it
  • verify_fk.py : runs Hiwonder's own IK and checks the MJCF reaches the same point
  • demo.py : scripted pick and place plus a mecanum base drive
  • render.py : offscreen still, no window needed
  • run.sh : venv, install, verify, launch, in one command
  • requirements.txt

Where the numbers come from

masterpi.xml is generated, not hand written. Edit build_model.py and re-run it. Sources, in order of authority:

  1. Hiwonder's dimensional drawing on the product page. Scaled off the published 343 mm height (805 px in the 1200 px render, 0.4261 mm/px) and cross checked against the 162 mm width, which lands at 162.3 mm. The drawing is where the chassis layout, the wheel positions and the shoulder height come from.
  2. ArmIK/InverseKinematics.py + ArmIK/ArmMoveIK.py on the robot image, for the four link lengths. These are what the robot's own software believes, so they define the chain and verify_fk.py checks against them.
  3. Servo datasheets: LDX-218 and LD-1501MG are both 40 x 20 x 40.5 mm.

Measured against the published envelope:

model spec
length, chassis and wheels 185.8 mm 185
width, across the wheel faces 163.0 mm 162
ground to top of rear deck 101.8 mm 101
wheel diameter x width 65 x 30 mm 65 x 30
mass 1.105 kg 1.100 kg
shoulder axis height 129 mm 129 (measured)
gripper tip, arm up 356 mm 343 with the jaws open

One conflict is worth knowing about. The drawing puts the shoulder axis 129 mm up and the arm's base plate at about 95 mm, 34 mm below it, but Hiwonder's IK calls that distance l1 = 93 mm. So their l1 is not measured from the arm's base plate. The chain is what has to stay true, so the IK frame origin is placed exactly l1 below the shoulder, 36 mm above the ground, and the visible base hardware is drawn where the drawing puts it. verify_fk.py still reads 0.00 mm.

Appearance

Every visible part is modelled from the product photography rather than blocked out, and the colours are the real anodising:

part how it is built colour
chassis box, decks, bumper, side plate boxes, deck perforated with 30 countersunk holes silver anodised aluminium
arm brackets, base U bracket slotted U channel: two rails a side with the slot between them, a spine down the back, a rounded ear nesting at each pivot orange anodised
shoulder / elbow / wrist / gripper servos LD-1501MG and LDX-218 cases with their silver labels matte black
servo horns and axle bosses discs on both sides of every joint bright steel
mecanum wheels grey hub, six spokes, ten roller barrels at 45 deg grey hub, orange rollers
gearmotors barrel plus gearbox collar, inboard of each wheel black, steel collar
dual ultrasonic two lit lenses in the front housing emissive blue
Raspberry Pi + expansion board + heatsinks + fan boards between the decks, on copper standoffs green, black, blue
wide angle camera body, mount plate and lens barrel on the wrist black, dark lens
gripper jaw rail, guide pins, two jaws gunmetal jaws, orange tips

Sensors on board

The real MasterPi carries exactly two sensing devices, and both are in the model:

  • HD wide angle camera, 480P, mounted on the gripper itself, standing above and behind the jaws on a plate held off by two brass standoffs, lens looking straight down the tool axis so the jaw tips sit at the edge of frame. It is a real MuJoCo <camera name="wrist_cam">, so you can render the robot's own FPV feed: Renderer.update_scene(d, "wrist_cam"). This is the camera Hiwonder's demos use for colour sorting, block tracking and visual line following.
  • The glowy ultrasonic module in the front housing, the two blue lit eyes. Modelled as two <rangefinder> sensors, sonar_left and sonar_right, reading metres along +x and -1 when nothing is in range.

There is no infrared sensor on the stock MasterPi. Line following is done in OpenCV through the wrist camera, not with a floor mounted IR array, and the spec sheet lists no IR part. The row of small holes in the lower bumper plate is bracket mounting, and it is modelled as such.

Geometry is split into two sets, so the render can be detailed without making the solver pay for it:

  • group 1 : visual only, contype 0, mass 0. 200 odd geoms of skin.
  • group 3 : the collision proxies, hidden by default. A box for the chassis, a cylinder per wheel, a capsule per arm link.

In the viewer press 1 to hide the skin and 3 to reveal the proxies, or run python render.py col.png --collision. Total mass comes out at 1.105 kg against the 1100 g on the product page.

The kinematic chain, joint names, actuators, sensors and site positions are untouched by all of this. verify_fk.py still reports 0.00 mm.

Verification

verify_fk.py feeds the waypoints from Hiwonder's control_by_kinematics.py demo through the stock IK, maps the servo angles into MuJoCo joints, and reads the TCP back. Current error on all five waypoints: 0.00 mm.

Joint and actuator map

MJCF joint robot servo note
joint6_base_yaw servo 6 theta6 = atan2(y, x), model zero is +x forward
joint5_shoulder servo 5 model zero = arm straight up, q5 = 90 - theta5
joint4_elbow servo 4 q4 = theta4
joint3_wrist servo 3 q3 = -theta3
finger_left_j / finger_right_j servo 1 coupled by equality constraint
base_x, base_y, base_yaw mecanum chassis velocity actuators, body frame

Servo pulse 500..2500 us maps to 0..180 deg, so every arm joint range is +/- 90 deg.

Base fidelity

MuJoCo's sliding friction is isotropic, so a mecanum wheel cannot be faked with friction parameters alone. Two honest options:

  1. Planar omni base (what this file does). Three joints on the chassis driven by velocity actuators that take vx, vy, wz in the body frame, exactly like MecanumChassis.set_velocity. Correct for anything where the arm is the subject.
  2. Real rollers. Replace the three joints with <freejoint/> and give each wheel 9 to 12 roller bodies, each a free spinning capsule with its axis at 45 deg to the hub. Needed only if wheel slip itself is what you are studying.

Quick start

./run.sh

or by hand:

python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python verify_fk.py          # expect 0.00 mm on all five rows
python demo.py --headless    # printed TCP and base positions
python render.py             # writes preview.png
mjpython demo.py             # interactive viewer (macOS needs mjpython, not python)

On macOS mujoco.viewer.launch_passive has to own the main thread, so the viewer must be started with mjpython, which pip installs alongside mujoco. run.sh ends with plain python demo.py and will fail on that last step on a Mac; run the mjpython line by hand instead.

About

MuJoCo (MJCF) model of the Hiwonder MasterPi mecanum robot arm car, built from Hiwonder's dimensional drawing and its own IK library. Verified 0.00 mm against the stock inverse kinematics.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages