PageRenderTime 70ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/udom_demo/udom_deformation_control/src/udom_deformation_control/coordinator_icra.py

https://gitlab.com/jsanch/udom
Python | 357 lines | 324 code | 6 blank | 27 comment | 2 complexity | 5914f440f89dd67fd3888e47d52c8428 MD5 | raw file
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. """
  4. This node uses a pipeline of components to perform deformation control using a
  5. a KUKA arm and a force/torque sensor. The component serves as a configurator/coordinator,
  6. i.e. it sets the required parameters for all the components and starts/stops them accordingly.
  7. It uses the following nodes:
  8. * `udom_sensor_model/force_sensor_model`
  9. * `udom_geometric_transformation/twist_rotator`
  10. * `udom_geometric_transformation/wrench_rotator`
  11. * `udom_geometric_transformation/wrench_transformer`
  12. * `udom_geometric_transformation/nodal_force_calculator`
  13. * `udom_topic_tools/topic_throttle`
  14. * `udom_deformation_modeling/deformation_model`
  15. * `udom_geometric_transformation/pose_extractor`
  16. * `udom_pose_control/pose_controller`
  17. **Assumptions:**
  18. * It assumes a force/torque sensor as input sensor.
  19. **Input(s):**
  20. * `wrench_in`: The output data of the force sensor.
  21. - *type:* `geometry_msgs/WrenchStamped`
  22. * `robot_data`: The data from encoders and IMUs used to predict a wrench at the robot's end effector.
  23. - *type:* `std_msgs/Float64MultiArray`
  24. * `event_in`: The desired event for the node:
  25. `e_start`: starts the component.
  26. `e_stop`: stops the component.
  27. `e_reset`: resets the mesh to its original undeformed state.
  28. - *type:* `std_msgs/String`
  29. **Output(s):**
  30. * `mesh`: A mesh representation of the object with the updated nodes' position based
  31. on the deformation.
  32. - *type:* `udom_modeling_msgs/Mesh`
  33. * `twist`: Twist command to the robot controller.
  34. - *type:* `geometry_msgs/TwistStamped`
  35. * `event_out`: The current event of the node.
  36. `e_running`: when the component is running.
  37. `e_stopped`: when the component is stopped.
  38. - *type:* `std_msgs/String`
  39. **Parameter(s):**
  40. * `loop_rate`: Node cycle rate (in Hz).
  41. * `mesh_filename`: Filename of the volumetric mesh in a .veg format. **Note:** This file
  42. should be located in the config directory of the `deformation_sensing` package.
  43. * `object_frame`: Reference frame of the object.
  44. * `twist_frame`: The twist will be described with respect to this frame (e.g. end-effector frame).
  45. * `pose_nodes`: Nodes used to extract a pose from the mesh.
  46. * `constrained_nodes`: Constrained vertices of the mesh. Each constrained node must
  47. specify its three degrees of freedom. E.g., to constrain vertices 4, 10 and 14 the
  48. constrained_nodes should be [12, 13, 14, 30, 31, 32, 42, 43, 44].
  49. """
  50. import rospy
  51. import std_msgs.msg
  52. class Coordinator(object):
  53. """
  54. Coordinates a set of components to control the deformation of an object.
  55. """
  56. def __init__(self):
  57. """
  58. Instantiates a node to coordinate the components of the deformation control pipeline.
  59. """
  60. # Params
  61. self.started_components = False
  62. self.event = None
  63. self.sensor_model_status = None
  64. self.twist_rotator_status = None
  65. self.pose_extractor_status = None
  66. self.pose_controller_status = None
  67. self.wrench_transformer_status = None
  68. self.wrench_rotator_status = None
  69. self.nodal_force_calculator_status = None
  70. self.topic_throttle_status = None
  71. self.deformation_model_status = None
  72. # Node cycle rate (in Hz).
  73. self.loop_rate = rospy.Rate(rospy.get_param('~loop_rate', 500))
  74. # Publishers
  75. self.event_out = rospy.Publisher("~event_out", std_msgs.msg.String, queue_size=10)
  76. self.start_sensor_model = rospy.Publisher(
  77. "~start_sensor_model", std_msgs.msg.String, queue_size=10, latch=True)
  78. self.start_twist_rotator = rospy.Publisher(
  79. "~start_twist_rotator", std_msgs.msg.String, queue_size=10, latch=True)
  80. self.start_pose_extractor = rospy.Publisher(
  81. "~start_pose_extractor", std_msgs.msg.String, queue_size=10, latch=True)
  82. self.start_pose_controller = rospy.Publisher(
  83. "~start_pose_controller", std_msgs.msg.String, queue_size=10, latch=True)
  84. self.start_wrench_transformer = rospy.Publisher(
  85. "~start_wrench_transformer", std_msgs.msg.String, queue_size=10, latch=True)
  86. self.start_wrench_rotator = rospy.Publisher(
  87. "~start_wrench_rotator", std_msgs.msg.String, queue_size=10, latch=True)
  88. self.start_nodal_force_calculator = rospy.Publisher(
  89. "~start_nodal_force_calculator", std_msgs.msg.String, queue_size=10, latch=True)
  90. self.start_topic_throttle = rospy.Publisher(
  91. "~start_topic_throttle", std_msgs.msg.String, queue_size=10, latch=True)
  92. self.start_deformation_model = rospy.Publisher(
  93. "~start_deformation_model", std_msgs.msg.String, queue_size=10, latch=True)
  94. # Subscribers
  95. rospy.Subscriber("~event_in", std_msgs.msg.String, self.event_in_cb)
  96. rospy.Subscriber(
  97. "~sensor_model_status", std_msgs.msg.String, self.sensor_model_status_cb)
  98. rospy.Subscriber(
  99. "~twist_rotator_status", std_msgs.msg.String, self.twist_rotator_status_cb)
  100. rospy.Subscriber(
  101. "~pose_extractor_status", std_msgs.msg.String, self.pose_extractor_status_cb)
  102. rospy.Subscriber(
  103. "~pose_controller_status", std_msgs.msg.String, self.pose_controller_status_cb)
  104. rospy.Subscriber(
  105. "~wrench_transformer_status", std_msgs.msg.String, self.wrench_transformer_status_cb)
  106. rospy.Subscriber(
  107. "~wrench_rotator_status", std_msgs.msg.String, self.wrench_rotator_status_cb)
  108. rospy.Subscriber(
  109. "~nodal_force_calculator_status", std_msgs.msg.String,
  110. self.nodal_force_calculator_status_cb)
  111. rospy.Subscriber(
  112. "~topic_throttle_status", std_msgs.msg.String, self.topic_throttle_status_cb)
  113. rospy.Subscriber(
  114. "~deformation_model_status", std_msgs.msg.String, self.deformation_model_status_cb)
  115. def event_in_cb(self, msg):
  116. """
  117. Obtains an event for the component.
  118. :param msg: Event message for the node.
  119. :type msg: std_msgs.msg.String
  120. """
  121. self.event = msg.data
  122. def sensor_model_status_cb(self, msg):
  123. """
  124. Obtains the status of the component (as an event).
  125. :param msg: Event message for the node.
  126. :type msg: std_msgs.msg.String
  127. """
  128. self.sensor_model_status = msg.data
  129. def twist_rotator_status_cb(self, msg):
  130. """
  131. Obtains the status of the component (as an event).
  132. :param msg: Event message for the node.
  133. :type msg: std_msgs.msg.String
  134. """
  135. self.twist_rotator_status = msg.data
  136. def pose_extractor_status_cb(self, msg):
  137. """
  138. Obtains the status of the component (as an event).
  139. :param msg: Event message for the node.
  140. :type msg: std_msgs.msg.String
  141. """
  142. self.pose_extractor_status = msg.data
  143. def pose_controller_status_cb(self, msg):
  144. """
  145. Obtains the status of the component (as an event).
  146. :param msg: Event message for the node.
  147. :type msg: std_msgs.msg.String
  148. """
  149. self.pose_controller_status = msg.data
  150. def wrench_transformer_status_cb(self, msg):
  151. """
  152. Obtains the status of the component (as an event).
  153. :param msg: Event message for the node.
  154. :type msg: std_msgs.msg.String
  155. """
  156. self.wrench_transformer_status = msg.data
  157. def wrench_rotator_status_cb(self, msg):
  158. """
  159. Obtains the status of the component (as an event).
  160. :param msg: Event message for the node.
  161. :type msg: std_msgs.msg.String
  162. """
  163. self.wrench_rotator_status = msg.data
  164. def nodal_force_calculator_status_cb(self, msg):
  165. """
  166. Obtains the status of the component (as an event).
  167. :param msg: Event message for the node.
  168. :type msg: std_msgs.msg.String
  169. """
  170. self.nodal_force_calculator_status = msg.data
  171. def topic_throttle_status_cb(self, msg):
  172. """
  173. Obtains the status of the topic throttle node (as an event).
  174. :param msg: Event message for the node.
  175. :type msg: std_msgs.msg.String
  176. """
  177. self.topic_throttle_status = msg.data
  178. def deformation_model_status_cb(self, msg):
  179. """
  180. Obtains the status of the component (as an event).
  181. :param msg: Event message for the node.
  182. :type msg: std_msgs.msg.String
  183. """
  184. self.deformation_model_status = msg.data
  185. def start(self):
  186. """
  187. Starts the component.
  188. """
  189. rospy.loginfo("Ready to start...")
  190. state = 'INIT'
  191. while not rospy.is_shutdown():
  192. if state == 'INIT':
  193. state = self.init_state()
  194. elif state == 'RUNNING':
  195. state = self.running_state()
  196. rospy.logdebug("State: {0}".format(state))
  197. self.loop_rate.sleep()
  198. def init_state(self):
  199. """
  200. Executes the INIT state of the state machine.
  201. :return: The updated state.
  202. :rtype: str
  203. """
  204. if self.event in ['e_start', 'e_reset']:
  205. return 'RUNNING'
  206. else:
  207. return 'INIT'
  208. def running_state(self):
  209. """
  210. Executes the RUNNING state of the state machine.
  211. :return: The updated state.
  212. :rtype: str
  213. """
  214. self.toggle_components(self.event)
  215. if self.event == 'e_stop':
  216. status = 'e_stopped'
  217. self.event_out.publish(status)
  218. self.reset_component_data(status)
  219. return 'INIT'
  220. else:
  221. return 'RUNNING'
  222. def toggle_components(self, event):
  223. """
  224. Starts or stops the necessary components based on the event.
  225. :param event: The event that determines either to start or stop the components.
  226. :type event: str
  227. """
  228. if event == 'e_stop':
  229. self.start_sensor_model.publish('e_stop')
  230. self.start_twist_rotator.publish('e_stop')
  231. self.start_pose_extractor.publish('e_stop')
  232. self.start_pose_controller.publish('e_stop')
  233. self.start_wrench_transformer.publish('e_stop')
  234. self.start_wrench_rotator.publish('e_stop')
  235. self.start_nodal_force_calculator.publish('e_stop')
  236. self.start_deformation_model.publish('e_stop')
  237. self.start_topic_throttle.publish('e_stop')
  238. self.started_components = False
  239. if event == 'e_reset':
  240. self.start_deformation_model.publish('e_reset')
  241. self.event = 'e_start'
  242. self.started_components = False
  243. if event == 'e_start' and not self.started_components:
  244. self.start_sensor_model.publish('e_start')
  245. self.start_twist_rotator.publish('e_start')
  246. self.start_pose_extractor.publish('e_start')
  247. self.start_pose_controller.publish('e_start')
  248. self.start_wrench_transformer.publish('e_start')
  249. self.start_wrench_rotator.publish('e_start')
  250. self.start_nodal_force_calculator.publish('e_start')
  251. self.start_topic_throttle.publish('e_start')
  252. self.start_deformation_model.publish('e_start')
  253. self.started_components = True
  254. def reset_component_data(self, result):
  255. """
  256. Clears the data of the component.
  257. :param result: The result_mesh of the component, e.g. stopped, failure, success.
  258. :type result: str
  259. """
  260. self.toggle_components(result)
  261. self.event = None
  262. self.sensor_model_status = None
  263. self.twist_rotator_status = None
  264. self.pose_extractor_status = None
  265. self.pose_controller_status = None
  266. self.wrench_transformer_status = None
  267. self.wrench_rotator_status = None
  268. self.nodal_force_calculator_status = None
  269. self.topic_throttle_status = None
  270. self.deformation_model_status = None
  271. self.started_components = False
  272. def main():
  273. rospy.init_node("coordinator", anonymous=True)
  274. coordinator = Coordinator()
  275. coordinator.start()