如何修复 RViz2 [ERROR]: Could not load resource [....]: Unable to open file: "..."
问题
使用文件中的自定义 URDF 模型运行 ROS2 的 RViz2 时,你看到如下错误消息:
[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".解决方案
这里的问题是 filename 属性不被当作文件名处理:
<mesh filename="./meshes/robot_arms/fr3/visual/link0.dae"/>相反,它使用 assimp_loader.getScene() 通过 OpenAssetImporter 库加载,如下所示:
const aiScene * scene = assimp_loader.getScene(resource_path);它在这里调用 Assimp::Importer::ReadFile()
其中包含以下代码:
// 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;
}Assimp 有许多不同的 IO 处理程序,但 rviz2 使用 ResourceIOSystem,这是一个 ROS/rviz2 特定的实现:
importer_->SetIOHandler(new ResourceIOSystem());这只是 resource_retriever::Retriever 的一个薄包装器,位于 ros/resource_retriever 项目中。
resource_retriever::Retriever 的实现在这里
我们现在需要查看 Retriever::get 来了解输入字符串如何被处理。
通常此函数会将任何输入字符串传递给 CURL,CURL 随后会尝试打开 URL 或文件。但是,Retriever::get 会以不同方式处理 package:// 方案的 URL。
这些本质上是 ROS 特定的 URL,最终将转换为相对于 package:// 目录的绝对 file:// 方案 URL。
包目录在这里确定
package_path = ament_index_cpp::get_package_share_directory(package);此函数来自 ament resource index 项目。
值得注意的是,这不会直接引用包根目录,而是引用包的 share 目录
return get_package_prefix(package_name) + "/share/" + package_name;如何直接插入文件
此追踪表明 rviz2 只支持 URL 而不支持直接文件路径。
要直接插入文件,你可以使用 file:// 方案,它只适用于绝对 URL 路径,因为 libcurl 不支持相对 file:// URL
从网络加载文件
由于每个非 package:// URL 都直接传递给 libcurl,你还可以从网络加载文件,例如使用 https:// 或类似 URL。