PageRenderTime 37ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/udom_demo/udom_deformation_sensing/src/udom_deformation_sensing/coordinator_kamal_approach.py

https://gitlab.com/jsanch/udom
Python | 245 lines | 190 code | 10 blank | 45 comment | 0 complexity | b27b907019de873e4881724911329efc MD5 | raw file
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. """
  4. This node uses a pipeline of components to demonstrate deformation sensing based
  5. on force and position sensing.
  6. The component serves as a configurator/coordinator, i.e. it sets the required
  7. parameters for all the components and starts/stops them accordingly.
  8. It uses the following nodes:
  9. * `udom_geometric_transformation/mesh_shifter`
  10. * `udom_geometric_transformation/position_based_force_calculator_node`
  11. * `udom_topic_tools/force_adder`
  12. * `udom_deformation_modeling/deformation_model`
  13. **Input(s):**
  14. * `event_in`: The desired event for the node:
  15. `e_start`: starts the component.
  16. `e_stop`: stops the component.
  17. **Output(s):**
  18. * `mesh`: A mesh representation of the object with the updated nodes' position based
  19. on the deformation.
  20. - *type:* `udom_modeling_msgs/Mesh`
  21. * `event_out`: The current event of the node.
  22. `e_running`: when the component is running.
  23. `e_stopped`: when the component is stopped.
  24. - *type:* `std_msgs/String`
  25. **Parameter(s):**
  26. * `loop_rate`: Node cycle rate (in Hz).
  27. """
  28. import rospy
  29. import std_msgs.msg
  30. class Coordinator(object):
  31. """
  32. Coordinates a set of components to estimate the deformation of an object caused by
  33. an external force.
  34. """
  35. def __init__(self):
  36. """
  37. Instantiates a node to coordinate the components of the deformation sensing
  38. pipeline.
  39. """
  40. # Params
  41. self.started_components = False
  42. self.event = None
  43. self.mesh_shifter_status = None
  44. self.position_based_force_calculator_status = None
  45. self.force_adder_status = None
  46. self.deformation_model_status = None
  47. # Node cycle rate (in Hz).
  48. self.loop_rate = rospy.Rate(rospy.get_param('~loop_rate', 10))
  49. # Publishers
  50. self.event_out = rospy.Publisher("~event_out", std_msgs.msg.String, queue_size=10)
  51. self.start_mesh_shifter = rospy.Publisher(
  52. "~start_mesh_shifter", std_msgs.msg.String, queue_size=10, latch=True)
  53. self.start_position_based_force_calculator = rospy.Publisher(
  54. "~start_position_based_force_calculator", std_msgs.msg.String, queue_size=10,
  55. latch=True)
  56. self.start_force_adder = rospy.Publisher(
  57. "~start_force_adder", std_msgs.msg.String, queue_size=10, latch=True)
  58. self.start_deformation_model = rospy.Publisher(
  59. "~start_deformation_model", std_msgs.msg.String, queue_size=10, latch=True)
  60. # Subscribers
  61. rospy.Subscriber("~event_in", std_msgs.msg.String, self.event_in_cb)
  62. rospy.Subscriber(
  63. "~mesh_shifter_status", std_msgs.msg.String, self.mesh_shifter_status_cb)
  64. rospy.Subscriber(
  65. "~force_adder_status", std_msgs.msg.String, self.force_adder_status_cb)
  66. rospy.Subscriber(
  67. "~position_based_force_calculator_status", std_msgs.msg.String,
  68. self.position_based_force_calculator_status_cb)
  69. rospy.Subscriber(
  70. "~force_adder_status", std_msgs.msg.String,self.force_adder_status_cb)
  71. rospy.Subscriber(
  72. "~deformation_model_status", std_msgs.msg.String,
  73. self.deformation_model_status_cb)
  74. def event_in_cb(self, msg):
  75. """
  76. Obtains an event for the component.
  77. :param msg: Event message for the node.
  78. :type msg: std_msgs.msg.String
  79. """
  80. self.event = msg.data
  81. def mesh_shifter_status_cb(self, msg):
  82. """
  83. Obtains the status of the mesh shifter (as an event).
  84. :param msg: Event message for the node.
  85. :type msg: std_msgs.msg.String
  86. """
  87. self.mesh_shifter_status = msg.data
  88. def force_adder_status_cb(self, msg):
  89. """
  90. Obtains the status of the force adder(as an event).
  91. :param msg: Event message for the node.
  92. :type msg: std_msgs.msg.String
  93. """
  94. self.force_adder_status = msg.data
  95. def position_based_force_calculator_status_cb(self, msg):
  96. """
  97. Obtains the status of the position based force calculator (as an event).
  98. :param msg: Event message for the node.
  99. :type msg: std_msgs.msg.String
  100. """
  101. self.position_based_force_calculator_status = msg.data
  102. def deformation_model_status_cb(self, msg):
  103. """
  104. Obtains the status of the deformation model (as an event).
  105. :param msg: Event message for the node.
  106. :type msg: std_msgs.msg.String
  107. """
  108. self.deformation_model_status = msg.data
  109. def start(self):
  110. """
  111. Starts the component.
  112. """
  113. rospy.loginfo("Ready to start...")
  114. state = 'INIT'
  115. while not rospy.is_shutdown():
  116. if state == 'INIT':
  117. state = self.init_state()
  118. elif state == 'RUNNING':
  119. state = self.running_state()
  120. rospy.logdebug("State: {0}".format(state))
  121. self.loop_rate.sleep()
  122. def init_state(self):
  123. """
  124. Executes the INIT state of the state machine.
  125. :return: The updated state.
  126. :rtype: str
  127. """
  128. if self.event in ['e_start', 'e_reset']:
  129. return 'RUNNING'
  130. else:
  131. return 'INIT'
  132. def running_state(self):
  133. """
  134. Executes the RUNNING state of the state machine.
  135. :return: The updated state.
  136. :rtype: str
  137. """
  138. self.toggle_components(self.event)
  139. if self.event == 'e_stop':
  140. status = 'e_stopped'
  141. self.event_out.publish(status)
  142. self.reset_component_data(status)
  143. return 'INIT'
  144. else:
  145. return 'RUNNING'
  146. def toggle_components(self, event):
  147. """
  148. Starts or stops the necessary components based on the event.
  149. :param event: The event that determines either to start or stop the components.
  150. :type event: str
  151. """
  152. if event == 'e_stop':
  153. self.start_mesh_shifter.publish('e_stop')
  154. self.start_position_based_force_calculator.publish('e_stop')
  155. self.start_force_adder.publish('e_stop')
  156. self.start_deformation_model.publish('e_stop')
  157. self.start_deformation_model.publish('e_stop')
  158. self.started_components = False
  159. if event == 'e_reset':
  160. self.start_deformation_model.publish('e_reset')
  161. self.event = 'e_start'
  162. self.started_components = False
  163. if event == 'e_start' and not self.started_components:
  164. self.start_mesh_shifter.publish('e_start')
  165. self.start_position_based_force_calculator.publish('e_start')
  166. self.start_force_adder.publish('e_start')
  167. self.start_deformation_model.publish('e_start')
  168. self.started_components = True
  169. def reset_component_data(self, result):
  170. """
  171. Clears the data of the component.
  172. :param result: The result of the component, e.g. stopped, failure, success.
  173. :type result: str
  174. """
  175. self.toggle_components(result)
  176. self.event = None
  177. self.mesh_shifter_status = None
  178. self.position_based_force_calculator_status = None
  179. self.force_adder_status = None
  180. self.deformation_model_status = None
  181. self.started_components = False
  182. def main():
  183. rospy.init_node("coordinator", anonymous=True)
  184. coordinator = Coordinator()
  185. coordinator.start()