Skip to content

Commit

Permalink
Add URDFLoader (#269)
Browse files Browse the repository at this point in the history
  • Loading branch information
markaren authored Jun 26, 2024
1 parent 2523bea commit 14049af
Show file tree
Hide file tree
Showing 9 changed files with 675 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ however much remains to be done..
* Controls [Orbit, Fly, Drag]
* Water and Sky shaders
* Built-in text rendering and font loading [typeface.json, TTF]
* Loaders [Binary STL, OBJ/MTL, SVG]
* Loaders [Binary STL, OBJ/MTL, SVG, URDF]
* Basic Audio support using [miniaudio](https://miniaud.io/docs/manual/index.html)
* Generic model loader based on [Assimp](https://github.com/assimp/assimp)
* Easy integration with [Dear ImGui](https://github.com/ocornut/imgui)
Expand Down
1 change: 1 addition & 0 deletions examples/loaders/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ add_example(NAME "obj_loader" WEB WEB_EMBED
"../data/textures/uv_grid_opengl.jpg@data/textures/uv_grid_opengl.jpg"
)
add_example(NAME "assimp_loader" LINK_ASSIMP)
add_example(NAME "urdf_loader" LINK_ASSIMP LINK_IMGUI)

if (THREEPP_WITH_SVG)
add_example(NAME "svg_loader" LINK_IMGUI)
Expand Down
118 changes: 118 additions & 0 deletions examples/loaders/urdf_loader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@

#include <iostream>
#include <threepp/extras/imgui/ImguiContext.hpp>
#include <threepp/loaders/AssimpLoader.hpp>
#include <threepp/loaders/URDFLoader.hpp>
#include <threepp/threepp.hpp>

using namespace threepp;

int main(int argc, char** argv) {

if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <urdf file>" << std::endl;
return 1;
}

std::filesystem::path urdfPath = argv[1];
if (!exists(urdfPath)) {
std::cerr << "File not found: " << urdfPath << std::endl;
return 1;
}

Canvas canvas{"URDF loader", {{"aa", 4}}};
GLRenderer renderer(canvas.size());
renderer.setClearColor(Color::aliceblue);

auto scene = Scene::create();
auto camera = PerspectiveCamera::create(75, canvas.aspect(), 0.1f, 100);
camera->position.z = 1;

OrbitControls controls{*camera, canvas};

auto light = HemisphereLight::create(Color::aliceblue, Color::grey);
scene->add(light);

URDFLoader loader;
AssimpLoader assimpLoader;
auto robot = loader.load(assimpLoader, urdfPath);
robot->rotation.x = -math::PI / 2;
robot->showColliders(false);
scene->add(robot);

Box3 bb;
bb.setFromObject(*robot);

Vector3 size = bb.getSize();
camera->position.set(0, size.y * 1.5f, size.z * 3.f);
controls.update();

bool animate{false};
bool showColliders{false};
const auto info = robot->getArticulatedJointInfo();
std::vector<float> jointValues = robot->jointValuesWithConversionFromRadiansToDeg();

auto axis = AxesHelper::create(size.length() * 0.1f);
scene->add(axis);

std::vector<std::string> labels;
for (auto i = 0; i < robot->numDOF(); i++) {
labels.emplace_back("j" + std::to_string(i + 1));
}

ImguiFunctionalContext ui(canvas.windowPtr(), [&] {
ImGui::SetNextWindowPos({}, 0, {});
ImGui::SetNextWindowSize({230, 0}, 0);

ImGui::Begin("Settings");

ImGui::Checkbox("Animate", &animate);
if (ImGui::Checkbox("Show Colliders", &showColliders)) {
robot->showColliders(showColliders);
}

for (auto i = 0; i < robot->numDOF(); i++) {
const auto type = info[i].type;
const auto minmax = robot->getJointRange(i, true);
bool isRevolute = type == Robot::JointType::Revolute;
float min = minmax.first > (isRevolute ? -360.f : -1.f) ? minmax.first : (isRevolute ? -360.f : -1.f);
float max = minmax.second < (isRevolute ? 360.f : 1.f) ? minmax.second : (isRevolute ? 360.f : 1.f);
if (ImGui::SliderFloat(labels[i].c_str(), &jointValues[i], min, max)) {
robot->setJointValue(i, jointValues[i], isRevolute);
animate = false;
}
}

ImGui::End();
});

IOCapture capture{};
capture.preventMouseEvent = [] {
return ImGui::GetIO().WantCaptureMouse;
};
canvas.setIOCapture(&capture);

canvas.onWindowResize([&](WindowSize size) {
camera->aspect = size.aspect();
camera->updateProjectionMatrix();
renderer.setSize(size);
});

Clock clock;
canvas.animate([&]() {

if (animate) {
for (auto i = 0; i < robot->numDOF(); ++i) {
jointValues[i] = robot->getJointValue(i, true);
robot->setJointValue(i, std::sin(clock.getElapsedTime()) * 0.5f);
}
}

auto m = robot->computeEndEffectorTransform(jointValues, true);
axis->position.setFromMatrixPosition(m);
axis->quaternion.setFromRotationMatrix(m);

renderer.render(*scene, *camera);
ui.render();
});
}
5 changes: 3 additions & 2 deletions include/threepp/loaders/AssimpLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#ifndef THREEPP_ASSIMPLOADER_HPP
#define THREEPP_ASSIMPLOADER_HPP

#include "URDFLoader.hpp"
#include "threepp/loaders/TextureLoader.hpp"
#include "threepp/materials/MeshStandardMaterial.hpp"
#include "threepp/objects/Group.hpp"
Expand All @@ -18,10 +19,10 @@

namespace threepp {

class AssimpLoader {
class AssimpLoader: public Loader<Group> {

public:
std::shared_ptr<Group> load(const std::filesystem::path& path) {
std::shared_ptr<Group> load(const std::filesystem::path& path) override {

auto aiScene = importer_.ReadFile(path.string().c_str(), aiProcessPreset_TargetRealtime_Quality);

Expand Down
20 changes: 20 additions & 0 deletions include/threepp/loaders/Loader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

#ifndef THREEPP_LOADER_HPP
#define THREEPP_LOADER_HPP

#include <filesystem>
#include <memory>

namespace threepp {

template<class T>
class Loader {
public:
virtual std::shared_ptr<T> load(const std::filesystem::path& path) = 0;

virtual ~Loader() = default;
};

}// namespace threepp

#endif//THREEPP_LOADER_HPP
31 changes: 31 additions & 0 deletions include/threepp/loaders/URDFLoader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

#ifndef THREEPP_URDFLOADER_HPP
#define THREEPP_URDFLOADER_HPP

#include "threepp/loaders/Loader.hpp"
#include "threepp/objects/Robot.hpp"

#include <filesystem>
#include <memory>

namespace threepp {

class Group;

class URDFLoader {

public:
explicit URDFLoader();

std::shared_ptr<Robot> load(Loader<Group>& loader, const std::filesystem::path& path);

~URDFLoader();

private:
struct Impl;
std::unique_ptr<Impl> pimpl_;
};

}// namespace threepp

#endif//THREEPP_URDFLOADER_HPP
Loading

0 comments on commit 14049af

Please sign in to comment.