rviz_visual_tools: drawing shapes and meshes from a ROS 2 node
C++ API wrapper for displaying shapes and meshes in Rviz
At a glance
- What is it?
- rviz_visual_tools is a C++ wrapper that publishes visualization_msgs markers from a running ROS 2 node, so you can draw spheres, arrows, paths, planes, graphs and meshes in RViz without hand assembling marker messages. It is BSD-3-Clause licensed, and the keyboard and mouse stepping features that made it useful for debugging are marked NOT PORTED on the ROS 2 branch.
- Who is it for?
- Adopt rviz_visual_tools if you develop ROS 2 robotics code and want to see poses, paths and geometry inside RViz from the running node rather than from recorded logs. Do not adopt it expecting the stepping and GUI debugging features from the ROS 1 version, since the documentation marks the Rviz panel, the mouse based control and the keyboard based control as NOT PORTED.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 45 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A marker publishing layer instead of a visualization framework
rviz_visual_tools is described as a C++ API wrapper for displaying shapes and meshes in Rviz, via helper functions that publish markers, and the README calls it useful for displaying and debugging data.
The mechanism is narrower than the name might suggest, and the narrower scope is what makes it useful. It does not draw anything itself. It publishes messages on a visualization_msgs marker topic, and RViz renders them. So this is a convenience layer over the marker message format, taking care of the identifiers, the lifetime, the color and size constants, and the frame assumptions that make hand written marker code tedious and error prone.
The package list in the README shows what is actually in it. An Rviz Panel GUI to step through your code for debugging and testing. Rviz-based keyboard control for stepping through an application. Easy to use helper functions for visualizing in RViz fast. Basic geometric markers, plus more complex geometric shapes such as coordinate frames, framed boxes, planes, paths and graphs. The ability to quickly choose standard colors and sizes. Tools to ensure proper connection to Rviz before publishing visualizations. Shortcuts to convert between different types of points and poses, ROS msgs, Eigen and tf. Batch publishing capabilities to reduce over throttling ROS messages. A tf publishing helper class. And an interactive marker helper class.
The target audience is robotics developers debugging behaviour in RViz, and the comparison the README draws is with moveit_visual_tools, which builds on this class for more advanced robot visualization features.
Three lines of setup before you can draw anything
The initialization sequence is short, and the README walks through it as if you are using the helper functions within a class. Almost all of the functions assume you are publishing transforms in the world frame, whatever you call that, for example /odom.
First the include:
#include <rviz_visual_tools/rviz_visual_tools.hpp>Then a member variable on your class:
// For visualizing things in rviz
rviz_visual_tools::RvizVisualToolsPtr visual_tools_;Then the constructor call:
visual_tools_.reset(new rviz_visual_tools::RvizVisualTools("base_frame","/rviz_visual_markers", node));The two parameters are your robot's base frame name and the name you want to use for the corresponding Rviz marker ROS topic. The documentation is explicit that you change the first to the name of your robot's base frame and the second to whatever name you like for the marker topic, and the frame assumption matters because almost every helper function places its shape relative to the world frame.
In RViz itself you then create a new marker using the Add button at the bottom right and choose the marker topic to be the same topic you specified in the constructor. That last step is the one people miss, and the symptom is a node that publishes markers and an RViz window that shows nothing, because RViz is listening on a different topic than the one your code is using.
The package also includes tools to ensure proper connection to Rviz before publishing visualizations, which addresses the same class of problem from the other side, and the package includes a tf publishing helper class so that the frames your markers reference actually exist in the tf tree.
The trigger call is the part that trips everyone up
The example in the README creates a pose at xyz (0.1, 0.1, 0.1), rotates it 45 degrees along the Y axis, and publishes it as an arrow:
// Create pose
Eigen::Isometry3d pose;
pose = Eigen::AngleAxisd(M_PI/4, Eigen::Vector3d::UnitY()); // rotate along X axis by 45 degrees
pose.translation() = Eigen::Vector3d( 0.1, 0.1, 0.1 ); // translate x,y,z
// Publish arrow vector of pose
ROS_INFO_STREAM_NAMED("test","Publishing Arrow");
visual_tools_->publishArrow(pose, rviz_visual_tools::RED, rviz_visual_tools::LARGE);
// Don't forget to trigger the publisher!
visual_tools_->trigger();The last line is the whole design. All markers must be triggered after being published, by calling the trigger() function, and this is what allows batch publishing: you create several markers and call trigger once at the end, rather than publishing each one individually. The documentation says this greatly increases the speed of your application, and the package list repeats the point as batch publishing capabilities to reduce over throttling ROS messages.
You can also control the cadence explicitly with triggerEvery(NUM_MARKERS), so the publisher flushes every twenty markers rather than only when you say so. The two documented calls are trigger() and triggerEvery(20).
For a robot publishing a trajectory of a few hundred points, that difference is the difference between a usable visualization and an RViz window that cannot keep up. It is also the reason the trigger call appears in the example with a comment, since the natural instinct is to assume a publish call sends the message.
The shape of the call also shows the level of abstraction. The arrow is published with a color constant and a size constant, both named, so the code reads as intent rather than as marker message fields.
The stepping and GUI features are marked NOT PORTED
The README is unusually blunt about which parts of the project did not survive the ROS 2 migration, and this is the most important thing to know before you adopt it.
Under Rviz GUI Usage, the mouse based control is labelled NOT PORTED. That was the Rviz panel called RvizVisualToolsGui, used to step through your program. Under keyboard based control, also NOT PORTED, was the KeyTool in the top of the RViz window, with the key bindings n for next, c or a for continue, b for break and s for stop. The Joy message button mapping is documented as 1 for Next, 2 for Continue, 3 for Break and 4 for Stop, with the note that only Next is fully implemented.
So the interactive debugging half of the package, which is arguably the reason most people adopted it in the first place, is not available on the ROS 2 branch. The visualizer half is.
The remaining functionality is intact. The publishing functions are extensive: publishSphere, publishSpheres, publishArrow and publishXArrow, publishYArrow, publishZArrow, publishCuboid, publishCone, publishXYPlane, publishXZPlane, publishYZPlane, publishLine, publishPath, publishPolygon, publishBlock, publishWireframeCuboid, publishWireframeRectangle, publishAxis, publishAxisLabeled, publishCylinder, publishMesh, publishText and publishTest.
Around those sit the helper functions, split into three groups. Reset functions, deleteMarker with a namespace and id to clear a specific marker, and deleteAllMarkers to clear every current marker. Conversion functions, convertPose, convertPoint32ToPose, convertPoseToPoint, convertPoint, convertPoint32, convertFromXYZRPY and convertToXYZRPY. And convenience functions, generateRandomPose, generateEmptyPose, dRand, fRand, iRand, getCenterPoint and getVectorBetweenPoints.
There is also a frame locking feature, shown in the README with a demonstration image, which allows markers to be automatically updated as the base frame moves, so a marker attached to a moving robot does not have to be republished every cycle.
Installing on ROS 2, and running the demo
The binary install on Ubuntu and Debian is one command:
sudo apt-get install ros-${ROS_DISTRO}-rviz-visual-toolsThe ${ROS_DISTRO} variable is what makes the command work across distributions, since the package name is namespaced per ROS release.
For a source install, the documentation says to clone the repository into a catkin workspace and then use rosdep to pull the dependencies automatically:
rosdep install --from-paths src --ignore-src --rosdistro ${ROS_DISTRO}The --ignore-src flag skips the packages that are already in your workspace, and the --rosdistro flag tells rosdep which dependency set applies.
The demo takes two steps. First launch RViz:
ros2 launch rviz_visual_tools demo_rviz.launch.pyThen start the demo node:
ros2 run rviz_visual_tools rviz_visual_tools_demoThe first command opens RViz with the right configuration loaded, and the second generates the random shapes. Running the demo before writing your own code is worth the two minutes, because it shows you the marker topic that the launch file expects, and the README's point about the Add button and the topic name applies to the demo configuration as much as to your own project.
The default branch is ros2, and the package is built as a ROS 2 package, with a package.xml and a plugin_description.xml at the root alongside the CMakeLists.txt, the include and src directories, a launch directory, tests and icons. There is also a MIGRATION.md, which is where you would look for what changed between the ROS 1 and ROS 2 versions, and a Dockerfile used for testing that sets up a catkin workspace on an older ROS base image and builds with colcon.
The API documentation is Doxygen generated and hosted on docs.ros.org, though the link in the README points at the melodic documentation, which is the ROS 1 version. That is another sign of the migration being partial, and it means the online API reference you are linked to may describe functions whose ROS 2 names differ.
Where a marker wrapper stops being enough
The main limitation is the one the documentation states, and it is worth restating plainly: if your workflow is stepping through your code in RViz, this package on its ROS 2 branch does not do that. The panel and the key tool are marked NOT PORTED.
That changes what the tool is for. It becomes a drawing library rather than a debugging environment, and the workflow becomes: publish a marker, look at the result, adjust the code, publish again. That loop is still valuable, and for anything involving geometry, paths or frames it is much better than reading log output, but it is a different loop from the one the ROS 1 version supported.
The second limitation is scope. This package draws markers. It does not manage a scene, it does not persist state, and it does not give you a way to inspect what you drew other than by looking at it. The moveit_visual_tools project that builds on this class exists because advanced robot visualization needs more than markers, and the README points there for that reason.
The third is the frame assumption. Almost all the helper functions assume transforms are published in the world frame. If your robot publishes transforms in a different frame, or if you have several frames in play, you are responsible for converting, and the conversion helpers are point to point and pose to pose rather than a general transform tree utility. That is fine for simple cases and a source of subtle errors in complex ones, where a marker appears in the wrong place because the base frame reference was wrong rather than because the pose was wrong.
The alternatives differ in approach. Publishing visualization_msgs markers directly is more work but gives you exact control over every field and no dependency on this package. The moveit_visual_tools project adds a higher level scene and configuration model on top of this one, which is the right choice if you need interactive markers and configuration rather than just drawing. And RViz itself, without any wrapper, can display a marker published by any node, so the question is really whether you want the convenience of named shapes and colors or the control of raw messages.
On licence, this is BSD-3-Clause with a LICENSE file at the repository root, which is permissive and raises no obligation on a commercial robotics product. The project was developed by Dave Coleman at the Correll Robotics Lab, University of Colorado Boulder, with help from Andy McEvoy and many others, and the repository is not archived with the last push on 2026-09-08.
Editorial conclusion
Adopt rviz_visual_tools if you develop ROS 2 robotics code and want to see poses, paths and geometry inside RViz from the running node rather than from recorded logs. Do not adopt it expecting the stepping and GUI debugging features from the ROS 1 version, since the documentation marks the Rviz panel, the mouse based control and the keyboard based control as NOT PORTED. Verify first that your target is a ROS 2 distribution, since the default branch is ros2, that the marker topic you configure matches the one you add in RViz, and that you call trigger() after publishing, since markers are not sent until you do.
Frequently asked questions
What does rviz_visual_tools do?
It is a C++ API wrapper that publishes visualization_msgs markers from a ROS 2 node, providing helper functions for spheres, arrows, cuboids, cones, planes, paths, polygons, axes, cylinders, meshes, text and more, plus conversions between poses and points in ROS messages, Eigen and tf.
How do I install rviz_visual_tools on Ubuntu or Debian?
Use `sudo apt-get install ros-${ROS_DISTRO}-rviz-visual-tools`. To build from source, clone the repository into a catkin workspace and run `rosdep install --from-paths src --ignore-src --rosdistro ${ROS_DISTRO}` to fetch the dependencies.
Why are my markers not showing up in RViz?
Markers are not sent until you call trigger() after publishing them, and the marker topic in RViz has to match the topic you passed to the RvizVisualTools constructor. The README also notes that the package includes tools to ensure proper connection to RViz before publishing.
Can I step through my code in RViz with rviz_visual_tools on ROS 2?
Not currently. The Rviz panel, the mouse based control and the keyboard based control are all marked NOT PORTED in the documentation, and of the Joy message buttons only Next is fully implemented. The marker publishing half of the package works on the ROS 2 branch.
How do I publish markers in batches to avoid throttling?
All markers must be triggered after being published by calling trigger(), which lets you create several markers and trigger once at the end. You can also set the cadence explicitly with triggerEvery(NUM_MARKERS), for example triggerEvery(20).
What license is rviz_visual_tools released under?
BSD-3-Clause, with the LICENSE file at the repository root. The project was developed by Dave Coleman at the Correll Robotics Lab, University of Colorado Boulder.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/picknikrobotics-rviz-visual-tools)Was this useful?