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.

103 lines
6.7 KiB

  1. # Motivation
  2. The aim of this document is to be the starting point for generating new ROS tutorials and to maintain consistency in structure and tone across the documentation. It starts off by formalizing the key objectives and then goes on to templatize the structure and tone that we should adopt going forward.
  3. ## Objectives
  4. 1. **Be inclusive of all levels of understanding** - start from the basics and link relevant external content to be concise yet informative
  5. 2. **Reinforce that getting started with Stretch is a breeze** - use easy to understand vocab and a friendly tone to encourage readers
  6. 3. **Encourage users to read other tutorials** - wherever possible, link other tutorials from the documentation to convey completeness and complexity
  7. 4. **Have a clear flow** - start with the theory, show with GIFs what to expect, and then breakdown the code
  8. What follows can be considered the template.
  9. # Major Topic
  10. In this tutorial, we will work with Stretch to explore *the main theme of tutorial* using *primary module* and also learn how to achieve *secondory theme*. If you want to know more about *any previously covered topic* on Stretch and how to get it up and running, we recommend visiting the previous tutorials on [*link to topic*]() and [*link to topic*]().
  11. *Motivation for the problem the topic solves*. The great thing about Stretch is that it comes preloaded with software that makes it a breeze to achieve *theme of the tutorial*.
  12. By the end of this tutorial, we will have a clear idea about how *first minor topic* works and how to use it to achieve *second minor topic* with Stretch. Let's jump in!
  13. ## First Minor Topic Title
  14. [PyTorch](https://pytorch.org/) is an open source end-to-end machine learning framework that makes many pretrained production quality neural networks available for general use. In this tutorial we will use the YOLOv5s model trained on the COCO dataset.
  15. [YOLOv5](https://github.com/ultralytics/yolov5) is a popular object detection model that divides a supplied image into a grid and detects objects in each cell of the grid recursively. The YOLOv5s model that we have deployed on Stretch has been pretrained on the [COCO dataset](https://cocodataset.org/#home) which allows Stretch to detect a wide range of day to day objects. However, that’s not all, in this demo we want to go a step further and use this extremely versatile object detection model to extract useful information about the scene.
  16. ## Second Minor Topic Title
  17. Now, let’s use what we have learned so far to upgrade the collision avoidance demo in a way that Stretch is able to scan an entire room autonomously without bumping into things or people. To account for dynamic obstacles getting too close to the robot, we will define a keepout distance of 0.4 m - detections below this value stop the robot. To keep Stretch from getting too close to static obstacles, we will define another variable called turning distance of 0.75 m - frontal detections below this value make Stretch turn to the left until it sees a clear path ahead.
  18. Building up on this, let's implement a simple logic for obstacle avoidance. The logic can be broken down into three steps:
  19. 1. If the minimum value from the frontal scans is greater than 0.75 m, then continue to move forward
  20. 2. If the minimum value from the frontal scans is less than 0.75 m, then turn to the right until this is no longer true
  21. 3. If the minimum value from the overall scans is less than 0.4 m, then stop the robot
  22. ## Third Minor Topic Title
  23. *If a tutorial covers more than two minor topics, it might be a good idea to break it down into multiple tutorials*
  24. ## Warning
  25. Running this tutorial on Stretch might result in *harm to robot, humans or the surrounding environment*. Please ensure *these conditions*. We recommend *taking these actions* to ensure safe operation.
  26. ## See It In Action
  27. Go ahead and execute the following commands to run the demo and visualize the result in RViz:
  28. Terminal 1:
  29. ```bash
  30. Enter first command here
  31. ```
  32. Terminal 2:
  33. ```bash
  34. Enter second command here
  35. ```
  36. *Enter GIF to show robot behavior*
  37. <p align="center">
  38. <img height=600 src="https://raw.githubusercontent.com/hello-robot/stretch_tutorials/ROS2/images/avoider.gif"/>
  39. </p>
  40. *Enter GIF to show robot and sensor visualization in RViz*
  41. <p align="center">
  42. <img height=600 src="https://raw.githubusercontent.com/hello-robot/stretch_tutorials/ROS2/images/scanfilter.gif"/>
  43. </p>
  44. ## Code Breakdown
  45. Now, let's jump into the code to see how things work under the hood. Follow along [*link to code*]() to have a look at the entire script.
  46. We make use of two separate Python classes for this demo. The FrameListener class is derived from the Node class and is the place where we compute the TF transformations. For an explantion of this class, you can refer to the [TF listener](https://docs.hello-robot.com/0.2/stretch-tutorials/ros2/example_10/) tutorial.
  47. ```python
  48. class FrameListener(Node):
  49. ```
  50. The AlignToAruco class is where we command Stretch to the pose goal. This class is derived from the FrameListener class so that they can both share the node instance.
  51. ```python
  52. class AlignToAruco(FrameListener):
  53. ```
  54. The constructor initializes the Joint trajectory action client. It also initializes the attribute called offset that determines the end distance between the marker and the robot.
  55. ```python
  56. def __init__(self, node, offset=0.75):
  57. self.trans_base = TransformStamped()
  58. self.trans_camera = TransformStamped()
  59. self.joint_state = JointState()
  60. self.offset = offset
  61. self.node = node
  62. self.trajectory_client = ActionClient(self.node, FollowJointTrajectory, '/stretch_controller/follow_joint_trajectory')
  63. server_reached = self.trajectory_client.wait_for_server(timeout_sec=60.0)
  64. if not server_reached:
  65. self.node.get_logger().error('Unable to connect to arm action server. Timeout exceeded.')
  66. sys.exit()
  67. ```
  68. The apply_to_image() method passes the stream of RGB images from the realsense camera to the YOLOv5s model and returns detections in the form of a dictionary consisting of class_id, label, confidence and bouding box coordinates. The last part is exactly what we need for further computations.
  69. ```python
  70. def apply_to_image(self, rgb_image, draw_output=False):
  71. results = self.model(rgb_image)
  72. ...
  73. if draw_output:
  74. output_image = rgb_image.copy()
  75. for detection_dict in results:
  76. self.draw_detection(output_image, detection_dict)
  77. return results, output_image
  78. ```
  79. *Motivate users to play with the code or continue exploring more topics*. Now go ahead and experiment with a few more pretrained models using PyTorch or OpenVINO on Stretch. If you are feeling extra motivated, try creating your own neural networks and training them. Stretch is ready to deploy them!