# Subscribe to a turtle{1}{2}/pose topic and call handle_turtle_pose # callback function on each message self.subscription = self.create_subscription( Pose, f'/{self.turtlename}/pose', self.handle_turtle_pose, 1) self.subscription
defhandle_turtle_pose(self, msg): # Initialize the transform broadcaster br = TransformBroadcaster(self) t = TransformStamped()
# Read message content and assign it to # corresponding tf variables t.header.stamp = self.get_clock().now().to_msg() t.header.frame_id = 'world' t.child_frame_id = self.turtlename
# Turtle only exists in 2D, thus we get x and y translation # coordinates from the message and set the z coordinate to 0 t.transform.translation.x = msg.x t.transform.translation.y = msg.y t.transform.translation.z = 0.0
# For the same reason, turtle can only rotate around one axis # and this why we set rotation in x and y to 0 and obtain # rotation in z axis from the message q = tf_transformations.quaternion_from_euler(0, 0, msg.theta) t.transform.rotation.x = q[0] t.transform.rotation.y = q[1] t.transform.rotation.z = q[2] t.transform.rotation.w = q[3]
# Turtle only exists in 2D, thus we get x and y translation # coordinates from the message and set the z coordinate to 0 t.transform.translation.x = msg.x t.transform.translation.y = msg.y t.transform.translation.z = 0.0
# For the same reason, turtle can only rotate around one axis # and this why we set rotation in x and y to 0 and obtain # rotation in z axis from the message q = tf_transformations.quaternion_from_euler(0, 0, msg.theta) t.transform.rotation.x = q[0] t.transform.rotation.y = q[1] t.transform.rotation.z = q[2] t.transform.rotation.w = q[3]
之后,进行消息的发布
1 2
# Send the transformation br.sendTransform(t)
You can also publish static transforms with the same pattern by instantiating a tf2_ros.StaticTransformBroadcaster instead of a tf2_ros.TransformBroadcaster. The static transforms will be published on the /tf_static topic and will be sent only when required, not periodically. For more details see here.
# Create a client to spawn a turtle self.client = self.create_client(Spawn, 'spawn')
# Check if the service is available whilenot self.client.wait_for_service(timeout_sec=5.0): self.get_logger().info('service not available, waiting again...')
# Initialize request with turtle name and coordinates # Note that x, y and theta are defined as floats in turtlesim/srv/Spawn request = Spawn.Request() request.name = 'turtle2' request.x = float(4) request.y = float(2) request.theta = float(0) # Call request self.client.call_async(request)
# Call on_timer function every second self._output_timer = self.create_timer(1.0, self.on_timer)
defon_timer(self): # Store frame names in variables that will be used to # compute transformations from_frame_rel = self.target_frame to_frame_rel = 'turtle2'
# Look up for the transformation between target_frame and turtle2 frames # and send velocity commands for turtle2 to reach target_frame try: now = rclpy.time.Time() trans = self._tf_buffer.lookup_transform( to_frame_rel, from_frame_rel, now, timeout=Duration(seconds=1.0)) except LookupException: self.get_logger().info('transform not ready') return
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription from launch.actions import IncludeLaunchDescription from launch.launch_description_sources import PythonLaunchDescriptionSource