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.

142 lines
5.1 KiB

  1. ## Example 1
  2. !!! note
  3. ROS 2 tutorials are still under active development.
  4. <p align="center">
  5. <img src="https://raw.githubusercontent.com/hello-robot/stretch_tutorials/ROS2/images/move_stretch.gif"/>
  6. </p>
  7. The goal of this example is to give you an enhanced understanding of how to control the mobile base by sending `Twist` messages to a Stretch robot.
  8. ```{.bash .shell-prompt}
  9. ros2 launch stretch_core stretch_driver.launch.py
  10. ```
  11. To drive the robot in circles with the move node, type the following in a new terminal.
  12. ```{.bash .shell-prompt}
  13. ros2 run stetch_ros_tutorials move
  14. ```
  15. To stop the node from sending twist messages, type **Ctrl** + **c**.
  16. ### The Code
  17. Below is the code which will send *Twist* messages to drive the robot in circles.
  18. ```python
  19. #!/usr/bin/env python3
  20. import rclpy
  21. from rclpy.node import Node
  22. from geometry_msgs.msg import Twist
  23. class Move(Node):
  24. def __init__(self):
  25. super().__init__('stretch_base_move')
  26. self.publisher_ = self.create_publisher(Twist, '/stretch/cmd_vel', 10)
  27. self.get_logger().info("Starting to move in circle...")
  28. timer_period = 0.5 # seconds
  29. self.timer = self.create_timer(timer_period, self.move_around)
  30. def move_around(self):
  31. command = Twist()
  32. command.linear.x = 0.0
  33. command.linear.y = 0.0
  34. command.linear.z = 0.0
  35. command.angular.x = 0.0
  36. command.angular.y = 0.0
  37. command.angular.z = 0.5
  38. self.publisher_.publish(command)
  39. def main(args=None):
  40. rclpy.init(args=args)
  41. base_motion = Move()
  42. rclpy.spin(base_motion)
  43. base_motion.destroy_node()
  44. rclpy.shutdown()
  45. if __name__ == '__main__':
  46. main()
  47. ```
  48. ### The Code Explained
  49. Now let's break the code down.
  50. ```python
  51. #!/usr/bin/env python3
  52. ```
  53. Every Python ROS [Node](http://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 Python script.
  54. ```python
  55. import rclpy
  56. from rclpy.node import Node
  57. from geometry_msgs.msg import Twist
  58. ```
  59. You need to import rclpy if you are writing a ROS 2 Node. The geometry_msgs.msg import is so that we can send velocity commands to the robot.
  60. ```python
  61. class Move(Node):
  62. def __init__(self):
  63. super().__init__('stretch_base_move')
  64. self.publisher_ = self.create_publisher(Twist, '/stretch/cmd_vel', 10)
  65. ```
  66. This section of code defines the talker's interface to the rest of ROS. self.publisher_ = self.create_publisher(Twist, '/stretch/cmd_vel', 10) declares that your node is publishing to the /stretch/cmd_vel topic using the message type Twist. The queue_size argument limits the amount of queued messages if any subscriber is not receiving them fast enough.
  67. ```Python
  68. timer_period = 0.5 # seconds
  69. self.timer = self.create_timer(timer_period, self.move_around)
  70. ```
  71. We create a timer with a period of 0.5 seconds. This timer ensures that the function move_around is called every 0.5 seconds. This ensures a constant rate of 2Hz for the execution loop.
  72. ```Python
  73. command = Twist()
  74. ```
  75. Make a Twist message. We're going to set all of the elements since we
  76. can't depend on them defaulting to safe values.
  77. ```python
  78. command.linear.x = 0.0
  79. command.linear.y = 0.0
  80. command.linear.z = 0.0
  81. ```
  82. A Twist has three linear velocities (in meters per second), along each of the axes. For Stretch, it will only pay attention to the x velocity, since it can't directly move in the y direction or the z-direction. We set the linear velocities to 0.
  83. ```python
  84. command.angular.x = 0.0
  85. command.angular.y = 0.0
  86. command.angular.z = 0.5
  87. ```
  88. A *Twist* also has three rotational velocities (in radians per second).
  89. The Stretch will only respond to rotations around the z (vertical) axis. We set this to a non-zero value.
  90. ```python
  91. self.publisher_.publish(command)
  92. ```
  93. Publish the Twist commands in the previously defined topic name */stretch/cmd_vel*.
  94. ```Python
  95. def main(args=None):
  96. rclpy.init(args=args)
  97. base_motion = Move()
  98. rclpy.spin(base_motion)
  99. base_motion.destroy_node()
  100. rclpy.shutdown()
  101. ```
  102. The next line, rclpy.init(args=args), is very important as it tells ROS to initialize the node. Until rclpy has this information, it cannot start communicating with the ROS Master. In this case, your node will take on the name 'stretch_base_move'. NOTE: the name must be a base name, i.e. it cannot contain any slashes "/". We then create an instance called base_motion of the class Move(). This is then spun using the spin function in rclpy to call the callback functions, in our case the timer that ensures the move_around function is called at a steady rate of 2Hz.
  103. <!-- ## Move Stretch in Simulation
  104. <p align="center">
  105. <img src="images/move.gif"/>
  106. </p>
  107. Using your preferred text editor, modify the topic name of the published *Twist* messages. Please review the edit in the **move.py** script below.
  108. ```python
  109. self.pub = rospy.Publisher('/stretch_diff_drive_controller/cmd_vel', Twist, queue_size=1)
  110. ```
  111. After saving the edited node, bringup [Stretch in the empty world simulation](gazebo_basics.md). To drive the robot with the node, type the follwing in a new terminal
  112. ```
  113. cd catkin_ws/src/stretch_ros_turotials/src/
  114. python3 move.py
  115. ``` -->
  116. To stop the node from sending twist messages, type `Ctrl + c`.