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.

149 lines
4.8 KiB

  1. # Example 8
  2. This example will showcase how to save the interpreted speech from Stretch's [ReSpeaker Mic Array v2.0](https://wiki.seeedstudio.com/ReSpeaker_Mic_Array_v2.0/) to a text file.
  3. <p align="center">
  4. <img src="https://raw.githubusercontent.com/hello-robot/stretch_tutorials/noetic/images/respeaker.jpg"/>
  5. </p>
  6. Begin by running the `respeaker.launch.py` file in a terminal.
  7. ```{.bash .shell-prompt}
  8. ros2 launch respeaker_ros2 respeaker.launch.py
  9. ```
  10. Then run the [speech_text.py](https://github.com/hello-robot/stretch_tutorials/blob/humble/stretch_ros_tutorials/speech_text.py) node. In a new terminal, execute:
  11. ```{.bash .shell-prompt}
  12. cd ament_ws/src/stretch_tutorials/stretch_ros_tutorials/
  13. python3 speech_text.py
  14. ```
  15. The ReSpeaker will be listening and will start to interpret speech and save the transcript to a text file. To shut down the node, type `Ctrl` + `c` in the terminal.
  16. ### The Code
  17. ```python
  18. #!/usr/bin/env python3
  19. # Import modules
  20. import rclpy
  21. import os
  22. from rclpy.node import Node
  23. # Import SpeechRecognitionCandidates from the speech_recognition_msgs package
  24. from speech_recognition_msgs.msg import SpeechRecognitionCandidates
  25. class SpeechText(Node):
  26. def __init__(self):
  27. super().__init__('stretch_speech_text')
  28. # Initialize subscriber
  29. self.sub = self.create_subscription(SpeechRecognitionCandidates, "speech_to_text", self.callback, 1)
  30. # Create path to save captured images to the stored data folder
  31. self.save_path = '/home/hello-robot/ament_ws/src/stretch_tutorials/stored_data'
  32. # Create log message
  33. self.get_logger().info("Listening to speech")
  34. def callback(self,msg):
  35. # Take all items in the iterable list and join them into a single string
  36. transcript = ' '.join(map(str,msg.transcript))
  37. # Define the file name and create a complete path name
  38. file_name = 'speech.txt'
  39. completeName = os.path.join(self.save_path, file_name)
  40. # Append 'hello' at the end of file
  41. with open(completeName, "a+") as file_object:
  42. file_object.write("\n")
  43. file_object.write(transcript)
  44. def main(args=None):
  45. # Initialize the node and name it speech_text
  46. rclpy.init(args=args)
  47. # Instantiate the SpeechText class
  48. speech_txt = SpeechText()
  49. # Give control to ROS. This will allow the callback to be called whenever new
  50. # messages come in. If we don't put this line in, then the node will not work,
  51. # and ROS will not process any messages
  52. rclpy.spin(speech_txt)
  53. if __name__ == '__main__':
  54. main()
  55. ```
  56. ### The Code Explained
  57. Now let's break the code down.
  58. ```python
  59. #!/usr/bin/env python3
  60. ```
  61. Every Python ROS [Node](https://docs.ros.org/en/humble/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Nodes/Understanding-ROS2-Nodes.html) will have this declaration at the top. The first line makes sure your script is executed as a Python3 script.
  62. ```python
  63. import rclpy
  64. import os
  65. from rclpy.node import Node
  66. ```
  67. You need to import rclpy if you are writing a ROS Node.
  68. ```python
  69. from speech_recognition_msgs.msg import SpeechRecognitionCandidates
  70. ```
  71. Import `SpeechRecognitionCandidates` from the `speech_recgonition_msgs.msg` so that we can receive the interpreted speech.
  72. ```python
  73. def __init__(self):
  74. super().__init__('stretch_speech_text')
  75. self.sub = self.create_subscription(SpeechRecognitionCandidates, "speech_to_text", self.callback, 1)
  76. ```
  77. Set up a subscriber. We're going to subscribe to the topic `speech_to_text`, looking for `SpeechRecognitionCandidates` messages. When a message comes in, ROS is going to pass it to the function "callback" automatically.
  78. ```python
  79. self.save_path = '/home/hello-robot/ament_ws/src/stretch_tutorials/stored_data'
  80. ```
  81. Define the directory to save the text file.
  82. ```python
  83. transcript = ' '.join(map(str,msg.transcript))
  84. ```
  85. Take all items in the iterable list and join them into a single string named transcript.
  86. ```python
  87. file_name = 'speech.txt'
  88. completeName = os.path.join(self.save_path, file_name)
  89. ```
  90. Define the file name and create a complete path directory.
  91. ```python
  92. with open(completeName, "a+") as file_object:
  93. file_object.write("\n")
  94. file_object.write(transcript)
  95. ```
  96. Append the transcript to the text file.
  97. ```python
  98. def main(args=None):
  99. rclpy.init(args=args)
  100. speech_txt = SpeechText()
  101. ```
  102. The next line, rclpy.init() method initializes the node. In this case, your node will take on the name 'stretch_speech_text'. Instantiate the `SpeechText()` class.
  103. !!! note
  104. The name must be a base name, i.e. it cannot contain any slashes "/".
  105. ```python
  106. rclpy.spin(speech_txt)
  107. ```
  108. Give control to ROS with `rclpy.spin()`. This will allow the callback to be called whenever new messages come in. If we don't put this line in, then the node will not work, and ROS will not process any messages.