Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions docs/examples/02_description_models/04_scaling_robot.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
.. _scaling_robots:

*******************************************************************************
Scaling robots
*******************************************************************************

Robot models loaded from URDF files — whether from disk, Github, or a running
ROS instance — follow the `ROS REP-0103 <https://www.ros.org/reps/rep-0103.html>`_
convention and store all geometry in **meters**. Many CAD environments (Rhino,
Grasshopper, etc.) work in **millimeters** by default. The
:meth:`~compas_fab.robots.Robot.scale` method bridges this gap.

Scaling a robot model
=====================

The simplest way to scale is to load a robot and call
:meth:`~compas_fab.robots.Robot.scale` with the desired multiplier.

.. literalinclude :: files/04_scaling_robot.py
:language: python

A few things to keep in mind:

* **Absolute, not cumulative.** :meth:`~compas_fab.robots.Robot.scale` always
sets the scale to the supplied factor relative to the original URDF geometry.
Calling ``robot.scale(1000)`` twice leaves the robot at ``1000x``, not
``1,000,000x``.

* **Idempotent within the same factor.** Repeating a call with the same value
is a no-op — useful for defensive code that may be called multiple times.

* **Reversible.** Call ``robot.scale(1)`` at any time to revert to the
original meter-based dimensions.

* **Affects planning.** Once a scale factor is set, all planning inputs and
outputs (frame positions, trajectory waypoints, IK targets) are
automatically converted to and from the scaled units so the ROS/backend
communication always happens in meters.

Scaling when visualizing
========================

When a scene object (artist) is involved, call :meth:`~compas_fab.robots.Robot.scale`
**after** assigning :attr:`~compas_fab.robots.Robot.scene_object`. This
ensures that both the internal model geometry and the CAD visualization are
updated in a single step.

.. note::

The following example uses the `ROS <https://www.ros.org/>`_ backend.
Before running it, make sure you have the :ref:`ROS backend <ros_backend>`
correctly configured and the :ref:`Panda Demo <ros_bundles_list>` started.

.. literalinclude :: files/04_scaling_robot_from_ros.py
:language: python

Calling :meth:`~compas_fab.robots.Robot.scale` *before* setting
:attr:`~compas_fab.robots.Robot.scene_object` also works: the factor is stored
internally and automatically applied to the scene object when it is assigned
later. Either order is correct; the post-assignment call is shown here because
it makes the intent explicit.

.. raw:: html

<div class="card bg-light">
<div class="card-body">
<div class="card-title">Downloads</div>

* :download:`Scale robot from library (.PY) <files/04_scaling_robot.py>`
* :download:`Scale robot from ROS (Rhino) (.PY) <files/04_scaling_robot_from_ros.py>`

.. raw:: html

</div>
</div>
26 changes: 26 additions & 0 deletions docs/examples/02_description_models/files/04_scaling_robot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from compas_fab.robots import RobotLibrary

# Load a UR5 robot with geometry.
# Robot models loaded from URDF/ROS are defined in meters by convention.
robot = RobotLibrary.ur5(load_geometry=True)

print("Default scale factor:", robot.scale_factor)

# Scale the robot geometry from meters to millimeters.
# Pass the desired scale factor as an absolute multiplier.
robot.scale(1000)

print("Scale factor after scaling to mm:", robot.scale_factor)

# scale() applies an *absolute* (non-cumulative) factor.
# Calling scale(1000) a second time leaves the robot at 1000x, not 1000*1000x.
robot.scale(1000)
print("Scale factor (repeated call, still 1000):", robot.scale_factor)

# Use a different value to change the scale at any point.
robot.scale(10)
print("Scale factor after changing to 10:", robot.scale_factor)

# Revert to the original meters-based scale.
robot.scale(1)
print("Scale factor after reverting to meters:", robot.scale_factor)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from compas.scene import Scene
from compas_fab.backends import RosClient

# NOTE: Requires a running ROS backend. See the ROS Examples section for setup.
with RosClient() as ros:
# Load complete robot model from ROS (geometry is in meters).
robot = ros.load_robot(load_geometry=True)

# Create a scene and obtain a scene object for the robot model.
scene = Scene()
scene_object = scene.add(robot.model)

# Assign the scene object so the robot knows about the visualization.
robot.scene_object = scene_object

# Scale from meters to millimeters.
# Calling scale() *after* setting the scene object ensures that both
# the internal model geometry and the visualization are updated together.
robot.scale(1000)

scene.draw()