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:

rviz2-error.txt
[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-example.xml
<mesh filename="./meshes/robot_arms/fr3/visual/link0.dae"/>

Stattdessen wird es mit assimp_loader.getScene() unter Verwendung der OpenAssetImporter-Bibliothek geladen wie folgt:

assimp-getscene.cpp
const aiScene * scene = assimp_loader.getScene(resource_path);

was Assimp::Importer::ReadFile() hier aufruft

was den folgenden Code enthält:

assimp-importer-check.cpp
// 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:

resourceio-setiohandler.cpp
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

retriever-get.cpp
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

get_package_share_directory.cpp
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.


Check out similar posts by category: ROS