Open source, beat-synced dance for the UFactory xArm 7-DOF. Plays a song, detects beats with librosa, and moves the arm through a small bank of safe joint poses on each beat. The full source for the beat tracker, pose bank, safety envelope, and webcam recorder is in this repository under the MIT license.
- UFactory xArm (7 joints) on the LAN, default IP
192.168.1.241. - The script uses joint-angle control in degrees via
xarm-python-sdk.
# macOS audio + video backends
brew install portaudio ffmpeg
# python deps
pip install -r requirements.txtffmpeg is required for muxing the song audio into the saved webcam video.
If you already have the semvs conda env from visual_servoing_for_suction_grippers, xarm-python-sdk and opencv-python are already installed; you only need to add the audio stack:
conda activate semvs
brew install portaudio ffmpeg
pip install librosa sounddevice soundfileA no-copyright song is bundled at samples/eliveta.mp3 and is the default audio. You can run with no arguments at all.
Dry run (preview choreography, no arm motion, no recording):
python3 dance.py --dry-run --no-recordWhen you're happy, connect to the arm. Webcam recording is on by default and outputs land in runs/:
python3 dance.pyEach run writes:
runs/dance_<song>_<timestamp>.mp4(webcam video with the song muxed as audio)runs/dance_<song>_<timestamp>.log(full stdout log including detected tempo, arm IP / ping, motion params)
Override the video path with --record-path out.mp4 or disable recording with --no-record.
The runs/ directory is tracked in git so you can push runs back to the repo for analysis. The script prints the exact git add / commit / push lines at the end of each run.
For the ZED Mini in webcam mode, point at the right camera index:
python dance.py song.mp3 --camera 0 # try 0 first
python dance.py song.mp3 --camera 1 # if 0 is the laptop's FaceTime cameraFor high-BPM songs, dance on every other beat:
python dance.py /path/to/song.mp3 --every-nth 2While the script is running you can stop it with any of:
- press
q(orQ, orESC) in the terminal - press
Ctrl-C(first press = graceful stop, second press = hard kill)
Graceful stop halts the arm at its current pose, finishes recording, muxes the song into the saved video, then disconnects. The video is always written:
- if
ffmpegsucceeds:runs/dance_<song>_<ts>.mp4with audio - if
ffmpegfails or isn't installed:runs/dance_<song>_<ts>.silent.mp4(no audio, can be remuxed later)
This script is intentionally conservative. The arm will not be sent into wild swings.
- All target poses are clipped to a per-joint envelope around a comfortable home pose (
HOME_POSE_DEGandMAX_JOINT_DELTA_DEGindance.py). Envelope verified inside published xArm 7 joint limits with wide margin. - Default joint speed
12 deg/s, accel300 deg/s^2, gentle. Hard refuses values above35 deg/s/800 deg/s^2. (Bump with--speed N --acc Nonce you're confident.) - Beat throttle (
MIN_MOVE_PERIOD_S = 0.75s) drops beats that arrive too close together, so fast songs don't whip the arm. - Camera index falls back: if
--camera 0doesn't open, the script scans indices 0..9 and uses the first working device, so it works regardless of whether the ZED Mini, a USB webcam, or anything else is plugged in. - On startup the arm moves to home before any beat command is sent. On shutdown it returns to zero pose.
--dry-runruns the full pipeline (audio analysis, scheduling, audio playback) without ever connecting to the arm.
- Add or replace poses in
POSE_BANKindance.py. Each row is a delta in degrees added toHOME_POSE_DEG. Stay withinMAX_JOINT_DELTA_DEG. - Change
HOME_POSE_DEGto face the dance toward your audience. - Increase
--every-nthfor slower, calmer dancing on busy songs.
MIT, open source. See LICENSE. The beat tracker, pose bank, safety envelope, and recorder are all in this repo.