diff --git a/ros_ign_gazebo_demos/README.md b/ros_ign_gazebo_demos/README.md
index 238937a2..e610aece 100644
--- a/ros_ign_gazebo_demos/README.md
+++ b/ros_ign_gazebo_demos/README.md
@@ -179,3 +179,14 @@ To try the demo launch:
ros2 launch ros_ign_gazebo_demos joint_states.launch.py
![](images/joint_states.png)
+
+## Bridging joint state and pose publishers
+
+The launch file demonstrates bridging ignition poses to TFMessage to visualize the pose
+and transforms of a robot in rviz.
+
+To try the demo launch:
+
+ ros2 launch ros_ign_gazebo_demos tf_bridge.launch.py
+
+![](images/tf_bridge.gif)
diff --git a/ros_ign_gazebo_demos/images/tf_bridge.gif b/ros_ign_gazebo_demos/images/tf_bridge.gif
new file mode 100644
index 00000000..872737e7
Binary files /dev/null and b/ros_ign_gazebo_demos/images/tf_bridge.gif differ
diff --git a/ros_ign_gazebo_demos/launch/tf_bridge.launch.py b/ros_ign_gazebo_demos/launch/tf_bridge.launch.py
new file mode 100644
index 00000000..e192a8d3
--- /dev/null
+++ b/ros_ign_gazebo_demos/launch/tf_bridge.launch.py
@@ -0,0 +1,50 @@
+# Copyright 2022 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+
+from ament_index_python.packages import get_package_share_directory
+
+from launch import LaunchDescription
+from launch.actions import ExecuteProcess
+from launch_ros.actions import Node
+
+def generate_launch_description():
+ pkg_ros_ign_gazebo_demos = get_package_share_directory('ros_ign_gazebo_demos')
+ return LaunchDescription([
+ # Launch gazebo
+ ExecuteProcess(
+ cmd=['ign','gazebo', '-r', os.path.join(pkg_ros_ign_gazebo_demos,
+ 'models', 'double_pendulum_model.sdf')]
+ ),
+ # Launch a bridge to forward tf and joint states to ros2
+ Node(
+ package='ros_ign_bridge',
+ executable='parameter_bridge',
+ arguments=[
+ '/world/default/model/double_pendulum_with_base0/joint_state@sensor_msgs/msg/JointState[ignition.msgs.Model',
+ '/model/double_pendulum_with_base0/pose@tf2_msgs/msg/TFMessage[ignition.msgs.Pose_V'
+ ],
+ remappings=[
+ ('/model/double_pendulum_with_base0/pose','/tf'),
+ ('/world/default/model/double_pendulum_with_base0/joint_state','/joint_states')
+ ]
+ ),
+ # Launch rviz
+ Node(
+ package='rviz2',
+ executable='rviz2',
+ arguments=['-d', os.path.join(pkg_ros_ign_gazebo_demos, 'rviz', 'tf_bridge.rviz')]
+ )
+ ])
diff --git a/ros_ign_gazebo_demos/models/double_pendulum_model.sdf b/ros_ign_gazebo_demos/models/double_pendulum_model.sdf
new file mode 100644
index 00000000..91e072e4
--- /dev/null
+++ b/ros_ign_gazebo_demos/models/double_pendulum_model.sdf
@@ -0,0 +1,266 @@
+
+
+
+
+ 0.001
+ 1
+
+
+
+ true
+ 0 0 10 0 0 0
+ 0.8 0.8 0.8 1
+ 0.2 0.2 0.2 1
+
+ 1000
+ 0.9
+ 0.01
+ 0.001
+
+ -0.5 0.1 -0.9
+
+
+
+ true
+
+
+
+
+ 0 0 1
+ 100 100
+
+
+
+
+
+
+ 0 0 1
+ 100 100
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+
+
+
+ 0 0 0 0 0 0
+
+
+
+ 100
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+
+
+
+ 0 0 2.1 -1.5708 0 0
+ 0
+
+ 0 0 0.5 0 0 0
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 1.0 0 1.5708 0
+
+
+ 0.1
+ 0.2
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 0.9
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+
+ 0 0 1.0 0 1.5708 0
+
+
+ 0.1
+ 0.2
+
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 0.9
+
+
+
+
+
+
+ 0.25 1.0 2.1 -2 0 0
+ 0
+
+ 0 0 0.5 0 0 0
+
+
+ 0 0 0 0 1.5708 0
+
+
+ 0.08
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 0.9
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0 0 1.5708 0
+
+
+ 0.08
+ 0.3
+
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 0.9
+
+
+
+
+
+
+ base
+ upper_link
+
+ 1.0 0 0
+
+
+
+
+ upper_link
+ lower_link
+
+ 1.0 0 0
+
+
+
+
+
+
+
+ true
+
+ true
+
+
+
+
+
+
diff --git a/ros_ign_gazebo_demos/rviz/tf_bridge.rviz b/ros_ign_gazebo_demos/rviz/tf_bridge.rviz
new file mode 100644
index 00000000..76c42557
--- /dev/null
+++ b/ros_ign_gazebo_demos/rviz/tf_bridge.rviz
@@ -0,0 +1,163 @@
+Panels:
+ - Class: rviz_common/Displays
+ Help Height: 78
+ Name: Displays
+ Property Tree Widget:
+ Expanded:
+ - /Global Options1
+ - /Status1
+ - /TF1
+ - /TF1/Frames1
+ Splitter Ratio: 0.516339898109436
+ Tree Height: 549
+ - Class: rviz_common/Selection
+ Name: Selection
+ - Class: rviz_common/Tool Properties
+ Expanded:
+ - /2D Goal Pose1
+ - /Publish Point1
+ Name: Tool Properties
+ Splitter Ratio: 0.5886790156364441
+ - Class: rviz_common/Views
+ Expanded:
+ - /Current View1
+ Name: Views
+ Splitter Ratio: 0.5
+ - Class: rviz_common/Time
+ Experimental: false
+ Name: Time
+ SyncMode: 0
+ SyncSource: ""
+Visualization Manager:
+ Class: ""
+ Displays:
+ - Alpha: 0.5
+ Cell Size: 1
+ Class: rviz_default_plugins/Grid
+ Color: 160; 160; 164
+ Enabled: true
+ Line Style:
+ Line Width: 0.029999999329447746
+ 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_default_plugins/TF
+ Enabled: true
+ Frame Timeout: 15
+ Frames:
+ All Enabled: true
+ double_pendulum_with_base0:
+ Value: true
+ double_pendulum_with_base0/base:
+ Value: true
+ double_pendulum_with_base0/lower_link:
+ Value: true
+ double_pendulum_with_base0/upper_link:
+ Value: true
+ Marker Scale: 1
+ Name: TF
+ Show Arrows: true
+ Show Axes: true
+ Show Names: true
+ Tree:
+ double_pendulum_with_base0:
+ double_pendulum_with_base0/base:
+ {}
+ double_pendulum_with_base0/lower_link:
+ {}
+ double_pendulum_with_base0/upper_link:
+ {}
+ Update Interval: 0
+ Value: true
+ Enabled: true
+ Global Options:
+ Background Color: 48; 48; 48
+ Fixed Frame: double_pendulum_with_base0
+ Frame Rate: 30
+ Name: root
+ Tools:
+ - Class: rviz_default_plugins/Interact
+ Hide Inactive Objects: true
+ - Class: rviz_default_plugins/MoveCamera
+ - Class: rviz_default_plugins/Select
+ - Class: rviz_default_plugins/FocusCamera
+ - Class: rviz_default_plugins/Measure
+ Line color: 128; 128; 0
+ - Class: rviz_default_plugins/SetInitialPose
+ Covariance x: 0.25
+ Covariance y: 0.25
+ Covariance yaw: 0.06853891909122467
+ Topic:
+ Depth: 5
+ Durability Policy: Volatile
+ History Policy: Keep Last
+ Reliability Policy: Reliable
+ Value: /initialpose
+ - Class: rviz_default_plugins/SetGoal
+ Topic:
+ Depth: 5
+ Durability Policy: Volatile
+ History Policy: Keep Last
+ Reliability Policy: Reliable
+ Value: /goal_pose
+ - Class: rviz_default_plugins/PublishPoint
+ Single click: true
+ Topic:
+ Depth: 5
+ Durability Policy: Volatile
+ History Policy: Keep Last
+ Reliability Policy: Reliable
+ Value: /clicked_point
+ Transformation:
+ Current:
+ Class: rviz_default_plugins/TF
+ Value: true
+ Views:
+ Current:
+ Class: rviz_default_plugins/Orbit
+ Distance: 8.114859580993652
+ Enable Stereo Rendering:
+ Stereo Eye Separation: 0.05999999865889549
+ Stereo Focal Distance: 1
+ Swap Stereo Eyes: false
+ Value: false
+ Focal Point:
+ X: 0
+ Y: 0
+ Z: 0
+ Focal Shape Fixed Size: true
+ Focal Shape Size: 0.05000000074505806
+ Invert Z Axis: false
+ Name: Current View
+ Near Clip Distance: 0.009999999776482582
+ Pitch: 0.3453984260559082
+ Target Frame:
+ Value: Orbit (rviz)
+ Yaw: 3.2535715103149414
+ Saved: ~
+Window Geometry:
+ Displays:
+ collapsed: false
+ Height: 846
+ Hide Left Dock: false
+ Hide Right Dock: false
+ QMainWindow State: 000000ff00000000fd0000000400000000000002ff000002b0fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002b0000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002b0fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002b0000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e100000197000000030000066f0000003efc0100000002fb0000000800540069006d006501000000000000066f000002eb00fffffffb0000000800540069006d0065010000000000000450000000000000000000000255000002b000000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
+ Selection:
+ collapsed: false
+ Time:
+ collapsed: false
+ Tool Properties:
+ collapsed: false
+ Views:
+ collapsed: false
+ Width: 1647
+ X: 251
+ Y: 169