From 0173b2dc37cd9897f8af944149a318f64064dff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C5=A0togl?= Date: Sat, 26 Jul 2014 01:14:22 +0200 Subject: [PATCH 1/3] Added new tutorial for tf2 --- geometry_tutorials/package.xml | 1 + turtle_tf2/CMakeLists.txt | 68 ++++++++++ turtle_tf2/launch/turtle_tf2_demo.launch | 20 +++ turtle_tf2/launch/turtle_tf2_sensor.launch | 4 + turtle_tf2/package.xml | 35 ++++++ turtle_tf2/rviz/turtle_rviz.rviz | 117 ++++++++++++++++++ turtle_tf2/rviz/turtle_rviz_groovy.rviz | 112 +++++++++++++++++ turtle_tf2/scripts/dynamic_tf2_broadcaster.py | 84 +++++++++++++ turtle_tf2/scripts/fixed_tf2_broadcaster.py | 71 +++++++++++ turtle_tf2/scripts/turtle_tf2_broadcaster.py | 72 +++++++++++ turtle_tf2/scripts/turtle_tf2_listener.py | 69 +++++++++++ .../scripts/turtle_tf2_listener_wait.py | 69 +++++++++++ .../scripts/turtle_tf2_message_broadcaster.py | 72 +++++++++++ turtle_tf2/src/turtle_tf2_broadcaster.cpp | 42 +++++++ turtle_tf2/src/turtle_tf2_listener.cpp | 46 +++++++ 15 files changed, 882 insertions(+) create mode 100644 turtle_tf2/CMakeLists.txt create mode 100644 turtle_tf2/launch/turtle_tf2_demo.launch create mode 100644 turtle_tf2/launch/turtle_tf2_sensor.launch create mode 100644 turtle_tf2/package.xml create mode 100644 turtle_tf2/rviz/turtle_rviz.rviz create mode 100644 turtle_tf2/rviz/turtle_rviz_groovy.rviz create mode 100755 turtle_tf2/scripts/dynamic_tf2_broadcaster.py create mode 100755 turtle_tf2/scripts/fixed_tf2_broadcaster.py create mode 100755 turtle_tf2/scripts/turtle_tf2_broadcaster.py create mode 100755 turtle_tf2/scripts/turtle_tf2_listener.py create mode 100755 turtle_tf2/scripts/turtle_tf2_listener_wait.py create mode 100755 turtle_tf2/scripts/turtle_tf2_message_broadcaster.py create mode 100644 turtle_tf2/src/turtle_tf2_broadcaster.cpp create mode 100644 turtle_tf2/src/turtle_tf2_listener.cpp diff --git a/geometry_tutorials/package.xml b/geometry_tutorials/package.xml index f69c281..174449a 100644 --- a/geometry_tutorials/package.xml +++ b/geometry_tutorials/package.xml @@ -15,6 +15,7 @@ catkin turtle_tf + turtle_tf2 diff --git a/turtle_tf2/CMakeLists.txt b/turtle_tf2/CMakeLists.txt new file mode 100644 index 0000000..d0b8b9d --- /dev/null +++ b/turtle_tf2/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 2.8.3) +project(turtle_tf2) +## Find dependencies +find_package(catkin REQUIRED COMPONENTS + geometry_msgs + roscpp + rospy + std_msgs + tf2 + tf2_ros + turtlesim +) + +################################### +## catkin specific configuration ## +################################### +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES turtle_tf2 + CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs tf2 tf2_ros +# DEPENDS system_lib +) + +########### +## Build ## +########### + +include_directories( + ${catkin_INCLUDE_DIRS} +) + +## C++ examples +add_executable(turtle_tf2_broadcaster src/turtle_tf2_broadcaster.cpp) +target_link_libraries(turtle_tf2_broadcaster ${catkin_LIBRARIES}) +if(catkin_EXPORTED_TARGETS) + add_dependencies(turtle_tf2_broadcaster ${catkin_EXPORTED_TARGETS}) +endif() + +add_executable(turtle_tf2_listener src/turtle_tf2_listener.cpp) +target_link_libraries(turtle_tf2_listener ${catkin_LIBRARIES}) +if(catkin_EXPORTED_TARGETS) + add_dependencies(turtle_tf2_listener ${catkin_EXPORTED_TARGETS}) +endif() + +## Install Python Examples +install(PROGRAMS + nodes/dynamic_tf2_broadcaster.py + nodes/fixed_tf2_broadcaster.py + nodes/turtle_tf2_broadcaster.py + nodes/turtle_tf2_listener.py + nodes/turtle_tf2_listener_wait.py + nodes/turtle_tf2_message_broadcaster.py + DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +## Install C++ Examples +install(TARGETS turtle_tf2_broadcaster turtle_tf2_listener + ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +## Install Other Resources +install(DIRECTORY launch + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) + +install(DIRECTORY rviz + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) diff --git a/turtle_tf2/launch/turtle_tf2_demo.launch b/turtle_tf2/launch/turtle_tf2_demo.launch new file mode 100644 index 0000000..86e67c0 --- /dev/null +++ b/turtle_tf2/launch/turtle_tf2_demo.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/turtle_tf2/launch/turtle_tf2_sensor.launch b/turtle_tf2/launch/turtle_tf2_sensor.launch new file mode 100644 index 0000000..4f0adcd --- /dev/null +++ b/turtle_tf2/launch/turtle_tf2_sensor.launch @@ -0,0 +1,4 @@ + + + + diff --git a/turtle_tf2/package.xml b/turtle_tf2/package.xml new file mode 100644 index 0000000..0b163f6 --- /dev/null +++ b/turtle_tf2/package.xml @@ -0,0 +1,35 @@ + + + turtle_tf2 + 0.0.1 + + turtle_tf2 demonstrates how to write a tf2 broadcaster and listener with the turtlesim. The tutle_tf2_listener commands turtle2 to follow turtle1 around as you drive turtle1 using the keyboard. + + Denis Štogl + BSD + + + https://github.com/ros/geometry_tutorials + https://github.com/ros/geometry_tutorials/issues + + Denis Štogl + + catkin + + geometry_msgs + roscpp + rospy + std_msgs + tf2 + tf2_ros + turtlesim + + geometry_msgs + roscpp + rospy + std_msgs + tf2 + tf2_ros + turtlesim + + \ No newline at end of file diff --git a/turtle_tf2/rviz/turtle_rviz.rviz b/turtle_tf2/rviz/turtle_rviz.rviz new file mode 100644 index 0000000..6a87e8d --- /dev/null +++ b/turtle_tf2/rviz/turtle_rviz.rviz @@ -0,0 +1,117 @@ +Panels: + - Class: rviz/Displays + Help Height: 78 + Name: Displays + Property Tree Widget: + Expanded: + - /Global Options1 + - /TF1/Frames1 + Splitter Ratio: 0.5 + Tree Height: 479 + - Class: rviz/Selection + Name: Selection + - Class: rviz/Tool Properties + Expanded: + - /2D Pose Estimate1 + - /2D Nav Goal1 + - /Publish Point1 + Name: Tool Properties + Splitter Ratio: 0.588679 + - Class: rviz/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: "" +Visualization Manager: + Class: "" + Displays: + - Alpha: 0.5 + Cell Size: 1 + Class: rviz/Grid + Color: 160; 160; 164 + Enabled: true + Line Style: + Line Width: 0.03 + Value: Lines + Name: Grid + Normal Cell Count: 0 + Offset: + X: 0 + Y: 0 + Z: 0 + Plane: XY + Plane Cell Count: 10 + Reference Frame: + Value: true + - Class: rviz/TF + Enabled: true + Frame Timeout: 15 + Frames: + All Enabled: false + Marker Scale: 1 + Name: TF + Show Arrows: false + Show Axes: true + Show Names: false + Tree: + {} + Update Interval: 0 + Value: true + Enabled: true + Global Options: + Background Color: 48; 48; 48 + Fixed Frame: /world + Name: root + Tools: + - Class: rviz/Interact + Hide Inactive Objects: true + - Class: rviz/MoveCamera + - Class: rviz/Select + - Class: rviz/FocusCamera + - Class: rviz/Measure + - Class: rviz/SetInitialPose + Topic: /initialpose + - Class: rviz/SetGoal + Topic: /move_base_simple/goal + - Class: rviz/PublishPoint + Single click: true + Topic: /clicked_point + Value: true + Views: + Current: + Class: rviz/Orbit + Distance: 11.8991 + Focal Point: + X: 0 + Y: 0 + Z: 0 + Name: Current View + Near Clip Distance: 0.01 + Pitch: 0.454796 + Target Frame: + Value: Orbit (rviz) + Yaw: 3.5554 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 756 + Hide Left Dock: false + Hide Right Dock: false + QMainWindow State: 000000ff00000000fd00000004000000000000013c0000026dfc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005600fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000002540000011a00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000002c0000026d000000dc00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f0000026dfc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000002c0000026d000000a500fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004fc0000003efc0100000002fb0000000800540069006d00650100000000000004fc0000020b00fffffffb0000000800540069006d00650100000000000004500000000000000000000002af0000026d00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: false + Width: 1276 + X: 4 + Y: 22 diff --git a/turtle_tf2/rviz/turtle_rviz_groovy.rviz b/turtle_tf2/rviz/turtle_rviz_groovy.rviz new file mode 100644 index 0000000..ea0d72c --- /dev/null +++ b/turtle_tf2/rviz/turtle_rviz_groovy.rviz @@ -0,0 +1,112 @@ +Panels: + - Class: rviz/Displays + Help Height: 78 + Name: Displays + Property Tree Widget: + Expanded: + - /Global Options1 + - /TF1/Frames1 + - /TF1/Tree1 + Splitter Ratio: 0.5 + Tree Height: 542 + - Class: rviz/Selection + Name: Selection + - Class: rviz/Tool Properties + Expanded: + - /2D Pose Estimate1 + - /2D Nav Goal1 + Name: Tool Properties + Splitter Ratio: 0.588679 + - Class: rviz/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: "" +Visualization Manager: + Class: "" + Displays: + - Alpha: 0.5 + Cell Size: 1 + Class: rviz/Grid + Color: 160; 160; 164 + Enabled: true + Line Style: + Line Width: 0.03 + Value: Lines + Name: Grid + Normal Cell Count: 0 + Offset: + X: 0 + Y: 0 + Z: 0 + Plane: XY + Plane Cell Count: 10 + Reference Frame: + Value: true + - Class: rviz/TF + Enabled: true + Frame Timeout: 15 + Frames: + All Enabled: true + Marker Scale: 1 + Name: TF + Show Arrows: true + Show Axes: true + Show Names: true + Tree: + {} + Update Interval: 0 + Value: true + Enabled: true + Global Options: + Background Color: 48; 48; 48 + Fixed Frame: /world + Name: root + Tools: + - Class: rviz/MoveCamera + - Class: rviz/Interact + Hide Inactive Objects: true + - Class: rviz/Select + - Class: rviz/SetInitialPose + Topic: /initialpose + - Class: rviz/SetGoal + Topic: /move_base_simple/goal + Value: true + Views: + Current: + Class: rviz/Orbit + Distance: 25.6515 + Focal Point: + X: 0 + Y: 0 + Z: 0 + Name: Current View + Near Clip Distance: 0.01 + Pitch: 0.785398 + Target Frame: + Value: Orbit (rviz) + Yaw: 0.785398 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 756 + Hide Left Dock: false + Hide Right Dock: false + QMainWindow State: 000000ff00000000fd00000004000000000000013c000002acfc0200000005fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005600fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000002c000002ac000000dc00ffffff000000010000010f000002acfc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000002c000002ac000000a500fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004a00000003efc0100000002fb0000000800540069006d00650000000000000004a00000020b00fffffffb0000000800540069006d00650100000000000004500000000000000000000002af000002ac00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: false + Width: 1276 + X: 7 + Y: 22 diff --git a/turtle_tf2/scripts/dynamic_tf2_broadcaster.py b/turtle_tf2/scripts/dynamic_tf2_broadcaster.py new file mode 100755 index 0000000..cd14465 --- /dev/null +++ b/turtle_tf2/scripts/dynamic_tf2_broadcaster.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of the Willow Garage nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import roslib +roslib.load_manifest('turtle_tf2') + +import rospy +import tf2_ros +import math + +if __name__ == '__ STATIC main__': + rospy.init_node('my_tf2_broadcaster') + br = tf2_ros.TransformBroadcaster() + t = geometry_msgs.msg.TransformStamped() + + t.header.frame_id = "turtle1" + t.child_frame_id = "carrot1" + t.transform.translation.x = 0.0 + t.transform.translation.y = 2.0 + t.transform.translation.z = 0.0 + t.transform.rotation.x = 0.0 + t.transform.rotation.y = 0.0 + t.transform.rotation.z = 0.0 + t.transform.rotation.w = 1.0 + + rate = rospy.Rate(10.0) + while not rospy.is_shutdown(): + t.header.stamp = rospy.Time.now() + br.sendTransform(t) + rate.sleep() + +if __name__ == '__main__': + rospy.init_node('my_tf2_broadcaster') + br = tf2_ros.TransformBroadcaster() + t = geometry_msgs.msg.TransformStamped() + + t.header.frame_id = "turtle1" + t.child_frame_id = "carrot1" + + rate = rospy.Rate(10.0) + while not rospy.is_shutdown(): + t = rospy.Time.now().to_sec() * math.pi + + t.header.stamp = rospy.Time.now() + t.transform.translation.x = 10 * math.sin(t) + t.transform.translation.y = 10 * math.cos(t) + t.transform.translation.z = 0.0 + t.transform.rotation.x = 0.0 + t.transform.rotation.y = 0.0 + t.transform.rotation.z = 0.0 + t.transform.rotation.w = 1.0 + + br.sendTransform(t) + rate.sleep() diff --git a/turtle_tf2/scripts/fixed_tf2_broadcaster.py b/turtle_tf2/scripts/fixed_tf2_broadcaster.py new file mode 100755 index 0000000..bdf6dd0 --- /dev/null +++ b/turtle_tf2/scripts/fixed_tf2_broadcaster.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of the Willow Garage nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import roslib +roslib.load_manifest('turtle_tf2') + +import rospy +import tf2_ros +import tf2_ros.msg +import geometry_msgs.msg + + +class FixedTFBroadcaster: + + def __init__(self): + self.pub_tf = rospy.Publisher("/tf", tf2_ros.msg.tfMessage, queue_size=1) + + while not rospy.is_shutdown(): + # Run this loop at about 10Hz + rospy.sleep(0.1) + + t = geometry_msgs.msg.TransformStamped() + t.header.frame_id = "turtle1" + t.header.stamp = rospy.Time.now() + t.child_frame_id = "carrot1" + t.transform.translation.x = 0.0 + t.transform.translation.y = 2.0 + t.transform.translation.z = 0.0 + + t.transform.rotation.x = 0.0 + t.transform.rotation.y = 0.0 + t.transform.rotation.z = 0.0 + t.transform.rotation.w = 1.0 + + tfm = tf2_ros.msg.tfMessage([t]) + self.pub_tf.publish(tfm) + +if __name__ == '__main__': + rospy.init_node('my_tf2_broadcaster') + tfb = FixedTFBroadcaster() + rospy.spin() diff --git a/turtle_tf2/scripts/turtle_tf2_broadcaster.py b/turtle_tf2/scripts/turtle_tf2_broadcaster.py new file mode 100755 index 0000000..2330417 --- /dev/null +++ b/turtle_tf2/scripts/turtle_tf2_broadcaster.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of the Willow Garage nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +#!/usr/bin/env python + +import roslib +roslib.load_manifest('turtle_tf2') +import rospy + +# Because of transformations +import tf + +import tf2_ros +import geometry_msgs.msg +import turtlesim.msg + + +def handle_turtle_pose(msg, turtlename): + br = tf2_ros.TransformBroadcaster() + t = geometry_msgs.msg.TransformStamped() + + t.header.stamp = rospy.Time.now() + t.header.frame_id = "world" + t.child_frame_id = turtlename + t.transform.translation.x = msg.x + t.transform.translation.y = msg.y + t.transform.translation.z = 0.0 + 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] + + br.sendTransform(t) + +if __name__ == '__main__': + rospy.init_node('tf_turtle') + turtlename = rospy.get_param('~turtle') + rospy.Subscriber('/%s/pose' % turtlename, + turtlesim.msg.Pose, + handle_turtle_pose, + turtlename) + rospy.spin() diff --git a/turtle_tf2/scripts/turtle_tf2_listener.py b/turtle_tf2/scripts/turtle_tf2_listener.py new file mode 100755 index 0000000..506c8bc --- /dev/null +++ b/turtle_tf2/scripts/turtle_tf2_listener.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of the Willow Garage nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import roslib +roslib.load_manifest('turtle_tf2') +import rospy + +import math +import tf2_ros +import geometry_msgs.msg +import turtlesim.srv + +if __name__ == '__main__': + rospy.init_node('tf2_turtle') + + tfBuffer = tf2_ros.Buffer() + listener = tf2_ros.TransformListener(tfBuffer) + + rospy.wait_for_service('spawn') + spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn) + spawner(4, 2, 0, 'turtle2') + + turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist, queue_size=1) + + rate = rospy.Rate(10.0) + while not rospy.is_shutdown(): + try: + trans = tfBuffer.lookup_transform('turtle2', 'turtle1', rospy.Time()) + except (tf2_ros.LookupException, tf2_ros.ConnectivityException): + continue + + angular = 4 * math.atan2(trans.transform.translation.y, trans.transform.translation.x) + linear = 0.5 * math.sqrt(trans.transform.translation.x ** 2 + trans.transform.translation.y ** 2) + msg = geometry_msgs.msg.Twist() + msg.linear.x = linear + msg.angular.z = angular + turtle_vel.publish(msg) + + rate.sleep() diff --git a/turtle_tf2/scripts/turtle_tf2_listener_wait.py b/turtle_tf2/scripts/turtle_tf2_listener_wait.py new file mode 100755 index 0000000..089b110 --- /dev/null +++ b/turtle_tf2/scripts/turtle_tf2_listener_wait.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of the Willow Garage nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import roslib +roslib.load_manifest('turtle_tf2') +import rospy + +import math +import tf2_ros +import geometry_msgs.msg +import turtlesim.srv + +if __name__ == '__main__': + rospy.init_node('tf2_turtle') + + tfBuffer = tf2_ros.Buffer() + listener = tf2_ros.TransformListener(tfBuffer) + + rospy.wait_for_service('spawn') + spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn) + spawner(4, 2, 0, 'turtle2') + + turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist, queue_size=1) + + rate = rospy.Rate(10.0) + while not rospy.is_shutdown(): + try: + trans = tfBuffer.lookup_transform('turtle2', 'turtle1', rospy.Time.now(), rospy.Duration(1.0)) + except tf2_ros.Exception: + continue + + angular = 4 * math.atan2(trans.transform.translation.y, trans.transform.translation.x) + linear = 0.5 * math.sqrt(trans.transform.translation.x ** 2 + trans.transform.translation.y ** 2) + msg = geometry_msgs.msg.Twist() + msg.linear.x = linear + msg.angular.z = angular + turtle_vel.publish(msg) + + rate.sleep() diff --git a/turtle_tf2/scripts/turtle_tf2_message_broadcaster.py b/turtle_tf2/scripts/turtle_tf2_message_broadcaster.py new file mode 100755 index 0000000..dfab3a2 --- /dev/null +++ b/turtle_tf2/scripts/turtle_tf2_message_broadcaster.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of the Willow Garage nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +#!/usr/bin/env python + +import roslib +roslib.load_manifest('turtle_tf2') +import rospy + +import turtlesim.msg +import geometry_msgs.msg +import turtlesim.srv +from geometry_msgs.msg import PointStamped, Point +from std_msgs.msg import Header + + +class PointPublisher: + def handle_turtle_pose(self, msg, turtlename): + self.pub.publish(PointStamped(Header(0, rospy.rostime.get_rostime(), "/world"), Point(msg.x, msg.y, 0))) + + def __init__(self): + self.turtlename = "turtle3" # rospy.get_param('~turtle') + self.sub = rospy.Subscriber('/%s/pose' % self.turtlename, + turtlesim.msg.Pose, + self.handle_turtle_pose, + self.turtlename) + self.pub = rospy.Publisher('turtle_point_stamped', PointStamped, queue_size=1) + +if __name__ == '__main__': + rospy.init_node('tf2_turtle_stamped_msg_publisher') + rospy.wait_for_service('spawn') + spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn) + spawner(4, 2, 0, 'turtle3') + + pp = PointPublisher() + + pub = rospy.Publisher("turtle3/cmd_vel", geometry_msgs.msg.Twist, queue_size=1) + while not rospy.is_shutdown(): + msg = geometry_msgs.msg.Twist() + msg.linear.x = 1 + msg.angular.z = 1 + pub.publish(msg) + rospy.sleep(rospy.Duration(0.1)) diff --git a/turtle_tf2/src/turtle_tf2_broadcaster.cpp b/turtle_tf2/src/turtle_tf2_broadcaster.cpp new file mode 100644 index 0000000..e1c1596 --- /dev/null +++ b/turtle_tf2/src/turtle_tf2_broadcaster.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +std::string turtle_name; + + + +void poseCallback(const turtlesim::PoseConstPtr& msg){ + static tf2_ros::TransformBroadcaster br; + geometry_msgs::TransformStamped transformStamped; + + transformStamped.header.stamp = ros::Time::now(); + transformStamped.header.frame_id = "world"; + transformStamped.child_frame_id = turtle_name; + transformStamped.transform.translation.x = msg->x; + transformStamped.transform.translation.y = msg->y; + transformStamped.transform.translation.z = 0.0; + tf2::Quaternion q; + q.setRPY(msg->theta, 0, 0); + transformStamped.transform.rotation.x = q.x(); + transformStamped.transform.rotation.y = q.y(); + transformStamped.transform.rotation.z = q.z(); + transformStamped.transform.rotation.w = q.w(); + + br.sendTransform(transformStamped); +} + +int main(int argc, char** argv){ + ros::init(argc, argv, "my_tf2_broadcaster"); + if (argc != 2){ROS_ERROR("need turtle name as argument"); return -1;}; + turtle_name = argv[1]; + + ros::NodeHandle node; + ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback); + + ros::spin(); + return 0; +}; + diff --git a/turtle_tf2/src/turtle_tf2_listener.cpp b/turtle_tf2/src/turtle_tf2_listener.cpp new file mode 100644 index 0000000..c504b91 --- /dev/null +++ b/turtle_tf2/src/turtle_tf2_listener.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +int main(int argc, char** argv){ + ros::init(argc, argv, "my_tf2_listener"); + + ros::NodeHandle node; + + ros::service::waitForService("spawn"); + ros::ServiceClient add_turtle = + node.serviceClient("spawn"); + turtlesim::Spawn srv; + add_turtle.call(srv); + + ros::Publisher turtle_vel = + node.advertise("turtle2/cmd_vel", 10); + + tf2_ros::Buffer tfBuffer; + tf2_ros::TransformListener tfListener(tfBuffer); + + ros::Rate rate(10.0); + while (node.ok()){ + geometry_msgs::TransformStamped transformStamped; + try{ + transformStamped = tfBuffer.lookupTransform("/turtle2", "/turtle1", + ros::Time(0)); + } + catch (tf2::TransformException &ex) { + ROS_ERROR("%s",ex.what()); + ros::Duration(1.0).sleep(); + } + + geometry_msgs::Twist vel_msg; + vel_msg.angular.z = 4.0 * atan2(transformStamped.transform.translation.y, + transformStamped.transform.translation.x); + vel_msg.linear.x = 0.5 * sqrt(pow(transformStamped.transform.translation.x, 2) + + pow(transformStamped.transform.translation.y, 2)); + turtle_vel.publish(vel_msg); + + rate.sleep(); + } + return 0; +}; From aa2b8f4dc28b992723eda1b45a9e63833c2d8306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C5=A0togl?= Date: Sat, 26 Jul 2014 10:25:07 +0200 Subject: [PATCH 2/3] Errors corrected after testing --- turtle_tf2/scripts/dynamic_tf2_broadcaster.py | 9 +++++---- turtle_tf2/scripts/fixed_tf2_broadcaster.py | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/turtle_tf2/scripts/dynamic_tf2_broadcaster.py b/turtle_tf2/scripts/dynamic_tf2_broadcaster.py index cd14465..6cbde41 100755 --- a/turtle_tf2/scripts/dynamic_tf2_broadcaster.py +++ b/turtle_tf2/scripts/dynamic_tf2_broadcaster.py @@ -36,12 +36,13 @@ import rospy import tf2_ros +import geometry_msgs.msg import math if __name__ == '__ STATIC main__': rospy.init_node('my_tf2_broadcaster') br = tf2_ros.TransformBroadcaster() - t = geometry_msgs.msg.TransformStamped() + t = geometry_msgs.msg.TransformStamped() t.header.frame_id = "turtle1" t.child_frame_id = "carrot1" @@ -69,11 +70,11 @@ rate = rospy.Rate(10.0) while not rospy.is_shutdown(): - t = rospy.Time.now().to_sec() * math.pi + x = rospy.Time.now().to_sec() * math.pi t.header.stamp = rospy.Time.now() - t.transform.translation.x = 10 * math.sin(t) - t.transform.translation.y = 10 * math.cos(t) + t.transform.translation.x = 10 * math.sin(x) + t.transform.translation.y = 10 * math.cos(x) t.transform.translation.z = 0.0 t.transform.rotation.x = 0.0 t.transform.rotation.y = 0.0 diff --git a/turtle_tf2/scripts/fixed_tf2_broadcaster.py b/turtle_tf2/scripts/fixed_tf2_broadcaster.py index bdf6dd0..c871150 100755 --- a/turtle_tf2/scripts/fixed_tf2_broadcaster.py +++ b/turtle_tf2/scripts/fixed_tf2_broadcaster.py @@ -36,14 +36,14 @@ import rospy import tf2_ros -import tf2_ros.msg +import tf2_msgs.msg import geometry_msgs.msg class FixedTFBroadcaster: def __init__(self): - self.pub_tf = rospy.Publisher("/tf", tf2_ros.msg.tfMessage, queue_size=1) + self.pub_tf = rospy.Publisher("/tf", tf2_msgs.msg.TFMessage, queue_size=1) while not rospy.is_shutdown(): # Run this loop at about 10Hz @@ -62,10 +62,11 @@ def __init__(self): t.transform.rotation.z = 0.0 t.transform.rotation.w = 1.0 - tfm = tf2_ros.msg.tfMessage([t]) + tfm = tf2_msgs.msg.TFMessage([t]) self.pub_tf.publish(tfm) if __name__ == '__main__': rospy.init_node('my_tf2_broadcaster') tfb = FixedTFBroadcaster() + rospy.spin() From 49269edb57bd2c6279bcbc40a6ad61634e5a21cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C5=A0togl?= Date: Sat, 26 Jul 2014 11:38:22 +0200 Subject: [PATCH 3/3] Ingnoring exceptions from lookup_transform --- turtle_tf2/scripts/turtle_tf2_listener.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/turtle_tf2/scripts/turtle_tf2_listener.py b/turtle_tf2/scripts/turtle_tf2_listener.py index 506c8bc..a62f0eb 100755 --- a/turtle_tf2/scripts/turtle_tf2_listener.py +++ b/turtle_tf2/scripts/turtle_tf2_listener.py @@ -57,13 +57,14 @@ try: trans = tfBuffer.lookup_transform('turtle2', 'turtle1', rospy.Time()) except (tf2_ros.LookupException, tf2_ros.ConnectivityException): + rospy.sleep(1.0) continue - angular = 4 * math.atan2(trans.transform.translation.y, trans.transform.translation.x) - linear = 0.5 * math.sqrt(trans.transform.translation.x ** 2 + trans.transform.translation.y ** 2) msg = geometry_msgs.msg.Twist() - msg.linear.x = linear - msg.angular.z = angular + + msg.angular.z = 4 * math.atan2(trans.transform.translation.y, trans.transform.translation.x) + msg.linear.x = 0.5 * math.sqrt(trans.transform.translation.x ** 2 + trans.transform.translation.y ** 2) + turtle_vel.publish(msg) rate.sleep()