You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
9.9 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. # Tutorial: Collision Avoidance
  2. In this tutorial, we will discuss the simple collision avoidance system that runs as a part of Stretch Body.
  3. ## Overview
  4. Stretch Body includes a system to prevent inadvertent self-collisions. It will dynamically limit the range of motion of each joint to prevent self-collisions.
  5. !!! warning
  6. Self collisions are still possible while using the collision-avoidance system. The factory default collision models are coarse and not necessarily complete.
  7. This system is turned off by default starting with Stretch 2. It may be turned off by default on many RE1 systems. First check if the collision detection system is turned on:
  8. ```{.bash .shell-prompt}
  9. stretch_params.py | grep use_collision_manager
  10. ```
  11. Output:
  12. ```{.bash .no-copy}
  13. stretch_body.robot_params.nominal_params param.robot.use_collision_manager 1
  14. ```
  15. If it is turned off you can enable it by adding the following to your stretch_user_yaml.py:
  16. ```{.bash .no-copy}
  17. robot:
  18. use_collision_manager: 1
  19. ```
  20. ## Common Self Collisions
  21. Fortunately, the simple kinematics of Stretch make self-collisions fairly uncommon and simple to predict. The primary places where self-collisions may occur are
  22. * The lift lowering the wrist or tool into the base
  23. * The arm retracting the wrist or tool into the base
  24. * The head_pan at `pos==0` and head_tilt at `pos=-90 deg` and the lift raising the arm into the camera (minor collision)
  25. * The Dex Wrist (if installed) colliding with itself
  26. * The Dex Wrist (if installed) colliding with the base
  27. ## Joint Limits
  28. The collision avoidance system works by dynamically modifying the acceptable range of motion for each joint. By default, a joint's range is set to the physical hard stop limits. For example, the lift has a mechanical throw of 1.1m:
  29. ```{.bash .shell-prompt}
  30. stretch_params.py | grep range | grep lift
  31. ```
  32. Output:
  33. ```{.bash .no-copy}
  34. stretch_body.robot_params.factory_params param.lift.range_m [0.0, 1.1]
  35. ```
  36. A reduced range of motion can be set at run-time by setting the Soft Motion Limit. For example, to limit the lift range of motion to 0.3 meters off the base:
  37. ```python
  38. import stretch_body.robot as robot
  39. r=robot.Robot()
  40. r.startup()
  41. r.lift.set_soft_motion_limit_min(0.3)
  42. ```
  43. We see in the [API](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/lift.py), the value of `None` is used to designate no soft limit.
  44. It is possible that when setting the Soft Motion Limit the joint's current position is outside of the specified range. In this case, the joint will move to the nearest soft limit to comply with the limits. This can be demonstrated by:
  45. ```python
  46. import stretch_body.robot as robot
  47. import time
  48. r=robot.Robot()
  49. r.startup()
  50. #Move to 0.2
  51. r.lift.move_to(0.2)
  52. r.push_command()
  53. time.sleep(5.0)
  54. #Will move to 0.3
  55. r.lift.set_soft_motion_limit_min(0.3)
  56. ```
  57. ## Collision Models
  58. The [RobotCollision](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot_collision.py) class manages a set of [RobotCollisionModels](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot_collision.py). Each [RobotCollisionModel](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot_collision.py) computes the soft limits for a subset of joints based on a simple geometric model. This geometric model captures the enumerated set of potential collisions listed above.
  59. We can see which collision models will execute when `use_collision_manager` is set to 1:
  60. ```{.bash .shell-prompt}
  61. stretch_params.py | grep collision | grep enabled
  62. ```
  63. Output:
  64. ```{.bash .no-copy}
  65. stretch_body.robot_params.nominal_params param.collision_arm_camera.enabled 1
  66. stretch_body.robot_params.nominal_params param.collision_stretch_gripper.enabled 1
  67. ```
  68. We see two models. One that protects the camera from the arm, and one that protects the base from the gripper. Each model is registered with the [RobotCollision](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot_collision.py) instance as a loadable plug-in. The [Robot](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot.py) class calls the `RobotCollision.step` method periodically at approximately 10hz.
  69. `RobotCollision.step` computes the 'AND' of the limits specified across each Collision Model such that the most restrictive joint limits are set for each joint using the `set_soft_motion_limit_min` and `set_soft_motion_limt_max` methods.
  70. ## Default Collision Models
  71. The default collision models for Stretch Body are found in [robot_collision_models.py](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot_collision_models.py). As of this writing, the provided models are:
  72. * [CollisionArmCamera](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot_collision_models.py#L8): Avoid collision of the head camera with the arm
  73. * [CollisionStretchGripper](https://github.com/hello-robot/stretch_body/blob/master/body/stretch_body/robot_collision_models.py#L75): Avoid collision of the wrist-yaw and gripper with the base and ground
  74. !!! warning
  75. The provided collision models are coarse and are provided to avoid common potentially harmful collisions only. Using these models it is still possible to collide the robot with itself in some cases.
  76. !!! info
  77. Additional collision models are provided for the DexWrist
  78. ### Working with Models
  79. The collision models to be used by Stretch Body are defined with the `robot_collision` parameter. For example, we see in `robot_params.py` that the CollisionArmCamera is loaded by default:
  80. ```python
  81. "robot_collision": {'models': ['collision_arm_camera']},
  82. ```
  83. We also see that model `collision_arm_camera` is defined as:
  84. ```python
  85. "collision_arm_camera": {
  86. 'enabled': 1,
  87. 'py_class_name': 'CollisionArmCamera',
  88. 'py_module_name': 'stretch_body.robot_collision_models'
  89. }
  90. ```
  91. This instructs RobotCollision to construct a model of type `CollisionArmCamera` and enable it by default. One can disable this model by default by specifying the following `stretch_re1_user_params.yaml`:
  92. ```yaml
  93. collision_arm_camera:
  94. enabled: 0
  95. ```
  96. The entire collision avoidance system can be disabled in `stretch_re1_user_params.yaml` by:
  97. ```yaml
  98. robot:
  99. use_collision_manager: 0
  100. ```
  101. A specific collision model can be enabled or disabled during runtime by:
  102. ```python
  103. import stretch_body.robot
  104. r=stretch_body.robot.Robot()
  105. r.startup()
  106. ... #Do some work
  107. r.collision.disable_model('collsion_arm_camera')
  108. ... #Do some work
  109. r.collision.enable_model('collsion_arm_camera')
  110. ```
  111. Finally, if we want to also use the CollisionStretchGripper model, we can add to `stretch_re1_user_params.py`:
  112. ```yaml
  113. robot_collision:
  114. models:
  115. - collision_arm_camera
  116. - collision_stretch_gripper
  117. ```
  118. ### Creating Custom Collision Models
  119. The `step` method of a RobotCollisionModel returns the desired joint limits given that model. For example, the base class is simply:
  120. ```python
  121. class RobotCollisionModel(Device):
  122. def step(self, status):
  123. return {'head_pan': [None, None],'head_tilt': [None, None],
  124. 'lift': [None, None],'arm': [None, None],'wrist_yaw': [None, None]}
  125. ```
  126. where the value of `None` specifies that no limit is specified and the full range of motion for the joint is acceptable.
  127. We could define a new collision model that simply limits the lift range of motion to 1 meter by:
  128. ```python
  129. class MyCollisionModel(Device):
  130. def step(self, status):
  131. return {'head_pan': [None, None],'head_tilt': [None, None],
  132. 'lift': [None, 1.0],'arm': [None, None],'wrist_yaw': [None, None]}
  133. ```
  134. It is straightforward to create a custom collision model. As an example, we will create a model that avoids collision of the arm with a tabletop by
  135. * Preventing the lift from descending below the table top when the arm is extended
  136. * Allowing the lift to descend below the tabletop so long as the arm retracted
  137. This assumes the arm is initially above the tabletop. To start, in a file `collision_arm_table.py` we add:
  138. ```python
  139. from stretch_body.robot_collision import *
  140. from stretch_body.hello_utils import *
  141. class CollisionArmTable(RobotCollisionModel):
  142. def __init__(self, collision_manager):
  143. RobotCollisionModel.__init__(self, collision_manager, 'collision_arm_table')
  144. def step(self, status):
  145. limits = {'lift': [None, None],'arm': [None, None]}
  146. table_height = 0.5 #m
  147. arm_safe_retract = 0.1 #m
  148. safety_margin=.05#m
  149. x_arm = status['arm']['pos']
  150. x_lift = status['lift']['pos']
  151. #Force arm to stay retracted if below table
  152. if x_lift<table_height:
  153. limits['arm'] = [None, arm_safe_retract-safety_margin]
  154. else:
  155. limits['arm'] = [None, None]
  156. #Force lift to stay above table unless arm is retracted
  157. if x_arm<arm_safe_retract:
  158. limits['lift'] =[None,None]
  159. else:
  160. limits['lift']=[table_height+safety_margin,None]
  161. return limits
  162. ```
  163. In this example, we include the `safety_margin` as a way to introduce some hysteresis around state changes to avoid toggling between the soft limits.
  164. The following command should be run to add the working directory to the PYTHONPATH env. This can also be added to our `.bashrc` to permanently edit the path:
  165. ```{.bash .shell-prompt}
  166. export PYTHONPATH=$PYTHONPATH:/<path_to_modules>
  167. ```
  168. Next, we configure RobotCollision to use our CollisionArmTable model in `stretch_re1_user_yaml`:
  169. ```yaml
  170. robot_collision:
  171. models:
  172. - collision_arm_table
  173. collision_arm_table:
  174. enabled: 1
  175. py_class_name: 'CollisionArmTable'
  176. py_module_name: 'collision_arm_table'
  177. ```
  178. Finally, test out the model by driving the arm and lift around using the Xbox teleoperation tool:
  179. ```{.bash .shell-prompt}
  180. stretch_xbox_controller_teleop.py
  181. ```
  182. ------
  183. <div align="center"> All materials are Copyright 2022 by Hello Robot Inc. Hello Robot and Stretch are registered trademarks.</div>