Add [SdfLib](https://github.com/UPC-ViRVIG/SdfLib) plugin to first-party SDFs.
The following dependencies are disabled with a cmake patch file. - Enoki - OpenMP - Assimp - FCPW PiperOrigin-RevId: 565352386 Change-Id: Icff9de68408e0afa2032bb83b24491fc4e41d181
This commit is contained in:
committed by
Copybara-Service
parent
de5c3b1a09
commit
1afd98ec4b
@@ -58,6 +58,11 @@ set(MUJOCO_DEP_VERSION_benchmark
|
||||
CACHE STRING "Version of `benchmark` to be fetched."
|
||||
)
|
||||
|
||||
set(MUJOCO_DEP_VERSION_sdflib
|
||||
492847fa81e46653114da48e8886730ccefed377
|
||||
CACHE STRING "Version of `openVDB` to be fetched."
|
||||
)
|
||||
|
||||
mark_as_advanced(MUJOCO_DEP_VERSION_lodepng)
|
||||
mark_as_advanced(MUJOCO_DEP_VERSION_MarchingCubeCpp)
|
||||
mark_as_advanced(MUJOCO_DEP_VERSION_tinyxml2)
|
||||
@@ -68,6 +73,7 @@ mark_as_advanced(MUJOCO_DEP_VERSION_Eigen3)
|
||||
mark_as_advanced(MUJOCO_DEP_VERSION_abseil)
|
||||
mark_as_advanced(MUJOCO_DEP_VERSION_gtest)
|
||||
mark_as_advanced(MUJOCO_DEP_VERSION_benchmark)
|
||||
mark_as_advanced(MUJOCO_DEP_VERSION_sdflib)
|
||||
|
||||
include(FetchContent)
|
||||
include(FindOrFetch)
|
||||
@@ -178,6 +184,26 @@ findorfetch(
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
findorfetch(
|
||||
USE_SYSTEM_PACKAGE
|
||||
OFF
|
||||
PACKAGE_NAME
|
||||
sdflib
|
||||
LIBRARY_NAME
|
||||
sdflib
|
||||
GIT_REPO
|
||||
https://github.com/UPC-ViRVIG/SdfLib.git
|
||||
GIT_TAG
|
||||
${MUJOCO_DEP_VERSION_sdflib}
|
||||
PATCH_COMMAND
|
||||
git apply --reject --whitespace=fix ${CMAKE_SOURCE_DIR}/cmake/sdflib-optional-dependencies.patch
|
||||
TARGETS
|
||||
SdfLib
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
target_compile_options(SdfLib PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS})
|
||||
target_link_options(SdfLib PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS})
|
||||
|
||||
set(ENABLE_DOUBLE_PRECISION ON)
|
||||
set(CCD_HIDE_ALL_SYMBOLS ON)
|
||||
findorfetch(
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
The spot assets were taken from https://www.cs.cmu.edu/~kmcrane/Projects/ModelRepository/ and are
|
||||
released under the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication license.
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
@@ -0,0 +1,64 @@
|
||||
<mujoco>
|
||||
<compiler texturedir="asset"/>
|
||||
|
||||
<extension>
|
||||
<plugin plugin="mujoco.sdf.torus">
|
||||
<instance name="torus">
|
||||
<config key="radius1" value="0.15"/>
|
||||
<config key="radius2" value="0.05"/>
|
||||
</instance>
|
||||
</plugin>
|
||||
<plugin plugin="mujoco.sdf.sdflib">
|
||||
<instance name="sdf">
|
||||
<config key="aabb" value="0"/>
|
||||
</instance>
|
||||
</plugin>
|
||||
</extension>
|
||||
|
||||
<asset>
|
||||
<texture name="texspot" type="2d" file="spot.png"/>
|
||||
<material name="matspot" texture="texspot"/>
|
||||
<mesh name="spot" file="asset/spot.obj">
|
||||
<plugin instance="sdf"/>
|
||||
</mesh>
|
||||
<mesh name="torus">
|
||||
<plugin instance="torus"/>
|
||||
</mesh>
|
||||
</asset>
|
||||
|
||||
<option sdf_iterations="20" sdf_initpoints="40"/>
|
||||
|
||||
<visual>
|
||||
<map force="1000"/>
|
||||
</visual>
|
||||
|
||||
<default>
|
||||
<geom solref="0.01 1" solimp=".95 .99 .0001" friction="0.5"/>
|
||||
</default>
|
||||
|
||||
<statistic meansize="0.2"/>
|
||||
|
||||
<include file="scene.xml"/>
|
||||
|
||||
<worldbody>
|
||||
<body pos="0.1 .25 5.7">
|
||||
<freejoint/>
|
||||
<geom type="sdf" mesh="torus" rgba=".2 .8 .2 1">
|
||||
<plugin instance="torus"/>
|
||||
</geom>
|
||||
</body>
|
||||
<body euler="90 0 0" pos="0 0 .7">
|
||||
<geom type="sdf" name="cow1" mesh="spot" material="matspot">
|
||||
<plugin instance="sdf"/>
|
||||
</geom>
|
||||
</body>
|
||||
<body pos="0.05 .25 2.2">
|
||||
<freejoint/>
|
||||
<geom type="sdf" name="cow2" mesh="spot" material="matspot">
|
||||
<plugin instance="sdf"/>
|
||||
</geom>
|
||||
</body>
|
||||
<light name="left" pos="0 0 1"/>
|
||||
<light name="right" pos="1 0 1"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
@@ -28,6 +28,8 @@ set(MUJOCO_SDF_SRCS
|
||||
register.cc
|
||||
nut.cc
|
||||
nut.h
|
||||
sdflib.cc
|
||||
sdflib.h
|
||||
torus.cc
|
||||
torus.h
|
||||
)
|
||||
@@ -35,7 +37,7 @@ set(MUJOCO_SDF_SRCS
|
||||
add_library(sdf SHARED)
|
||||
target_sources(sdf PRIVATE ${MUJOCO_SDF_SRCS})
|
||||
target_include_directories(sdf PRIVATE ${MUJOCO_SDF_INCLUDE})
|
||||
target_link_libraries(sdf PRIVATE mujoco)
|
||||
target_link_libraries(sdf PRIVATE mujoco SdfLib)
|
||||
target_compile_options(
|
||||
sdf
|
||||
PRIVATE ${AVX_COMPILE_OPTIONS}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "gear.h"
|
||||
#include "nut.h"
|
||||
#include "torus.h"
|
||||
#include "sdflib.h"
|
||||
|
||||
namespace mujoco::plugin::sdf {
|
||||
|
||||
@@ -26,6 +27,7 @@ mjPLUGIN_LIB_INIT {
|
||||
Gear::RegisterPlugin();
|
||||
Nut::RegisterPlugin();
|
||||
Torus::RegisterPlugin();
|
||||
SdfLib::RegisterPlugin();
|
||||
}
|
||||
|
||||
} // namespace mujoco::plugin::sdf
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
// Copyright 2022 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <SdfLib/utils/Mesh.h>
|
||||
#include <SdfLib/OctreeSdf.h>
|
||||
#include <mujoco/mjplugin.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "sdf.h"
|
||||
#include "sdflib.h"
|
||||
|
||||
namespace mujoco::plugin::sdf {
|
||||
namespace {
|
||||
|
||||
inline unsigned int* MakeNonConstUnsigned(const int* ptr) {
|
||||
return reinterpret_cast<unsigned int*>(const_cast<int*>(ptr));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// factory function
|
||||
std::optional<SdfLib> SdfLib::Create(const mjModel* m, mjData* d,
|
||||
int instance) {
|
||||
int geomid = 0;
|
||||
for (int i = 0; i < m->ngeom; ++i) {
|
||||
if (m->geom_plugin[i] == instance) {
|
||||
geomid = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int meshid = m->geom_dataid[geomid];
|
||||
int nvert = m->mesh_vertnum[meshid];
|
||||
int nface = m->mesh_facenum[meshid];
|
||||
int* indices = m->mesh_face + 3*m->mesh_faceadr[meshid];
|
||||
float* verts = m->mesh_vert + 3*m->mesh_vertadr[meshid];
|
||||
std::vector<glm::vec3> vertices(nvert);
|
||||
for (int i = 0; i < nvert; i++) {
|
||||
mjtNum vert[3] = {verts[3*i+0], verts[3*i+1], verts[3*i+2]};
|
||||
mju_rotVecQuat(vert, vert, m->mesh_quat + 4*meshid);
|
||||
mju_addTo3(vert, m->mesh_pos + 3*meshid);
|
||||
vertices[i].x = vert[0];
|
||||
vertices[i].y = vert[1];
|
||||
vertices[i].z = vert[2];
|
||||
}
|
||||
sdflib::Mesh mesh(vertices.data(), nvert,
|
||||
MakeNonConstUnsigned(indices), 3*nface);
|
||||
mesh.computeBoundingBox();
|
||||
return SdfLib(std::move(mesh));
|
||||
}
|
||||
|
||||
// plugin constructor
|
||||
SdfLib::SdfLib(sdflib::Mesh&& mesh) {
|
||||
sdf_func_ =
|
||||
sdflib::OctreeSdf(mesh, mesh.getBoundingBox(), 8, 3, 1e-3,
|
||||
sdflib::OctreeSdf::InitAlgorithm::CONTINUITY, 1);
|
||||
}
|
||||
|
||||
// plugin computation
|
||||
void SdfLib::Compute(const mjModel* m, mjData* d, int instance) {
|
||||
visualizer_.Next();
|
||||
}
|
||||
|
||||
// plugin reset
|
||||
void SdfLib::Reset() {
|
||||
visualizer_.Reset();
|
||||
}
|
||||
|
||||
// plugin visualization
|
||||
void SdfLib::Visualize(const mjModel* m, mjData* d, const mjvOption* opt,
|
||||
mjvScene* scn, int instance) {
|
||||
visualizer_.Visualize(m, d, opt, scn, instance);
|
||||
}
|
||||
|
||||
// sdf
|
||||
mjtNum SdfLib::Distance(const mjtNum p[3]) const {
|
||||
glm::vec3 point(p[0], p[1], p[2]);
|
||||
return sdf_func_.getDistance(point);
|
||||
}
|
||||
|
||||
// gradient of sdf
|
||||
void SdfLib::Gradient(mjtNum grad[3], const mjtNum point[3]) const {
|
||||
glm::vec3 gradient;
|
||||
glm::vec3 p(point[0], point[1], point[2]);
|
||||
sdf_func_.getDistance(p, gradient);
|
||||
grad[0] = gradient[0];
|
||||
grad[1] = gradient[1];
|
||||
grad[2] = gradient[2];
|
||||
}
|
||||
|
||||
// plugin registration
|
||||
void SdfLib::RegisterPlugin() {
|
||||
mjpPlugin plugin;
|
||||
mjp_defaultPlugin(&plugin);
|
||||
|
||||
plugin.name = "mujoco.sdf.sdflib";
|
||||
plugin.capabilityflags |= mjPLUGIN_SDF;
|
||||
|
||||
const char* attributes[] = {"aabb"};
|
||||
plugin.nattribute = sizeof(attributes) / sizeof(attributes[0]);
|
||||
plugin.attributes = attributes;
|
||||
plugin.nstate = +[](const mjModel* m, int instance) { return 0; };
|
||||
|
||||
plugin.init = +[](const mjModel* m, mjData* d, int instance) {
|
||||
auto sdf_or_null = SdfLib::Create(m, d, instance);
|
||||
if (!sdf_or_null.has_value()) {
|
||||
return -1;
|
||||
}
|
||||
d->plugin_data[instance] = reinterpret_cast<uintptr_t>(
|
||||
new SdfLib(std::move(*sdf_or_null)));
|
||||
return 0;
|
||||
};
|
||||
plugin.destroy = +[](mjData* d, int instance) {
|
||||
delete reinterpret_cast<SdfLib*>(d->plugin_data[instance]);
|
||||
d->plugin_data[instance] = 0;
|
||||
};
|
||||
plugin.reset = +[](const mjModel* m, double* plugin_state, void* plugin_data,
|
||||
int instance) {
|
||||
auto sdf = reinterpret_cast<SdfLib*>(plugin_data);
|
||||
sdf->Reset();
|
||||
};
|
||||
plugin.visualize = +[](const mjModel* m, mjData* d, const mjvOption* opt,
|
||||
mjvScene* scn, int instance) {
|
||||
auto* sdf = reinterpret_cast<SdfLib*>(d->plugin_data[instance]);
|
||||
sdf->Visualize(m, d, opt, scn, instance);
|
||||
};
|
||||
plugin.compute =
|
||||
+[](const mjModel* m, mjData* d, int instance, int capability_bit) {
|
||||
auto* sdf = reinterpret_cast<SdfLib*>(d->plugin_data[instance]);
|
||||
sdf->Compute(m, d, instance);
|
||||
};
|
||||
plugin.sdf_distance =
|
||||
+[](const mjtNum point[3], const mjData* d, int instance) {
|
||||
auto* sdf = reinterpret_cast<SdfLib*>(d->plugin_data[instance]);
|
||||
sdf->visualizer_.AddPoint(point);
|
||||
return sdf->Distance(point);
|
||||
};
|
||||
plugin.sdf_gradient = +[](mjtNum gradient[3], const mjtNum point[3],
|
||||
const mjData* d, int instance) {
|
||||
auto* sdf = reinterpret_cast<SdfLib*>(d->plugin_data[instance]);
|
||||
sdf->Gradient(gradient, point);
|
||||
};
|
||||
|
||||
mjp_registerPlugin(&plugin);
|
||||
}
|
||||
|
||||
} // namespace mujoco::plugin::sdf
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2022 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MUJOCO_PLUGIN_SDF_SDFLIB_H_
|
||||
#define MUJOCO_PLUGIN_SDF_SDFLIB_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <SdfLib/utils/Mesh.h>
|
||||
#include <SdfLib/OctreeSdf.h>
|
||||
#include <mujoco/mjdata.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mjtnum.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include "sdf.h"
|
||||
|
||||
namespace mujoco::plugin::sdf {
|
||||
class SdfLib {
|
||||
public:
|
||||
// Creates a new SdfLib instance or returns null on failure.
|
||||
static std::optional<SdfLib> Create(const mjModel* m, mjData* d,
|
||||
int instance);
|
||||
SdfLib(SdfLib&&) = default;
|
||||
~SdfLib() = default;
|
||||
|
||||
void Reset();
|
||||
void Visualize(const mjModel* m, mjData* d, const mjvOption* opt,
|
||||
mjvScene* scn, int instance);
|
||||
void Compute(const mjModel* m, mjData* d, int instance);
|
||||
mjtNum Distance(const mjtNum point[3]) const;
|
||||
void Gradient(mjtNum grad[3], const mjtNum point[3]) const;
|
||||
|
||||
static void RegisterPlugin();
|
||||
|
||||
private:
|
||||
SdfLib(sdflib::Mesh&& mesh);
|
||||
SdfVisualizer visualizer_;
|
||||
sdflib::OctreeSdf sdf_func_;
|
||||
};
|
||||
|
||||
} // namespace mujoco::plugin::sdf
|
||||
|
||||
#endif // MUJOCO_PLUGIN_SDF_SDFLIB_H_
|
||||
+2
-1
@@ -437,7 +437,8 @@ __attribute__((used, visibility("default"))) extern "C" void _mj_rosettaError(co
|
||||
#endif
|
||||
|
||||
// run event loop
|
||||
int main(int argc, const char** argv) {
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// display an error if running on macOS under Rosetta 2
|
||||
#if defined(__APPLE__) && defined(__AVX__)
|
||||
if (rosetta_error_msg) {
|
||||
|
||||
@@ -367,7 +367,9 @@ static mjtNum stepGradient(mjtNum x[3], const mjModel* m, const mjSDF* s,
|
||||
mjc_gradient(m, d, s, grad, x);
|
||||
|
||||
// sanity check
|
||||
if (isnan(grad[0]) || isnan(grad[1]) || isnan(grad[2])) {
|
||||
if (isnan(grad[0]) || grad[0]>mjMAXVAL || grad[0]<-mjMAXVAL ||
|
||||
isnan(grad[1]) || grad[1]>mjMAXVAL || grad[1]<-mjMAXVAL ||
|
||||
isnan(grad[2]) || grad[2]>mjMAXVAL || grad[2]<-mjMAXVAL) {
|
||||
return mjMAXVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -774,6 +774,9 @@ mjtNum ray_sdf(const mjModel* m, const mjData* d, int g,
|
||||
if (distance < 1e-8) {
|
||||
return distance_total;
|
||||
}
|
||||
if (distance > 1e6) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reset counter
|
||||
|
||||
@@ -394,7 +394,7 @@ void mjCMesh::Compile(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// create using marching cubes
|
||||
if (is_plugin) {
|
||||
else if (is_plugin) {
|
||||
LoadSDF();
|
||||
}
|
||||
|
||||
|
||||
@@ -669,6 +669,8 @@ std::string mjuu_extToContentType(std::string_view filename) {
|
||||
return "model/stl";
|
||||
} else if (!strcasecmp(ext.c_str(), ".obj")) {
|
||||
return "model/obj";
|
||||
} else if (!strcasecmp(ext.c_str(), ".ply")) {
|
||||
return "model/ply";
|
||||
} else if (!strcasecmp(ext.c_str(), ".msh")) {
|
||||
return "model/vnd.mujoco.msh";
|
||||
} else if (!strcasecmp(ext.c_str(), ".png")) {
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace {
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::NotNull;
|
||||
|
||||
constexpr int kNumTruePlugins = 8;
|
||||
constexpr int kNumTruePlugins = 9;
|
||||
constexpr int kNumFakePlugins = 30;
|
||||
constexpr int kNumTestPlugins = 3;
|
||||
|
||||
|
||||
@@ -1063,7 +1063,8 @@ TEST_F(PluginTest, WriteReadCompare) {
|
||||
|
||||
// if file is meant to fail, skip it
|
||||
if (absl::StrContains(p.path().string(), "malformed_") ||
|
||||
absl::StrContains(p.path().string(), "touch_grid")) {
|
||||
absl::StrContains(p.path().string(), "touch_grid") ||
|
||||
absl::StrContains(p.path().string(), "cow")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user