diff --git a/docs/examples/02_description_models/04_scaling_robot.rst b/docs/examples/02_description_models/04_scaling_robot.rst new file mode 100644 index 0000000000..556c27503d --- /dev/null +++ b/docs/examples/02_description_models/04_scaling_robot.rst @@ -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 `_ +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 `_ backend. + Before running it, make sure you have the :ref:`ROS backend ` + correctly configured and the :ref:`Panda Demo ` 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 + +
+
+
Downloads
+ +* :download:`Scale robot from library (.PY) ` +* :download:`Scale robot from ROS (Rhino) (.PY) ` + +.. raw:: html + +
+
diff --git a/docs/examples/02_description_models/files/04_scaling_robot.py b/docs/examples/02_description_models/files/04_scaling_robot.py new file mode 100644 index 0000000000..ad78401e90 --- /dev/null +++ b/docs/examples/02_description_models/files/04_scaling_robot.py @@ -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) diff --git a/docs/examples/02_description_models/files/04_scaling_robot_from_ros.py b/docs/examples/02_description_models/files/04_scaling_robot_from_ros.py new file mode 100644 index 0000000000..0bdb108148 --- /dev/null +++ b/docs/examples/02_description_models/files/04_scaling_robot_from_ros.py @@ -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()