Georg commited on
Commit
d5b839c
·
1 Parent(s): c1222b2

Enhance UR5 environment jogging functionality with internal fallback

Browse files

- Introduced an internal jogging mechanism for cartesian and joint movements when Nova jogging is unavailable.
- Updated the start_jog method to handle both Nova and internal jogging commands, improving robustness.
- Enhanced stop_jog method to manage both Nova and internal jogging states.
- Modified the step function to apply internal jogging updates to target positions and joint targets, ensuring smooth operation.

robots/ur5/model/scene_t_push.xml CHANGED
@@ -188,8 +188,8 @@
188
  <!-- Movable T-shaped object to push into target -->
189
  <body name="t_object" pos="0.45 0.2 0.43">
190
  <freejoint name="t_object_joint"/>
191
- <geom name="t_object_stem" type="box" pos="0 -0.05 0" size="0.02 0.07 0.01" material="t_object_mat" mass="0.3" friction="1 0.005 0.005"/>
192
- <geom name="t_object_cap" type="box" pos="0 0.03 0" size="0.08 0.02 0.01" material="t_object_mat" mass="0.15" friction="1 0.005 0.005"/>
193
  </body>
194
  </worldbody>
195
 
 
188
  <!-- Movable T-shaped object to push into target -->
189
  <body name="t_object" pos="0.45 0.2 0.43">
190
  <freejoint name="t_object_joint"/>
191
+ <geom name="t_object_stem" type="box" pos="0 -0.05 0" size="0.02 0.07 0.03" material="t_object_mat" mass="3.0" friction="0.3 0.005 0.005"/>
192
+ <geom name="t_object_cap" type="box" pos="0 0.03 0" size="0.08 0.02 0.03" material="t_object_mat" mass="2.0" friction="0.3 0.005 0.005"/>
193
  </body>
194
  </worldbody>
195
 
robots/ur5/ur5_env.py CHANGED
@@ -140,6 +140,7 @@ class UR5Env(gym.Env):
140
  self._use_nova_jogging = False
141
  self._last_nova_sequence = None
142
  self._latest_nova_joints = None
 
143
 
144
  # IK controller for end-effector control
