How to fix RViz2 [ERROR]: Could not load resource [....]: Unable to open file: "..."
Problem
When running ROS2’s RViz2 with a custom URDF model from file, you see an error message like this:
[ERROR] [1736351067.730994512] [rviz2]: Could not load resource [./meshes/robot_arms/fr3/visual/link0.dae]: Unable to open file "./meshes/robot_arms/fr3/visual/link0.dae".Solution
The issue here is that a filename attribute is not treated as a filename:
<mesh filename="./meshes/robot_arms/fr3/visual/link0.dae"/>Instead, it’s loaded using assimp_loader.getScene() using the OpenAssetImporter library like this:
const aiScene * scene = assimp_loader.getScene(resource_path);which calls Assimp::Importer::ReadFile() here
which contains the following code:
// First check if the file is accessible at all
if( !pimpl->mIOHandler->Exists( pFile)) {
pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
ASSIMP_LOG_ERROR(pimpl->mErrorString);
return nullptr;
}There are many different IO handlers for Assimp, but rviz2 uses ResourceIOSystem which is a ROS/rviz2-specific implementation:
importer_->SetIOHandler(new ResourceIOSystem());This is just a thin wrapper around a resource_retriever::Retriever which is located in the ros/resource_retriever project.
The implementation of the resource_retriever::Retriever is here
We now need to look at Retriever::get to see how input strings are handled.
Generally this function will pass any input string to CURL, which will then try to open the URL or file. However, Retriever::get will handle package://-schemes URLs differently.
These are essentially ROS-specific URLs and these will, in the end, be converted to absolute file://-schemed URLs, referenced to the package:// directory.
The package directory is determined here
package_path = ament_index_cpp::get_package_share_directory(package);This function is from the ament resource index project.
Notably, this will not refer to the package root directly, but to the share directory of the package
return get_package_prefix(package_name) + "/share/" + package_name;How to insert files directly
This tracedown shows us that rviz2 will only support URLs and not direct file paths.
To insert files directly, you can use the file://-scheme which only work with absolute URL paths since libcurl doesn’t support relativ file:// URLs
Loading files from the network
Since every non-package:// URL is passed directly to libcurl, you can also load files from the network such as using https:// or similar URLs.