Wie man RViz2 [ERROR]: Could not load resource [....]: Unable to open file: "..." behebt
Problem
Beim Ausführen von ROS2s RViz2 mit einem benutzerdefinierten URDF-Modell aus einer Datei sehen Sie eine Fehlermeldung wie diese:
[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".Lösung
Das Problem hier ist, dass ein filename-Attribut nicht als Dateiname behandelt wird:
<mesh filename="./meshes/robot_arms/fr3/visual/link0.dae"/>Stattdessen wird es mit assimp_loader.getScene() unter Verwendung der OpenAssetImporter-Bibliothek geladen wie folgt:
const aiScene * scene = assimp_loader.getScene(resource_path);was Assimp::Importer::ReadFile() hier aufruft
was den folgenden Code enthält:
// 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;
}Es gibt viele verschiedene IO-Handler für Assimp, aber rviz2 verwendet ResourceIOSystem, was eine ROS/rviz2-spezifische Implementierung ist:
importer_->SetIOHandler(new ResourceIOSystem());Dies ist nur ein dünner Wrapper um einen resource_retriever::Retriever, der sich im ros/resource_retriever-Projekt befindet.
Die Implementierung des resource_retriever::Retriever befindet sich hier
Wir müssen nun Retriever::get betrachten, um zu sehen, wie Eingabe-Strings behandelt werden.
Im Allgemeinen wird diese Funktion jeden Eingabe-String an CURL weitergeben, das dann versucht, die URL oder Datei zu öffnen. Retriever::get wird jedoch package://-Schema-URLs unterschiedlich behandeln.
Dies sind im Wesentlichen ROS-spezifische URLs und diese werden am Ende in absolute file://-Schema-URLs umgewandelt, referenziert auf das package://-Verzeichnis.
Das Paketverzeichnis wird hier bestimmt
package_path = ament_index_cpp::get_package_share_directory(package);Diese Funktion stammt aus dem ament resource index-Projekt.
Bemerkenswerterweise wird dies nicht direkt auf das Paket-Root-Verzeichnis verweisen, sondern auf das share-Verzeichnis des Pakets
return get_package_prefix(package_name) + "/share/" + package_name;Wie man Dateien direkt einfügt
Diese Rückverfolgung zeigt uns, dass rviz2 nur URLs unterstützt und keine direkten Dateipfade.
Um Dateien direkt einzufügen, können Sie das file://-Schema verwenden, das nur mit absoluten URL-Pfaden funktioniert, da libcurl keine relativen file://-URLs unterstützt
Dateien aus dem Netzwerk laden
Da jede Nicht-package://-URL direkt an libcurl weitergegeben wird, können Sie auch Dateien aus dem Netzwerk laden, z.B. mit https:// oder ähnlichen URLs.