145
  self.controller = IKController(
@@ -338,7 +339,7 @@ class UR5Env(gym.Env):
338
  return self._control_mode
339
 
340
  def start_jog(self, jog_type: str, **kwargs) -> bool:
341
- """Start Nova jogging command.
342
 
343
  Args:
344
  jog_type: 'joint', 'cartesian_translation', or 'cartesian_rotation'
@@ -347,50 +348,102 @@ class UR5Env(gym.Env):
347
  Returns:
348
  True if command sent successfully
349
  """
350
- if not self._use_nova_jogging or self._nova_jogger is None:
351
- print("[Nova] Jogging not enabled or jogger not connected")
352
- return False
353
-
354
- try:
355
- if jog_type == 'joint':
356
- return self._nova_jogger.start_joint_jog(
357
- joint=kwargs.get('joint', 0),
358
- direction=kwargs.get('direction', '+'),
359
- velocity_rads_per_sec=kwargs.get('velocity', 0.5)
360
- )
361
- elif jog_type == 'cartesian_translation':
362
- return self._nova_jogger.start_cartesian_translation(
363
- axis=kwargs.get('axis', 'x'),
364
- direction=kwargs.get('direction', '+'),
365
- velocity_mm_per_sec=kwargs.get('velocity', 50.0),
366
- tcp_id=kwargs.get('tcp_id', 'Flange'),
367
- coord_system_id=kwargs.get('coord_system_id', 'world')
368
- )
369
- elif jog_type == 'cartesian_rotation':
370
- return self._nova_jogger.start_cartesian_rotation(
371
- axis=kwargs.get('axis', 'x'),
372
- direction=kwargs.get('direction', '+'),
373
- velocity_rads_per_sec=kwargs.get('velocity', 0.3),
374
- tcp_id=kwargs.get('tcp_id', 'Flange'),
375
- coord_system_id=kwargs.get('coord_system_id', 'world')
376
- )
377
- else:
378
- print(f"[Nova] Unknown jog type: {jog_type}")
 
379
  return False
380
- except Exception as e:
381
- print(f"[Nova] Error starting jog: {e}")
382
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
 
384
  def stop_jog(self) -> bool:
385
- """Stop any active Nova jogging movement."""
386
- if not self._use_nova_jogging or self._nova_jogger is None:
387
- return False
 
 
 
 
 
388
 
389
- try:
390
- return self._nova_jogger.stop()
391
- except Exception as e:
392
- print(f"[Nova] Error stopping jog: {e}")
393
- return False
 
 
394
 
395
  def set_joint_positions(self, positions, update_ik_target=True):
396
  """Set target joint positions directly (bypasses IK).
@@ -575,6 +628,27 @@ class UR5Env(gym.Env):
575
  self.steps += 1
576
  return self._get_obs()
577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  if self._control_mode == 'ik':
579
  joint_targets = self._compute_joint_targets()
580
  else:
 
140
  self._use_nova_jogging = False
141
  self._last_nova_sequence = None
142
  self._latest_nova_joints = None
143
+ self._active_jog = None # Internal jogging state
144
 
145
  # IK controller for end-effector control
146
  self.controller = IKController(
 
339
  return self._control_mode
340
 
341
  def start_jog(self, jog_type: str, **kwargs) -> bool:
342
+ """Start jogging command (Nova or internal IK fallback).
343
 
344
  Args:
345
  jog_type: 'joint', 'cartesian_translation', or 'cartesian_rotation'
 
348
  Returns:
349
  True if command sent successfully
350
  """
351
+ # Try Nova jogging first if available
352
+ if self._use_nova_jogging and self._nova_jogger is not None:
353
+ try:
354
+ if jog_type == 'joint':
355
+ return self._nova_jogger.start_joint_jog(
356
+ joint=kwargs.get('joint', 0),
357
+ direction=kwargs.get('direction', '+'),
358
+ velocity_rads_per_sec=kwargs.get('velocity', 0.5)
359
+ )
360
+ elif jog_type == 'cartesian_translation':
361
+ return self._nova_jogger.start_cartesian_translation(
362
+ axis=kwargs.get('axis', 'x'),
363
+ direction=kwargs.get('direction', '+'),
364
+ velocity_mm_per_sec=kwargs.get('velocity', 50.0),
365
+ tcp_id=kwargs.get('tcp_id', 'Flange'),
366
+ coord_system_id=kwargs.get('coord_system_id', 'world')
367
+ )
368
+ elif jog_type == 'cartesian_rotation':
369
+ return self._nova_jogger.start_cartesian_rotation(
370
+ axis=kwargs.get('axis', 'x'),
371
+ direction=kwargs.get('direction', '+'),
372
+ velocity_rads_per_sec=kwargs.get('velocity', 0.3),
373
+ tcp_id=kwargs.get('tcp_id', 'Flange'),
374
+ coord_system_id=kwargs.get('coord_system_id', 'world')
375
+ )
376
+ else:
377
+ print(f"[Nova] Unknown jog type: {jog_type}")
378
+ return False
379
+ except Exception as e:
380
+ print(f"[Nova] Error starting jog: {e}")
381
  return False
382
+
383
+ # Fallback to internal IK for cartesian movements
384
+ print(f"[Internal] Using internal IK for jogging: {jog_type}")
385
+ if jog_type in ('cartesian_translation', 'cartesian_rotation'):
386
+ axis = kwargs.get('axis', 'x')
387
+ direction = kwargs.get('direction', '+')
388
+
389
+ # Calculate step size (velocity * dt where dt ~= 0.002s per step)
390
+ # For translation: velocity in mm/s, convert to m/s and multiply by step time
391
+ # For rotation: velocity in rad/s, multiply by step time
392
+ if jog_type == 'cartesian_translation':
393
+ velocity_mm_per_sec = kwargs.get('velocity', 50.0)
394
+ step_size = (velocity_mm_per_sec / 1000.0) * 0.02 # m per update (10 Hz updates)
395
+ else: # rotation
396
+ velocity_rad_per_sec = kwargs.get('velocity', 0.3)
397
+ step_size = velocity_rad_per_sec * 0.02 # radians per update (10 Hz updates)
398
+
399
+ # Apply direction
400
+ if direction == '-':
401
+ step_size = -step_size
402
+
403
+ self._active_jog = {
404
+ 'type': jog_type,
405
+ 'axis': axis,
406
+ 'step_size': step_size
407
+ }
408
+ return True
409
+
410
+ # For joint jogging with internal control
411
+ elif jog_type == 'joint':
412
+ joint = kwargs.get('joint', 0)
413
+ direction = kwargs.get('direction', '+')
414
+ velocity_rad_per_sec = kwargs.get('velocity', 0.5)
415
+
416
+ step_size = velocity_rad_per_sec * 0.02 # radians per update (10 Hz updates)
417
+ if direction == '-':
418
+ step_size = -step_size
419
+
420
+ self._active_jog = {
421
+ 'type': 'joint',
422
+ 'joint': joint,
423
+ 'step_size': step_size
424
+ }
425
+ return True
426
+
427
+ print(f"[Internal] Unknown jog type: {jog_type}")
428
+ return False
429
 
430
  def stop_jog(self) -> bool:
431
+ """Stop any active jogging movement (Nova or internal)."""
432
+ # Stop Nova jogging if active
433
+ if self._use_nova_jogging and self._nova_jogger is not None:
434
+ try:
435
+ return self._nova_jogger.stop()
436
+ except Exception as e:
437
+ print(f"[Nova] Error stopping jog: {e}")
438
+ return False
439
 
440
+ # Stop internal jogging
441
+ if hasattr(self, '_active_jog'):
442
+ self._active_jog = None
443
+ print("[Internal] Stopped internal jogging")
444
+ return True
445
+
446
+ return False
447
 
448
  def set_joint_positions(self, positions, update_ik_target=True):
449
  """Set target joint positions directly (bypasses IK).
 
628
  self.steps += 1
629
  return self._get_obs()
630
 
631
+ # Apply internal jogging if active
632
+ if hasattr(self, '_active_jog') and self._active_jog is not None:
633
+ jog = self._active_jog
634
+ if jog['type'] == 'cartesian_translation':
635
+ # Update target position along specified axis
636
+ axis_idx = {'x': 0, 'y': 1, 'z': 2}[jog['axis']]
637
+ self._target_pos[axis_idx] += jog['step_size']
638
+ elif jog['type'] == 'cartesian_rotation':
639
+ # Update target orientation around specified axis
640
+ axis_idx = {'x': 0, 'y': 1, 'z': 2}[jog['axis']]
641
+ self._target_euler[axis_idx] += jog['step_size']
642
+ elif jog['type'] == 'joint':
643
+ # Update target joint position directly
644
+ self._joint_targets[jog['joint']] += jog['step_size']
645
+ # Clamp to joint limits
646
+ self._joint_targets = np.clip(
647
+ self._joint_targets,
648
+ self.action_space.low[:6],
649
+ self.action_space.high[:6]
650
+ )
651
+
652
  if self._control_mode == 'ik':
653
  joint_targets = self._compute_joint_targets()
654
  else: