PlaCo: The Robotics Library That Turns Balance Into a Constraint Problem
A C++ and Python planning stack from Rhoban that turns humanoid motion into prioritized tasks, then solves them fast enough for real robots that cannot afford to fall.
- PlaCo’s distinctive move is to make humanoid control feel like a ranked negotiation between constraints instead of a pile of ad hoc motion code.
- Its real strength is the abstraction boundary, because tasks become formal objects that can be combined, prioritized, and solved in real time.
- The library’s architecture balances ergonomics and performance, with Python for iteration and C++ for the control loop that has to keep the robot upright.
- PlaCo sits in a narrow but useful niche between bare solver wrappers and giant robotics toolboxes, which is why it reads as a control system rather than a general platform.
Why humanoid control becomes a bargaining problem
A humanoid robot almost never gets one clean objective. It has to keep its balance, place its feet, move its hands, avoid self-collision, and stay within joint limits, all while the world keeps changing. Treat all of those goals as equal and you get trouble fast.
PlaCo’s first useful idea is that the robot’s intent should be split into hard constraints and soft constraints. Some things must hold, like not falling. Other things should hold if possible, like reaching a hand target cleanly.
PlaCo’s central trick: tasks become solvable objects
This is where PlaCo stops being a convenience wrapper and becomes an argument about how to model control. A PositionTask, ComTask, or CentroidalMomentumTask is not just a helper method. It is a way to turn robot intent into a structured optimization problem.
placo::Problem problem;
problem.rewrite_equalities = true;
auto q = problem.add_variable("q", robot.dof());
auto hand = problem.add_task<placo::PositionTask>("hand", robot.frame("hand"));
hand->set_target(target_pose);
hand->priority = placo::TaskPriority::Soft;
auto balance = problem.add_task<placo::ComTask>("com");
balance->set_target(com_target);
balance->priority = placo::TaskPriority::Hard;
problem.solve();
That last line hides a lot. PlaCo does not simply dump matrices into a solver and hope for the best. It organizes the problem first, then solves a control problem that already reflects task priority, feasibility, and runtime constraints.
What the solver does before the solver solves
One of the more interesting details in the codebase is the equality rewrite step. If the library can reduce redundant equalities with QR decomposition before the QP solve, it can shrink the problem and make the control loop behave better under pressure.
That matters because humanoid control is not a desktop optimization demo. It runs in loops where numerical clutter becomes latency, and latency becomes a fall. The pruning step is an engineering move, not a mathematical flourish.
| Step | Naive approach | PlaCo approach |
|---|---|---|
| Equality handling | Send every row directly to the solver | Rewrite and reduce equalities first |
| Runtime impact | More matrix clutter and more solve work | Smaller effective problem when redundancy exists |
| Control loop effect | Higher chance of unnecessary delay | Better fit for real-time execution |
PlaCo is Rhoban's planning and control library. It is built on the top of pinocchio, eiquadprog QP solver, and fully written in C++ with Python bindings, allowing fast prototyping with good runtime performances. It features task-space inverse kinematics and dynamics (see below) high-level API for whole-body control tasks.
Why Rhoban built it this way
Rhoban did not build PlaCo in a vacuum. The team comes out of RoboCup humanoid competition, where a control system gets judged by reality, not elegance. If the robot loses balance, no abstraction diagram can save the point.
That context explains the library’s tone. It is practical, not ornamental. The design keeps the math visible, but the higher purpose is plain: help a robot stand up, move, and recover when the world pushes back.
PlaCo also reflects a team that wanted to publish the machinery, not just the result. The open source package makes their walking and balancing stack inspectable, which is useful for researchers and for anyone trying to ship hardware that cannot afford a dramatic failure mode.
The Python front door, the C++ engine underneath
This split is a big part of PlaCo’s appeal. Python gives engineers a fast way to assemble tasks, test targets, and iterate on controller logic. C++ handles the performance-sensitive path that has to stay responsive when the robot is in motion.
That is a good robotics compromise. It lowers the cost of experimentation without pretending the control loop is lightweight. The user gets a friendly surface, but the library still behaves like infrastructure.
| Layer | What it does | Why it matters |
|---|---|---|
| Python | Rapid prototyping and controller scripting | Speeds up iteration |
| C++ | Real-time control and heavy math | Keeps execution fast and predictable |
| Pinocchio + solver stack | Kinematics, dynamics, QP solving | Turns intent into actuation |
Where PlaCo sits in the robotics stack
PlaCo is not trying to be the whole robotics universe. It is not a simulator, not a trajectory optimizer, and not a giant all-in-one research environment. It sits in the middle, where intent becomes a control command.
That makes it feel closest to tools like Pink and Stack-of-Tasks, while still being narrower and more deployable than Drake. The value is not breadth. It is the combination of whole-body control structure, Python ergonomics, and a C++ runtime that is meant for real hardware.
| Project | Primary purpose | Language model | Best fit |
|---|---|---|---|
| PlaCo | QP-based whole-body control | C++ with Python bindings | Humanoid and legged robots that need practical real-time control |
| Pink | Python QP inverse kinematics | Python-first | Fast prototyping around Pinocchio |
| Stack-of-Tasks | Hierarchical whole-body control | C++ with Python support | Complex research controllers with deeper hierarchy |
| Drake | Broad robotics toolbox | C++ with Python bindings | Teams that want an integrated research and planning ecosystem |
The takeaways for builders
PlaCo is a reminder that good robotics software is often about choosing the right boundary. If the library makes intent legible, constraints explicit, and runtime predictable, it can be much more useful than a larger system with fuzzier edges.
That is the real lesson here. The robot is not just solving a math problem. The software is deciding which problems are allowed to matter, and in what order.