@@ -254,19 +254,19 @@ def __init__(
254254
255255 logger .info ("URRobot initialized at %s" , ip )
256256
257- def activate_gripper (self , * , timeout : float = 10.0 ) -> bool :
258- """Activate the gripper with a timeout .
257+ def _activate_gripper (self , * , timeout : float = 10.0 ) -> bool :
258+ """Activate the gripper with error handling (internal use) .
259259
260260 Tries to activate the configured gripper. If activation fails
261261 or times out (e.g., gripper not physically connected), disconnects
262262 the gripper, nulls out ``self._gripper``, and returns ``False``.
263263
264- This is the single place that handles gripper activation — the
265- CLI and library code should call this rather than touching
266- `` gripper.activate()`` directly .
264+ Users should call ``robot. gripper.activate()`` directly instead.
265+ This method exists for the CLI which needs graceful fallback
266+ when the gripper isn't connected .
267267
268268 Args:
269- timeout: Maximum seconds to wait for activation (default 5 .0).
269+ timeout: Maximum seconds to wait for activation (default 10 .0).
270270
271271 Returns:
272272 ``True`` if the gripper was activated successfully,
@@ -1113,16 +1113,31 @@ def move_sequence(
11131113 except Exception as e :
11141114 raise MotionError (f"move_sequence failed: { e } " )
11151115
1116+ def zero_ft_sensor (self ) -> None :
1117+ """Zero the robot's force/torque sensor.
1118+
1119+ Clears the baseline so that subsequent force/torque readings
1120+ reflect only forces applied after this call. Call before
1121+ ``move_until_contact()`` or any force-based operation.
1122+
1123+ Raises:
1124+ MotionError: If the command fails.
1125+ """
1126+ self ._check_connection ()
1127+ self ._motion .zero_ft_sensor ()
1128+
11161129 def move_until_contact (
11171130 self ,
11181131 speed_vector : list [float ],
11191132 * ,
11201133 threshold : float = 5.0 ,
11211134 acceleration : float = 0.1 ,
1135+ zero_first : bool = True ,
11221136 ) -> None :
11231137 """Move until contact is detected via TCP force sensing.
11241138
11251139 Runs an interruptible control loop — press Ctrl+C to stop at any time.
1140+ Zeros the FT sensor by default before reading the baseline.
11261141
11271142 Args:
11281143 speed_vector: 6-element speed vector
@@ -1131,17 +1146,22 @@ def move_until_contact(
11311146 Contact fires when any wrench component changes by more
11321147 than this value from the baseline reading.
11331148 acceleration: Acceleration limit passed to ``speedL()`` in m/s².
1149+ zero_first: If True (default), zero the FT sensor before reading
1150+ the baseline. Set to False if you need absolute force values.
11341151
11351152 Example:
1136- >>> # Move straight down until contact
1153+ >>> # Move straight down until contact (zeros FT sensor first)
11371154 >>> robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
11381155 >>> # Higher threshold for heavier contact
11391156 >>> robot.move_until_contact([0, 0, -0.02, 0, 0, 0], threshold=10.0)
11401157 """
11411158 self ._check_connection ()
11421159 self ._disable_freedrive_guard ()
11431160 self ._motion .move_until_contact (
1144- speed_vector , threshold = threshold , acceleration = acceleration
1161+ speed_vector ,
1162+ threshold = threshold ,
1163+ acceleration = acceleration ,
1164+ zero_first = zero_first ,
11451165 )
11461166
11471167 def move_velocity (
0 commit comments