crisp-python 3.1.0__tar.gz → 3.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. {crisp_python-3.1.0/crisp_python.egg-info → crisp_python-3.2.0}/PKG-INFO +1 -1
  2. crisp_python-3.2.0/crisp_py/config/grippers/gripper_robotiq_2f85.yaml +6 -0
  3. crisp_python-3.2.0/crisp_py/config/robots/dynaarm.yaml +1 -0
  4. crisp_python-3.2.0/crisp_py/config/robots/iiwa14.yaml +1 -0
  5. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/control/controller_switcher.py +43 -16
  6. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/gripper/gripper.py +49 -6
  7. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/gripper/gripper_config.py +15 -0
  8. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/robot/robot_config.py +47 -12
  9. {crisp_python-3.1.0 → crisp_python-3.2.0/crisp_python.egg-info}/PKG-INFO +1 -1
  10. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_python.egg-info/SOURCES.txt +3 -0
  11. {crisp_python-3.1.0 → crisp_python-3.2.0}/pyproject.toml +1 -1
  12. {crisp_python-3.1.0 → crisp_python-3.2.0}/LICENSE.md +0 -0
  13. {crisp_python-3.1.0 → crisp_python-3.2.0}/MANIFEST.in +0 -0
  14. {crisp_python-3.1.0 → crisp_python-3.2.0}/README.md +0 -0
  15. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/__init__.py +0 -0
  16. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/camera/__init__.py +0 -0
  17. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/camera/camera.py +0 -0
  18. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/camera/camera_config.py +0 -0
  19. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/__init__.py +0 -0
  20. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/cameras/right_wrist_camera.yaml +0 -0
  21. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/cameras/third_person_camera.yaml +0 -0
  22. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/cameras/wrist_camera.yaml +0 -0
  23. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/clipped_cartesian_impedance.yaml +0 -0
  24. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/default_cartesian_impedance.yaml +0 -0
  25. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/default_operational_space_controller.yaml +0 -0
  26. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/gravity_compensation.yaml +0 -0
  27. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/gravity_compensation_on_plane.yaml +0 -0
  28. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/joint_control.yaml +0 -0
  29. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/joint_velocity_control.yaml +0 -0
  30. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/control/no_friction_cartesian_impedance.yaml +0 -0
  31. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/aloha-gripper.yaml +0 -0
  32. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/gripper_franka.yaml +0 -0
  33. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/gripper_left.yaml +0 -0
  34. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/gripper_left_config.yaml +0 -0
  35. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/gripper_right.yaml +0 -0
  36. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/gripper_right_config.yaml +0 -0
  37. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/gripper_uncalibrated.yaml +0 -0
  38. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/gripper_with_trigger.yaml +0 -0
  39. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/grippers/trigger_left.yaml +0 -0
  40. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/path.py +0 -0
  41. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/robots/fr3.yaml +0 -0
  42. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/robots/fr3_left.yaml +0 -0
  43. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/robots/fr3_right.yaml +0 -0
  44. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/robots/panda.yaml +0 -0
  45. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/sensors/anyskin_sensor.yaml +0 -0
  46. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/sensors/force_torque_sensor.yaml +0 -0
  47. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/config/sensors/mock_force_torque_sensor.yaml +0 -0
  48. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/control/__init__.py +0 -0
  49. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/control/joint_trajectory_controller_client.py +0 -0
  50. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/control/parameters_client.py +0 -0
  51. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/gripper/__init__.py +0 -0
  52. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/robot/__init__.py +0 -0
  53. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/robot/robot.py +0 -0
  54. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/sensors/__init__.py +0 -0
  55. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/sensors/float32_array_sensor.py +0 -0
  56. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/sensors/force_torque_sensor.py +0 -0
  57. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/sensors/sensor.py +0 -0
  58. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/sensors/sensor_config.py +0 -0
  59. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/utils/__init__.py +0 -0
  60. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/utils/callback_monitor.py +0 -0
  61. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/utils/diagnostics_viewer.py +0 -0
  62. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/utils/geometry.py +0 -0
  63. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/utils/sliding_buffer.py +0 -0
  64. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_py/utils/tf_pose.py +0 -0
  65. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_python.egg-info/dependency_links.txt +0 -0
  66. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_python.egg-info/requires.txt +0 -0
  67. {crisp_python-3.1.0 → crisp_python-3.2.0}/crisp_python.egg-info/top_level.txt +0 -0
  68. {crisp_python-3.1.0 → crisp_python-3.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crisp-python
3
- Version: 3.1.0
3
+ Version: 3.2.0
4
4
  Summary: Simple python interface to control robots that use crisp_controllers and other ROS2 components.
5
5
  Project-URL: Homepage, https://utiasDSL.github.io/crisp_controllers/
6
6
  Requires-Python: >=3.11
@@ -0,0 +1,6 @@
1
+ min_value: 0.8
2
+ max_value: 0.0
3
+ command_topic: "/robotiq_gripper_controller/gripper_cmd"
4
+ use_gripper_command_action: True
5
+ max_delta: 1.0
6
+ max_effort: 5.0
@@ -0,0 +1 @@
1
+ robot_type: "dynaarm"
@@ -0,0 +1 @@
1
+ robot_type: "iiwa"
@@ -120,16 +120,26 @@ class ControllerSwitcherClient:
120
120
 
121
121
  return response.ok
122
122
 
123
- def switch_controller(self, controller_name: str) -> bool | None:
123
+ def switch_controller(
124
+ self,
125
+ controller_name: str,
126
+ controllers_that_should_be_active: list[str] | None = None,
127
+ ) -> bool | None:
124
128
  """Switch to a different ros2_controller that is already loaded using a service.
125
129
 
126
130
  First we request a list of current controllers.
127
131
  If the desired controller is not loaded, then we request to load it and configure it.
128
- Finally, we request to switch to the desired controller.
132
+ Then we prepare a list of controllers to deactivate (all active controllers except broadcasters and those that should remain active).
133
+ We also prepare a list of controllers to activate (the desired controller and those that should remain active).
134
+ Finally, we request to switch to the desired controllers.
129
135
 
130
136
  Args:
131
137
  controller_name (str): Name of the controller to switch to.
138
+ controllers_that_should_be_active (list[str] | None): List of controller names to keep active or activate in the switch. Defaults to None.
132
139
  """
140
+ if controllers_that_should_be_active is None:
141
+ controllers_that_should_be_active = []
142
+
133
143
  controllers = self.get_controller_list()
134
144
 
135
145
  active_controllers = [
@@ -144,24 +154,23 @@ class ControllerSwitcherClient:
144
154
  return True
145
155
 
146
156
  if controller_name not in inactive_controllers:
147
- ok = self.load_controller(controller_name)
148
- if not ok:
149
- self.node.get_logger().error(
150
- f"Failed to load controller {controller_name}. Are you sure the controller exists?"
151
- )
152
- raise RuntimeError(f"Failed to load controller {controller_name}.")
153
-
154
- ok = self.configure_controller(controller_name)
155
- if not ok:
156
- self.node.get_logger().error(f"Failed to configure controller {controller_name}.")
157
- raise RuntimeError(f"Failed to configure controller {controller_name}.")
157
+ self._try_loading_and_configuring_controller(controller_name)
158
158
 
159
159
  to_deactivate = []
160
160
  for active_controller in active_controllers:
161
- if not active_controller.endswith("broadcaster"): # Do not deactivate broadcasters
162
- to_deactivate.append(active_controller)
161
+ if active_controller in controllers_that_should_be_active:
162
+ continue # Keep this controller active
163
+
164
+ if active_controller.endswith("broadcaster"): # Do not deactivate broadcasters
165
+ continue
163
166
 
164
- to_activate = [controller_name]
167
+ to_deactivate.append(active_controller)
168
+
169
+ to_activate = [
170
+ inactive_controller
171
+ for inactive_controller in inactive_controllers
172
+ if inactive_controller in controllers_that_should_be_active
173
+ ] + [controller_name]
165
174
 
166
175
  ok = self._switch_controller(to_deactivate, to_activate)
167
176
 
@@ -170,3 +179,21 @@ class ControllerSwitcherClient:
170
179
  raise RuntimeError(f"Failed to switch to controller {controller_name}.")
171
180
 
172
181
  return True
182
+
183
+ def _try_loading_and_configuring_controller(self, controller_name: str) -> None:
184
+ """Try to load and configure a controller.
185
+
186
+ Args:
187
+ controller_name (str): Name of the controller to load and configure.
188
+ """
189
+ ok = self.load_controller(controller_name)
190
+ if not ok:
191
+ self.node.get_logger().error(
192
+ f"Failed to load controller {controller_name}. Are you sure the controller exists?"
193
+ )
194
+ raise RuntimeError(f"Failed to load controller {controller_name}.")
195
+
196
+ ok = self.configure_controller(controller_name)
197
+ if not ok:
198
+ self.node.get_logger().error(f"Failed to configure controller {controller_name}.")
199
+ raise RuntimeError(f"Failed to configure controller {controller_name}.")
@@ -5,6 +5,8 @@ import threading
5
5
  import numpy as np
6
6
  import rclpy
7
7
  import yaml
8
+ from control_msgs.action import GripperCommand
9
+ from rclpy.action.client import ActionClient
8
10
  from rclpy.callback_groups import ReentrantCallbackGroup
9
11
  from rclpy.executors import MultiThreadedExecutor
10
12
  from rclpy.node import Node
@@ -61,12 +63,27 @@ class Gripper:
61
63
  self.node, stale_threshold=self.config.max_joint_delay
62
64
  )
63
65
 
64
- self._command_publisher = self.node.create_publisher(
65
- Float64MultiArray,
66
- self.config.command_topic,
67
- qos_profile_system_default,
68
- callback_group=ReentrantCallbackGroup(),
66
+ self._command_publisher = (
67
+ self.node.create_publisher(
68
+ Float64MultiArray,
69
+ self.config.command_topic,
70
+ qos_profile_system_default,
71
+ callback_group=ReentrantCallbackGroup(),
72
+ )
73
+ if not self.config.use_gripper_command_action
74
+ else None
75
+ )
76
+ self._command_action_client = (
77
+ ActionClient(
78
+ self.node,
79
+ GripperCommand,
80
+ self.config.command_topic,
81
+ callback_group=ReentrantCallbackGroup(),
82
+ )
83
+ if self.config.use_gripper_command_action
84
+ else None
69
85
  )
86
+
70
87
  self._joint_subscriber = self.node.create_subscription(
71
88
  JointState,
72
89
  self.config.joint_state_topic,
@@ -216,7 +233,12 @@ class Gripper:
216
233
 
217
234
  def is_ready(self) -> bool:
218
235
  """Returns True if the gripper is fully ready to operate."""
219
- return self._value is not None
236
+ action_client_ready = (
237
+ self._command_action_client.wait_for_server(timeout_sec=0.0)
238
+ if self._command_action_client
239
+ else True
240
+ )
241
+ return self._value is not None and action_client_ready
220
242
 
221
243
  def wait_until_ready(self, timeout: float = 10.0, check_frequency: float = 10.0):
222
244
  """Wait until the gripper is available."""
@@ -247,6 +269,27 @@ class Gripper:
247
269
  """Publish the target command."""
248
270
  if self._target is None:
249
271
  return
272
+
273
+ if self.config.use_gripper_command_action:
274
+ if self._command_action_client is None:
275
+ raise RuntimeError("Command action client is not initialized.")
276
+
277
+ goal = GripperCommand.Goal()
278
+ goal.command.position = self._unnormalize(
279
+ self.value
280
+ + np.clip(
281
+ self._normalize(self._target) - self.value,
282
+ -self.config.max_delta,
283
+ self.config.max_delta,
284
+ )
285
+ )
286
+ goal.command.max_effort = self.config.max_effort
287
+ self._command_action_client.send_goal_async(goal)
288
+ return
289
+
290
+ if self._command_publisher is None:
291
+ raise RuntimeError("Command publisher is not initialized.")
292
+
250
293
  msg = Float64MultiArray()
251
294
  msg.data = [
252
295
  self._unnormalize(
@@ -13,6 +13,19 @@ class GripperConfig:
13
13
  """Gripper default config.
14
14
 
15
15
  Can be extented to be used with other grippers.
16
+
17
+ Attributes:
18
+ min_value (float): Minimum gripper value (fully closed).
19
+ max_value (float): Maximum gripper value (fully open).
20
+ command_topic (str): Topic to publish gripper commands to.
21
+ joint_state_topic (str): Topic to subscribe for joint states.
22
+ reboot_service (str): Service to reboot the gripper.
23
+ enable_torque_service (str): Service to enable torque on the gripper.
24
+ index (int): Index of the gripper joint in the joint states message.
25
+ publish_frequency (float): Frequency to publish gripper state.
26
+ max_joint_delay (float): Maximum delay for joint state updates.
27
+ max_delta (float): Maximum change in gripper value per update.
28
+ use_gripper_command_action (bool): Whether to use GripperCommandAction.
16
29
  """
17
30
 
18
31
  min_value: float
@@ -25,6 +38,8 @@ class GripperConfig:
25
38
  publish_frequency: float = 30.0
26
39
  max_joint_delay: float = 1.0
27
40
  max_delta: float = 0.1
41
+ use_gripper_command_action: bool = False
42
+ max_effort: float = 10.0
28
43
 
29
44
  @classmethod
30
45
  def from_yaml(cls, path: str | Path, **overrides) -> "GripperConfig": # noqa: ANN003
@@ -202,18 +202,18 @@ class IiwaConfig(RobotConfig):
202
202
 
203
203
  joint_names: list = field(
204
204
  default_factory=lambda: [
205
- "joint_a1",
206
- "joint_a2",
207
- "joint_a3",
208
- "joint_a4",
209
- "joint_a5",
210
- "joint_a6",
211
- "joint_a7",
205
+ "lbr_A1",
206
+ "lbr_A2",
207
+ "lbr_A3",
208
+ "lbr_A4",
209
+ "lbr_A5",
210
+ "lbr_A6",
211
+ "lbr_A7",
212
212
  ]
213
213
  )
214
214
  home_config: list = field(
215
215
  default_factory=lambda: [
216
- 0,
216
+ np.pi / 2,
217
217
  -np.pi / 4,
218
218
  0,
219
219
  -3 * np.pi / 4,
@@ -222,8 +222,8 @@ class IiwaConfig(RobotConfig):
222
222
  np.pi / 4,
223
223
  ]
224
224
  )
225
- base_frame: str = "iiwa_base"
226
- target_frame: str = "tool0"
225
+ base_frame: str = "world"
226
+ target_frame: str = "lbr_link_ee"
227
227
 
228
228
 
229
229
  @dataclass
@@ -258,11 +258,44 @@ class SO101Config(RobotConfig):
258
258
  target_frame: str = "Fixed_Gripper"
259
259
 
260
260
 
261
+ @dataclass
262
+ class DynaArmConfig(RobotConfig):
263
+ """Configuration specific to DynaArm robots.
264
+
265
+ Provides default values for frame names, joint names, and home configuration
266
+ specifically for DynaArm robots.
267
+ """
268
+
269
+ joint_names: list = field(
270
+ default_factory=lambda: [
271
+ "shoulder_rotation",
272
+ "shoulder_flexion",
273
+ "elbow_flexion",
274
+ "forearm_rotation",
275
+ "wrist_flexion",
276
+ "wrist_rotation",
277
+ ]
278
+ )
279
+ home_config: list = field(
280
+ default_factory=lambda: [
281
+ 2.4,
282
+ -0.15,
283
+ 2.0,
284
+ 0.0,
285
+ 1.26,
286
+ 0.0,
287
+ ],
288
+ )
289
+ base_frame: str = "base_link"
290
+ target_frame: str = "flange"
291
+ cartesian_impedance_controller_name: str = "crisp_cartesian_controller"
292
+
293
+
261
294
  def make_robot_config(robot_type: str, **kwargs) -> RobotConfig: # noqa: ANN003
262
295
  """Factory function to create robot configuration objects.
263
296
 
264
297
  Args:
265
- robot_type (str): Type of robot ('franka', 'kinova', 'iiwa', 'so101')
298
+ robot_type (str): Type of robot ('franka', 'kinova', 'iiwa', 'so101', 'dynaarm')
266
299
  **kwargs: Additional keyword arguments to override default configuration
267
300
 
268
301
  Returns:
@@ -283,7 +316,9 @@ def make_robot_config(robot_type: str, **kwargs) -> RobotConfig: # noqa: ANN003
283
316
  return IiwaConfig(**kwargs)
284
317
  elif robot_type == "so101":
285
318
  return SO101Config(**kwargs)
319
+ elif robot_type == "dynaarm":
320
+ return DynaArmConfig(**kwargs)
286
321
  else:
287
322
  raise ValueError(
288
- f"Unsupported robot type: {robot_type}. Supported types: franka, panda, kinova, iiwa, so101"
323
+ f"Unsupported robot type: {robot_type}. Supported types: franka, panda, kinova, iiwa, so101, dynaarm"
289
324
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crisp-python
3
- Version: 3.1.0
3
+ Version: 3.2.0
4
4
  Summary: Simple python interface to control robots that use crisp_controllers and other ROS2 components.
5
5
  Project-URL: Homepage, https://utiasDSL.github.io/crisp_controllers/
6
6
  Requires-Python: >=3.11
@@ -25,12 +25,15 @@ crisp_py/config/grippers/gripper_left.yaml
25
25
  crisp_py/config/grippers/gripper_left_config.yaml
26
26
  crisp_py/config/grippers/gripper_right.yaml
27
27
  crisp_py/config/grippers/gripper_right_config.yaml
28
+ crisp_py/config/grippers/gripper_robotiq_2f85.yaml
28
29
  crisp_py/config/grippers/gripper_uncalibrated.yaml
29
30
  crisp_py/config/grippers/gripper_with_trigger.yaml
30
31
  crisp_py/config/grippers/trigger_left.yaml
32
+ crisp_py/config/robots/dynaarm.yaml
31
33
  crisp_py/config/robots/fr3.yaml
32
34
  crisp_py/config/robots/fr3_left.yaml
33
35
  crisp_py/config/robots/fr3_right.yaml
36
+ crisp_py/config/robots/iiwa14.yaml
34
37
  crisp_py/config/robots/panda.yaml
35
38
  crisp_py/config/sensors/anyskin_sensor.yaml
36
39
  crisp_py/config/sensors/force_torque_sensor.yaml
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "crisp-python"
3
- version = "3.1.0"
3
+ version = "3.2.0"
4
4
  description = "Simple python interface to control robots that use crisp_controllers and other ROS2 components."
5
5
  readme = "README.md"
6
6
  license-files = ["LICENSE.md"]
File without changes
File without changes
File without changes
File without changes