Inspiration
You should have perfect hair every time you walk out the door. But your barber is a human being right? They have off days, shaky mornings, and they go on vacation when you need them the most.
So we asked the room: who here has cut their own hair? Plenty of hands. And everyone who's tried knows the same thing. The sides are fine. The top is fine. The back is impossible though because you physically cannot see it, and two mirrors and a prayer is not a technique.
We aspire to solve haircutting as a whole, but for now, we have solved the fade (sides + back). The back is the one piece a person genuinely cannot do for themselves, which happens to be exactly where a fade lives.
What it does
Fade Ninja lets a barber teach a cut once, by hand, and then repeat it forever.
You hold an iPhone like a clipper. ARKit tracks it in 3D and the robot arm mirrors your hand. Move up and the clipper climbs the head, tilt your wrist and the blade angle changes, which is what decides how much hair is left. A hold-to-lock button parks the arm so you can reposition your hand, like lifting a mouse off the pad.
While you work, the system records the cut at 50 Hz and saves it to your account. Later you pick that cut from your library and press replay which then makes the arm run it again on its own, with nobody holding the phone.
Crucially, what gets saved is where the arm actually went, not where the phone thought it was. A drifting sensor can't corrupt the recording. That's the difference between a macro recorder and "your haircut is a file."
How we built it
The physics first. The clipper's heel stays pressed on the scalp and the blade tilts away from it, so hair length is h = L·sin(θ). Sensitivity is 0.43 mm per degree. The alternative: hovering the clipper at a set distance, making every millimetre of positioning error a millimetre of length error against a fade whose entire range is 0.5 to 8 mm. Contact and tilt collapses the error bar, hovering doesn't.
Simulation before hardware. We built a physics-lite simulator of the arm, wrote forward and inverse kinematics with real joint limits and reachability, and put the whole control stack behind 235 automated tests before any metal existed. The same suite validates the real machine.
The stack: an iPhone app (SwiftUI + ARKit) streaming pose over UDP at 50 Hz → a Python server doing IK, joint-limit enforcement, recording and replay → an Arduino driving four servos on a 3D-printed arm (55/80/80 mm links, 61–160 mm reach). A live 3D viewer renders the linkage from the joint angles, and telemetry lands in SQLite, or TimescaleDB as a hypertable when one's configured.
Challenges we ran into
Coordinate frames, three times. The app was sending position in the camera's axes rather than gravity-aligned world axes. Held upright it looked fine but held like an actual clipper, up became forward and moving up yawed the arm sideways. Same class of bug bit us again in orientation: turning the phone horizontally tilted the blade by up to 30° of its 45° range.
A test that agreed with the bug. We had a sign error in the quaternion math, and the unit test didn't catch it because we'd written the test helper with the same wrong convention. It only surfaced when we ran our code against a teammate's independently written simulator and the numbers disagreed.
Clipping joints instead of clamping targets. Reaching past the arm's envelope froze it mid-pose with the elbow still folded, and clipping solved angles pushed the tip ~15 mm off the line you commanded. Clamping the target to the workspace before solving fixed both as the elbow now straightens progressively to reach full height.
The network. Campus wifi uses 802.1X with client isolation, so the phone and laptop simply could not see each other. Hours went into this before we gave up and ran everything off a phone hotspot.
Replay that looked frozen. Long recordings appeared to replay as a motionless arm. The phone was still streaming and overwriting the replayed pose 50 times a second. Solution: put the phone down to watch, and the arm held wherever it was pointing.
Accomplishments that we're proud of
- Teaching a cut and watching the arm repeat it with nobody touching anything. That's the whole thesis, and it works.
- Getting hand-to-clipper motion genuinely 1:1 (not eyeballed) and cutting tracking lag from 0.9 s to 0.3 s once we found the joint speed cap.
- Building the entire machine in simulation first, so we could measure replay fidelity, seam spacing and profile transfer before a single part was printed. When hardware questions came up, we had numbers instead of opinions.
- And an app that's actually pleasant: sign in, a library of your cuts, swipe to delete, haptics on anything that moves a motor.
What we learned
- Simulate first. Every bug we found in the simulator was a bug we didn't find with a motor spinning next to a mannequin's head.
- Record the actuator, not the controller. It's the single decision that makes replay trustworthy, and it means a cheap, drifty sensor is good enough.
- Your own tests can encode your own wrong assumption. Ours passed happily while the sign was backwards. Integration against something written by someone else caught what our unit tests structurally could not.
- Refuse, don't repair. A recording asking for an impossible pose is corrupt data. Smoothing would have quietly pulled it back into range and run it near someone's head.
What's next for Fade Ninja
- Show it a photo, get that haircut. A vision model reads the guideline height and blend span from a reference picture and turns it into a cuttable profile.
- It checks its own work. A fixed camera photographs each pass, flags uneven patches and schedules a corrective pass. We prototyped this and it recovered from a deliberately miscalibrated blade.
- Your cut, anywhere. A saved profile already transfers to a different head size within 0.17 mm in simulation so your fade follows you when you move cities.
- Access. A haircut without the trip, for people for whom the trip is the hard part.
Log in or sign up for Devpost to join the conversation.