{"id":10048,"library":"placo","title":"PlaCo: Rhoban Planning and Control Library","description":"PlaCo (Planning and Control) is a Python library developed by Rhoban for motion planning and control, particularly in robotics applications. It provides tools for inverse kinematics, contact planning, and motion generation, building upon `pinocchio` and `eigenpy`. The library is currently at version 0.9.20 and has an active but somewhat irregular release cadence, often with minor updates.","status":"active","version":"0.9.20","language":"en","source_language":"en","source_url":"https://github.com/rhoban/placo.git","tags":["robotics","kinematics","motion-planning","control","inverse-kinematics","pinocchio","rhoban"],"install":[{"cmd":"pip install placo","lang":"bash","label":"Basic install"},{"cmd":"conda install -c conda-forge placo","lang":"bash","label":"Recommended for C++ dependencies"}],"dependencies":[{"reason":"Numerical operations and array manipulation.","package":"numpy"},{"reason":"Scientific computing tools.","package":"scipy"},{"reason":"Python bindings for Eigen (dense and sparse matrix algebra), core dependency for numerical operations in robotics.","package":"eigenpy"},{"reason":"Robotics library for rigid body dynamics algorithms, core dependency for robot modeling and kinematics.","package":"pinocchio"},{"reason":"Plotting and visualization (optional, but often used in examples).","package":"matplotlib"},{"reason":"Flexible logging library.","package":"loguru"},{"reason":"3D visualization (optional, for displaying robot and environment).","package":"meshcat"}],"imports":[{"note":"Main entry point for robot interaction.","symbol":"RobotWrapper","correct":"import placo\nrobot = placo.RobotWrapper(...)"},{"note":"Used for inverse kinematics.","symbol":"KinematicsSolver","correct":"import placo\nsolver = placo.KinematicsSolver(...)"},{"note":"One of the common task types for inverse kinematics.","symbol":"PositionTask","correct":"import placo\ntask = placo.PositionTask(...)"}],"quickstart":{"code":"import placo\nimport numpy as np\n\n# Create a robot wrapper from an online URDF (e.g., UR5 robot)\n# This avoids local file dependencies for a quick test.\n# Ensure internet connectivity for the URDF download.\nrobot = placo.RobotWrapper(\n    \"https://raw.githubusercontent.com/ros-industrial/universal_robot/kinetic-devel/ur_description/urdf/ur5_robot.urdf\",\n    placo.Flags.FLOATING_BASE # Set to true if the robot base is free-floating (e.g., a humanoid)\n)\n\n# Set an initial configuration for the robot's joints\nrobot.set_joint_positions({\n    \"shoulder_pan_joint\": 0.0,\n    \"shoulder_lift_joint\": -np.pi / 2,\n    \"elbow_joint\": np.pi / 2,\n    \"wrist_1_joint\": -np.pi / 2,\n    \"wrist_2_joint\": -np.pi / 2,\n    \"wrist_3_joint\": 0.0\n})\nrobot.update_kinematics() # Update the robot's internal kinematics based on current joint positions\n\n# Get the current transform (position and orientation) of the 'tool0' end-effector\nT_tool0_world = robot.get_transform(\"tool0\")\ncurrent_position = T_tool0_world.translation\ncurrent_orientation = T_tool0_world.rotation # as a 3x3 rotation matrix\n\n# Define a target for the end-effector: move it slightly forward and up\ntarget_position = current_position + np.array([0.1, 0.0, 0.05]) # Move 10cm in X, 5cm in Z\ntarget_orientation = current_orientation # Keep the current orientation\n\n# Create a kinematics solver instance\nsolver = placo.KinematicsSolver(robot)\n\n# Add tasks to the solver\n# PositionTask: Make the 'tool0' frame reach the target_position\nposition_task = placo.PositionTask(robot.frame_id(\"tool0\"), target_position)\nposition_task.set_weight(1.0) # Set task weight (importance)\nsolver.add_task(position_task)\n\n# OrientationTask: Make the 'tool0' frame match the target_orientation\norientation_task = placo.OrientationTask(robot.frame_id(\"tool0\"), target_orientation)\norientation_task.set_weight(0.5) # Orientation is less critical than position\nsolver.add_task(orientation_task)\n\n# Solve the inverse kinematics problem\nsolver.solve(verbose=False) # Set verbose=True for detailed solver output\nrobot.update_kinematics() # Apply the newly calculated joint positions to the robot model\n\n# Print the results\nnew_T_tool0_world = robot.get_transform(\"tool0\")\nprint(f\"Initial tool0 position: {current_position.round(3)}\")\nprint(f\"Target tool0 position:  {target_position.round(3)}\")\nprint(f\"Final tool0 position:   {new_T_tool0_world.translation.round(3)}\")","lang":"python","description":"This quickstart demonstrates how to instantiate a robot from an online URDF, set an initial configuration, define an inverse kinematics problem with position and orientation tasks for an end-effector, and solve it using PlaCo's `KinematicsSolver`. It then prints the initial, target, and final positions of the end-effector."},"warnings":[{"fix":"Always consult the latest GitHub README or `examples` directory for the most current API usage. Pin your dependency version (`pip install placo==X.Y.Z`) to avoid unexpected breakages.","message":"PlaCo is pre-1.0, and its API can change between minor versions. Methods and class structures may be refactored, leading to `AttributeError` or `TypeError` if code is not updated.","severity":"breaking","affected_versions":"<1.0.0"},{"fix":"For smoother installation, especially on Linux, consider using `conda` (`conda install -c conda-forge placo`) as it often handles C++ dependencies better. Alternatively, ensure all `eigenpy` and `pinocchio` system-level prerequisites are met if installing via `pip`.","message":"Installation can be complex due to underlying C++ dependencies (`eigenpy`, `pinocchio`). Missing system libraries (e.g., Boost, Eigen) or incorrect environment setup can lead to build failures or `ModuleNotFoundError`.","severity":"gotcha","affected_versions":"All"},{"fix":"Always verify PlaCo's coordinate system conventions by testing with simple movements or by referring to `pinocchio`'s documentation, as PlaCo builds on it. Visualizing with `meshcat` or `matplotlib` can help catch issues early.","message":"Robotics libraries often use specific coordinate system conventions (e.g., Z-up vs Y-up) or joint orderings that might differ from other tools or your expectations. Misinterpreting these can lead to unexpected robot behavior.","severity":"gotcha","affected_versions":"All"},{"fix":"Profile your application to identify bottlenecks. For critical real-time components, consider moving the tightest loops to C++ if possible, or optimizing the Python interface calls. Ensure the `verbose` flag on solvers is `False` for production.","message":"While PlaCo provides Python bindings, the core computations are in C++. For very high-frequency or real-time control loops, the Python overhead might introduce latency. Trying to run complex solvers at rates above a few hundred Hz may hit performance limits.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Try installing PlaCo using `conda` (`conda install -c conda-forge placo`). If using `pip`, ensure all system-level C++ prerequisites for `eigenpy` and `pinocchio` are installed (e.g., `libboost-all-dev`, `libeigen3-dev` on Ubuntu) before retrying `pip install placo`.","cause":"The `eigenpy` or `pinocchio` dependency (which are C++ libraries with Python bindings) was not installed correctly or its C++ components failed to build. This is common outside of `conda` environments.","error":"ModuleNotFoundError: No module named 'eigenpy' (or 'pinocchio')"},{"fix":"Provide a correct and accessible path to a URDF file (local or online URL) or pass an already loaded `pinocchio.Model` object. Double-check the path for typos and ensure the file exists/is reachable.","cause":"`placo.RobotWrapper` requires a valid path to a URDF file or a `pinocchio.Model` instance to initialize the robot model.","error":"RuntimeError: A robot must be provided (through path to URDF or Pinocchio model)"},{"fix":"Consult the latest `placo` documentation, the GitHub `README`, or `examples` directory for the correct method names and usage patterns corresponding to your installed version. Consider pinning your `placo` version.","cause":"An API change occurred between `placo` versions, and the method name or signature you are calling no longer exists or has been renamed.","error":"AttributeError: 'RobotWrapper' object has no attribute 'get_transform' (or similar method missing)"},{"fix":"Carefully inspect all arguments provided to `placo` classes and methods, especially for tasks (`PositionTask`, `OrientationTask`), to ensure they are of the expected type (e.g., `numpy` arrays for positions, strings for frame IDs) and are not `None`.","cause":"A parameter passed to a PlaCo task constructor (e.g., target position, joint names, frame ID) is `None` or of an incorrect Python type, which the underlying C++ code cannot handle.","error":"TypeError: argument of type 'NoneType' is not iterable (or similar type-related errors within task setup)"}]}