From 7f72f2f69c8f3d84f35a248ef1cdf9ef4fdaead7 Mon Sep 17 00:00:00 2001 From: amillane Date: Thu, 6 Apr 2023 10:22:00 +0200 Subject: [PATCH] Release v0.0.4. --- .gitignore | 2 + Jenkinsfile | 14 +- README.md | 122 +- docs/conf.py | 23 +- docs/images/3dmatch.gif | Bin 0 -> 3341785 bytes docs/images/redwood_apartment.png | Bin 0 -> 1272270 bytes docs/images/replica_office0.png | Bin 0 -> 1053078 bytes docs/pages/technical.md | 2 +- docs/pages/tutorial_library_interface.md | 142 + docs/pages/tutorial_public_datasets.md | 61 + .../__init__.py => docs/root.md | 0 docs/root.rst | 8 - docs/rst/examples/core_example.rst | 63 - docs/rst/examples/index.rst | 9 - docs/rst/examples/ros_example.rst | 86 - docs/rst/index.rst | 30 - docs/rst/installation/core.rst | 119 - docs/rst/installation/index.rst | 12 - docs/rst/installation/ros.rst | 165 - docs/rst/integrators.rst | 21 - docs/rst/map.rst | 61 - docs/rst/mapper.rst | 31 - docs/rst/rays.rst | 10 - nvblox/CMakeLists.txt | 96 +- .../__init__.py => evaluation/COLCON_IGNORE} | 0 nvblox/evaluation/README.md | 5 + .../nvblox_evaluation}/__init__.py | 0 .../compare_branch_timings}/.gitignore | 0 .../compare_branch_timings/README.md | 10 + .../compare_branch_timings}/__init__.py | 0 .../compare_branch_timings.py} | 11 +- .../helpers/__init__.py | 0 .../helpers/plot_timing_comparison.py} | 2 +- .../helpers/run_threedmatch.py} | 0 .../evaluation_utils/__init__.py | 0 .../evaluation_utils/esdf_evaluation.py | 2 +- .../evaluation_utils/parse_nvblox_timing.py} | 0 .../evaluation_utils/quad_mesh.py | 0 .../evaluation_utils/surface_evaluation.py | 0 .../evaluation_utils/voxel_grid.py | 0 .../.gitignore | 1 + .../README.md | 0 .../__init__.py | 0 .../replica.py | 2 +- .../replica_esdf_evaluation.py | 6 +- .../replica_reconstruction.py | 4 +- .../replica_surface_evaluation.py | 4 +- nvblox/evaluation/requirements.txt | 7 + nvblox/evaluation/setup.py | 17 + nvblox/examples/src/esdf_query.cu | 16 +- nvblox/examples/src/load_map_and_mesh.cpp | 4 +- .../include/nvblox/datasets/3dmatch.h | 14 +- .../include/nvblox/datasets/data_loader.h | 14 +- .../include/nvblox/datasets/image_loader.h | 10 +- .../include/nvblox/datasets/redwood.h | 10 + .../include/nvblox/datasets/replica.h | 13 +- .../include/nvblox/executables/fuser.h | 39 +- nvblox/executables/src/datasets/3dmatch.cpp | 23 +- .../executables/src/datasets/image_loader.cpp | 3 +- nvblox/executables/src/datasets/redwood.cpp | 19 +- nvblox/executables/src/datasets/replica.cpp | 35 +- nvblox/executables/src/fuse_3dmatch.cpp | 5 +- nvblox/executables/src/fuse_redwood.cpp | 8 +- nvblox/executables/src/fuse_replica.cpp | 8 +- nvblox/executables/src/fuser.cpp | 259 +- nvblox/experiments/.gitignore | 1 - nvblox/experiments/CMakeLists.txt | 47 +- nvblox/experiments/README.md | 2 + .../compare_branches/CMakeLists.txt | 3 - .../isolate_tsdf_block_update/CMakeLists.txt | 2 - .../isolate_tsdf_block_update/main.cpp | 133 - .../layer_cake_interface/CMakeLists.txt | 25 - .../include/nvblox/experiments/cake_common.h | 32 - .../include/nvblox/experiments/cake_dynamic.h | 61 - .../include/nvblox/experiments/cake_static.h | 47 - .../nvblox/experiments/cake_type_erasure.h | 95 - .../experiments/impl/cake_common_impl.h | 63 - .../experiments/impl/cake_dynamic_impl.h | 73 - .../experiments/impl/cake_static_impl.h | 52 - .../nvblox/experiments/impl/load_impl.h | 60 - .../include/nvblox/experiments/load.h | 36 - .../nvblox/experiments/user_defined_block.h | 49 - .../layer_cake_interface/main_dynamic.cpp | 95 - .../layer_cake_interface/main_static.cpp | 62 - .../main_type_erasure.cpp | 43 - .../src/cuda/user_defined_block.cu | 34 - .../ratio_of_freespace/CMakeLists.txt | 2 - .../experiments/ratio_of_freespace/main.cpp | 138 - .../ratio_of_freespace/run_experiment.py | 122 - .../realistic_timings/CMakeLists.txt | 4 - .../realistic_timings/compare_platforms.py | 88 - .../realistic_timings/gather_timings.py | 85 - .../realistic_timings/plot_timings.py | 133 - .../stream_compaction/CMakeLists.txt | 11 - .../nvblox/experiments/cached_allocator.h | 40 - .../nvblox/experiments/stream_compaction.h | 37 - .../stream_compaction/lib/cached_allocator.cu | 64 - .../lib/stream_compaction.cu | 53 - .../experiments/stream_compaction/main.cpp | 106 - .../experiments/stream_compaction/plot.py | 72 - .../experiments/stream_compaction/run.py | 43 - .../CMakeLists.txt | 2 - .../main.cpp | 57 - .../threaded_image_loading/CMakeLists.txt | 4 - .../threaded_image_loading/main.cpp | 79 - .../threaded_image_loading/plot_comparison.py | 70 - .../experiments/threaded_image_loading/run.py | 87 - .../unified_vs_device_memory/CMakeLists.txt | 4 - .../analyze_results.py | 73 - .../unified_vs_device_memory/main.cpp | 78 - .../unified_vs_device_memory/run.py | 75 - .../experiments/vector_copies/CMakeLists.txt | 8 - .../experiments/vector_copies/main.cpp | 55 - .../experiments/vector_copies/plot_timings.py | 75 - .../vector_copies/vector_copies.cu | 155 - .../experiments/vector_copies/vector_copies.h | 18 - .../experimental_integrator_input_frames.cuh | 91 - ...experimental_projective_tsdf_integrators.h | 63 - nvblox/experiments/python/MANIFEST.in | 14 - nvblox/experiments/python/README.md | 2 - .../python/nvblox_experiments/timing.py | 48 - nvblox/experiments/python/requirements.txt | 1 - nvblox/experiments/python/setup.py | 17 - .../integrators/cuda/depth_frame_texture.cu | 70 - .../experimental_integrator_input_frames.cu | 102 - ...xperimental_projective_tsdf_integrators.cu | 344 - nvblox/experiments/src/test_bench.cpp | 52 + .../include/nvblox/experiments/.gitkeep | 0 nvblox/include/nvblox/core/color.h | 2 +- nvblox/include/nvblox/core/cuda/image_cuda.h | 49 - nvblox/include/nvblox/core/image.h | 164 - nvblox/include/nvblox/core/impl/image_impl.h | 138 - nvblox/include/nvblox/core/indexing.h | 2 +- .../core/{ => internal}/cuda/atomic_float.cuh | 3 +- .../cuda/impl/atomic_float_impl.cuh | 10 + .../error_check.h} | 2 + .../core/{ => internal}/impl/indexing_impl.h | 4 +- .../{ => internal}/impl/unified_ptr_impl.h | 21 +- .../{ => internal}/impl/unified_vector_impl.h | 4 +- .../impl/variadic_template_tools_impl.h | 0 .../{cuda/warmup.h => internal/warmup_cuda.h} | 2 +- nvblox/include/nvblox/core/iterator.h | 4 +- .../nvblox/core/log_odds.h} | 26 +- nvblox/include/nvblox/core/traits.h | 2 +- nvblox/include/nvblox/core/types.h | 16 +- nvblox/include/nvblox/core/unified_ptr.h | 17 +- nvblox/include/nvblox/core/unified_vector.h | 4 +- .../nvblox/core/variadic_template_tools.h | 4 +- .../{core => geometry}/bounding_boxes.h | 6 +- .../{core => geometry}/bounding_spheres.h | 2 +- .../internal}/impl/bounding_boxes_impl.h | 2 +- .../include/nvblox/gpu_hash/gpu_layer_view.h | 4 +- .../cuda/gpu_hash_interface.cuh | 4 +- .../{ => internal}/cuda/gpu_indexing.cuh | 6 +- .../gpu_hash/{ => internal}/cuda/gpu_set.cuh | 0 .../cuda/impl/gpu_hash_interface_impl.cuh | 0 .../cuda/impl/gpu_layer_view_impl.cuh | 9 +- .../nvblox/integrators/esdf_integrator.h | 201 +- .../cuda/impl/projective_integrator_impl.cuh} | 229 +- .../cuda/projective_integrators_common.cuh | 6 +- .../impl/projective_integrator_impl.h | 87 + .../internal/impl/weighting_function_impl.h | 98 + .../integrators/internal/integrators_common.h | 4 +- .../internal/projective_integrator.h | 169 + .../integrators/occupancy_decay_integrator.h | 87 + .../integrators/projective_color_integrator.h | 88 +- .../integrators/projective_integrator_base.h | 98 - .../projective_occupancy_integrator.h | 123 + .../integrators/projective_tsdf_integrator.h | 154 +- .../nvblox/integrators/view_calculator.h | 59 +- .../nvblox/integrators/weighting_function.h | 69 + .../internal}/impl/interpolation_2d_impl.h | 13 +- .../internal}/impl/interpolation_3d_impl.h | 27 +- .../interpolation_2d.h | 4 +- .../interpolation_3d.h | 13 +- nvblox/include/nvblox/io/csv.h | 8 +- nvblox/include/nvblox/io/image_io.h | 47 + .../nvblox/io/{ => internal}/impl/csv_impl.h | 2 +- .../{ => internal}/impl/pointcloud_io_impl.h | 2 +- .../nvblox/io/internal/thirdparty/stb_image.h | 7890 +++++++++++++++++ .../io/internal/thirdparty/stb_image_write.h | 1724 ++++ nvblox/include/nvblox/io/layer_cake_io.h | 2 +- nvblox/include/nvblox/io/mesh_io.h | 5 +- nvblox/include/nvblox/io/pointcloud_io.h | 9 +- .../include/nvblox/{core => map}/accessors.h | 8 +- nvblox/include/nvblox/{core => map}/blox.h | 9 +- .../nvblox/{core => map}/common_names.h | 8 +- .../internal}/cuda/impl/layer_impl.cuh | 4 +- .../internal}/impl/accessors_impl.h | 4 +- .../{core => map/internal}/impl/blox_impl.h | 0 .../internal}/impl/layer_cake_impl.h | 0 .../{core => map/internal}/impl/layer_impl.h | 28 +- nvblox/include/nvblox/{core => map}/layer.h | 14 +- .../include/nvblox/{core => map}/layer_cake.h | 14 +- nvblox/include/nvblox/{core => map}/voxels.h | 4 + .../include/nvblox/{core => mapper}/mapper.h | 210 +- nvblox/include/nvblox/mapper/multi_mapper.h | 102 + .../impl/marching_cubes_table.h | 0 .../mesh/{ => internal}/marching_cubes.h | 14 +- nvblox/include/nvblox/mesh/mesh.h | 2 +- nvblox/include/nvblox/mesh/mesh_block.h | 8 +- nvblox/include/nvblox/mesh/mesh_integrator.h | 6 +- nvblox/include/nvblox/nvblox.h | 53 +- .../{ => internal}/impl/scene_impl.h | 71 +- nvblox/include/nvblox/primitives/primitives.h | 2 +- nvblox/include/nvblox/primitives/scene.h | 20 +- .../{ => internal}/impl/ray_caster_impl.h | 14 +- nvblox/include/nvblox/rays/ray_caster.h | 4 +- nvblox/include/nvblox/rays/sphere_tracer.h | 137 +- .../include/nvblox/semantics/image_masker.h | 90 +- .../nvblox/semantics/image_projector.h | 13 +- .../include/nvblox/{core => sensors}/camera.h | 6 +- nvblox/include/nvblox/sensors/image.h | 247 + .../internal}/impl/camera_impl.h | 2 +- .../internal/impl/image_cuda_impl.h} | 15 +- .../nvblox/sensors/internal/impl/image_impl.h | 175 + .../internal}/impl/lidar_impl.h | 2 +- .../include/nvblox/{core => sensors}/lidar.h | 2 +- .../nvblox/{core => sensors}/pointcloud.h | 4 +- .../{ => internal}/block_serialization.h | 4 +- .../{ => internal}/common_types.h | 14 +- .../impl/block_serialization_impl.h | 0 .../{ => internal}/impl/common_types_impl.h | 2 + .../impl/layer_serialization_impl.h | 0 .../{ => internal}/layer_serialization.h | 10 +- .../{ => internal}/layer_type_register.h | 4 +- .../serialization/{ => internal}/serializer.h | 12 +- .../{ => internal}/sqlite_database.h | 3 +- nvblox/include/nvblox/utils/logging.h | 77 + nvblox/lint/format_everything.sh | 8 + nvblox/lint/lint_nvblox_h.sh | 63 + nvblox/src/benchmarks/sphere_benchmark.cpp | 25 +- nvblox/src/core/cuda/image_cuda.cu | 148 - nvblox/src/core/{cuda => }/error_check.cu | 2 +- nvblox/src/core/image.cpp | 81 - nvblox/src/core/interpolation_3d.cpp | 57 - nvblox/src/core/mapper.cpp | 257 - nvblox/src/core/{cuda => }/warmup.cu | 4 +- .../src/{core => geometry}/bounding_boxes.cpp | 2 +- .../{core => geometry}/bounding_spheres.cpp | 4 +- .../src/gpu_hash/{cuda => }/gpu_layer_view.cu | 5 +- nvblox/src/gpu_hash/{cuda => }/gpu_set.cu | 2 +- .../integrators/{cuda => }/esdf_integrator.cu | 515 +- .../integrators/occupancy_decay_integrator.cu | 176 + .../{cuda => }/projective_color_integrator.cu | 102 +- .../projective_integrator_base.cpp | 62 - .../projective_occupancy_integrator.cu | 162 + .../integrators/projective_tsdf_integrator.cu | 235 + nvblox/src/integrators/view_calculator.cpp | 66 - .../integrators/{cuda => }/view_calculator.cu | 106 +- nvblox/src/interpolation/interpolation_3d.cpp | 103 + nvblox/src/io/csv.cpp | 105 - nvblox/src/io/image_io.cpp | 170 + nvblox/src/io/layer_cake_io.cpp | 4 +- nvblox/src/io/mesh_io.cpp | 5 + nvblox/src/io/ply_writer.cpp | 2 +- nvblox/src/io/pointcloud_io.cpp | 40 +- nvblox/src/{core/cuda => map}/blox.cu | 4 +- nvblox/src/{core/cuda => map}/layer.cu | 4 +- nvblox/src/mapper/mapper.cpp | 283 + nvblox/src/mapper/multi_mapper.cpp | 84 + nvblox/src/mesh/marching_cubes.cu | 4 +- nvblox/src/mesh/mesh_integrator.cpp | 221 - nvblox/src/mesh/mesh_integrator.cu | 218 +- nvblox/src/mesh/mesh_integrator_color.cu | 14 +- nvblox/src/rays/{cuda => }/sphere_tracer.cu | 239 +- .../src/semantics/{cuda => }/image_masker.cu | 267 +- .../semantics/{cuda => }/image_projector.cu | 16 +- nvblox/src/{core => sensors}/camera.cpp | 35 +- nvblox/src/{core => sensors}/color.cpp | 0 nvblox/src/sensors/image.cu | 286 + .../src/{core/cuda => sensors}/pointcloud.cu | 6 +- .../src/serialization/layer_type_register.cpp | 2 +- nvblox/src/serialization/serializer.cpp | 4 +- nvblox/src/serialization/sqlite_database.cpp | 6 +- nvblox/src/utils/timing.cpp | 2 +- nvblox/tests/CMakeLists.txt | 31 +- nvblox/tests/include/nvblox/tests/blox.h | 2 +- .../tests/include/nvblox/tests/blox_utils.h | 4 +- .../nvblox/tests/esdf_integrator_cpu.h | 70 + .../include/nvblox/tests/gpu_image_routines.h | 2 +- .../include/nvblox/tests/gpu_layer_utils.h | 2 +- .../include/nvblox/tests/integrator_utils.h | 51 + .../nvblox/tests/interpolation_2d_gpu.h | 2 +- .../tests/include/nvblox/tests/mesh_utils.h | 8 +- .../tests/projective_tsdf_integrator_cpu.h | 6 +- ...ojective_tsdf_integrator_cuda_components.h | 12 +- .../include/nvblox/tests/test_utils_cuda.h | 4 +- nvblox/tests/include/nvblox/tests/utils.h | 6 +- .../include/nvblox/tests/weighting_utils.h | 20 + nvblox/tests/lib/cuda/blox.cu | 2 +- nvblox/tests/lib/cuda/gpu_image_routines.cu | 4 +- nvblox/tests/lib/cuda/gpu_layer_utils.cu | 9 +- nvblox/tests/lib/cuda/increment_kernel.cu | 1 - nvblox/tests/lib/cuda/interpolation_2d_gpu.cu | 2 +- nvblox/tests/lib/cuda/layer.cu | 4 +- nvblox/tests/lib/cuda/mesh_utils.cu | 5 +- ...jective_tsdf_integrator_cuda_components.cu | 22 +- nvblox/tests/lib/cuda/test_utils_cuda.cu | 13 +- nvblox/tests/lib/cuda/weighting_utils.cu | 34 + .../lib/esdf_integrator_cpu.cpp} | 105 +- nvblox/tests/lib/integrator_utils.cpp | 110 + .../lib/projective_tsdf_integrator_cpu.cpp | 2 +- nvblox/tests/lib/utils.cpp | 2 +- nvblox/tests/test_3d_interpolation.cpp | 6 +- nvblox/tests/test_3dmatch.cpp | 4 +- nvblox/tests/test_blox.cpp | 6 +- nvblox/tests/test_bounding_spheres.cpp | 8 +- nvblox/tests/test_cake.cpp | 10 +- nvblox/tests/test_camera.cpp | 23 +- nvblox/tests/test_color_image.cpp | 8 +- nvblox/tests/test_color_integrator.cpp | 153 +- nvblox/tests/test_depth_image.cpp | 238 +- nvblox/tests/test_esdf_integrator.cpp | 228 +- nvblox/tests/test_for_memory_leaks.cpp | 8 +- nvblox/tests/test_frustum.cpp | 10 +- nvblox/tests/test_fuser.cpp | 92 +- nvblox/tests/test_gpu_layer_view.cpp | 12 +- nvblox/tests/test_image_io.cpp | 115 + nvblox/tests/test_image_masker.cpp | 107 +- nvblox/tests/test_image_projector.cpp | 16 +- nvblox/tests/test_indexing.cpp | 4 +- nvblox/tests/test_layer.cpp | 16 +- nvblox/tests/test_lidar.cpp | 15 +- nvblox/tests/test_lidar_integration.cpp | 11 +- nvblox/tests/test_mapper.cpp | 125 +- nvblox/tests/test_mesh.cpp | 18 +- nvblox/tests/test_mesh_coloring.cpp | 10 +- ...human_mapper.cpp => test_multi_mapper.cpp} | 73 +- nvblox/tests/test_occupancy_decay.cpp | 185 + nvblox/tests/test_occupancy_integrator.cpp | 217 + nvblox/tests/test_pointcloud.cpp | 2 +- nvblox/tests/test_ray_caster.cpp | 4 +- nvblox/tests/test_scene.cpp | 4 +- nvblox/tests/test_serialization.cpp | 16 +- nvblox/tests/test_sphere_tracing.cpp | 87 +- nvblox/tests/test_traits.cpp | 8 +- nvblox/tests/test_tsdf_integrator.cpp | 305 +- .../test_tsdf_integrator_cuda_components.cpp | 2 +- nvblox/tests/test_unified_ptr.cpp | 4 +- nvblox/tests/test_unified_vector.cpp | 2 +- nvblox/tests/test_weighting_function.cpp | 126 + .../visualize_csv_color_image.py | 30 - .../visualize_csv_depth_image.py | 18 - .../visualization/visualize_csv_pointcloud.py | 23 - nvblox/visualization/visualize_mesh.py | 57 - python_scripts/COLCON_IGNORE | 0 python_scripts/README.md | 20 + .../nvblox_visualize_mesh/__main__.py | 34 + python_scripts/requirements.txt | 1 + python_scripts/setup.py | 17 + 351 files changed, 17912 insertions(+), 7735 deletions(-) create mode 100644 docs/images/3dmatch.gif create mode 100644 docs/images/redwood_apartment.png create mode 100644 docs/images/replica_office0.png create mode 100644 docs/pages/tutorial_library_interface.md create mode 100644 docs/pages/tutorial_public_datasets.md rename nvblox/evaluation/replica/evaluation_utils/__init__.py => docs/root.md (100%) delete mode 100644 docs/root.rst delete mode 100644 docs/rst/examples/core_example.rst delete mode 100644 docs/rst/examples/index.rst delete mode 100644 docs/rst/examples/ros_example.rst delete mode 100644 docs/rst/index.rst delete mode 100644 docs/rst/installation/core.rst delete mode 100644 docs/rst/installation/index.rst delete mode 100644 docs/rst/installation/ros.rst delete mode 100644 docs/rst/integrators.rst delete mode 100644 docs/rst/map.rst delete mode 100644 docs/rst/mapper.rst delete mode 100644 docs/rst/rays.rst rename nvblox/{experiments/experiments/compare_branches/__init__.py => evaluation/COLCON_IGNORE} (100%) create mode 100644 nvblox/evaluation/README.md rename nvblox/{experiments/experiments/threaded_image_loading => evaluation/nvblox_evaluation}/__init__.py (100%) rename nvblox/evaluation/{replica => nvblox_evaluation/compare_branch_timings}/.gitignore (100%) create mode 100644 nvblox/evaluation/nvblox_evaluation/compare_branch_timings/README.md rename nvblox/{experiments/python/nvblox_experiments => evaluation/nvblox_evaluation/compare_branch_timings}/__init__.py (100%) rename nvblox/{experiments/experiments/compare_branches/compare_branches.py => evaluation/nvblox_evaluation/compare_branch_timings/compare_branch_timings.py} (91%) create mode 100644 nvblox/evaluation/nvblox_evaluation/compare_branch_timings/helpers/__init__.py rename nvblox/{experiments/experiments/compare_branches/plot_comparison.py => evaluation/nvblox_evaluation/compare_branch_timings/helpers/plot_timing_comparison.py} (98%) rename nvblox/{experiments/python/nvblox_experiments/threedmatch.py => evaluation/nvblox_evaluation/compare_branch_timings/helpers/run_threedmatch.py} (100%) create mode 100644 nvblox/evaluation/nvblox_evaluation/evaluation_utils/__init__.py rename nvblox/evaluation/{replica => nvblox_evaluation}/evaluation_utils/esdf_evaluation.py (98%) rename nvblox/evaluation/{replica/timing.py => nvblox_evaluation/evaluation_utils/parse_nvblox_timing.py} (100%) rename nvblox/evaluation/{replica => nvblox_evaluation}/evaluation_utils/quad_mesh.py (100%) rename nvblox/evaluation/{replica => nvblox_evaluation}/evaluation_utils/surface_evaluation.py (100%) rename nvblox/evaluation/{replica => nvblox_evaluation}/evaluation_utils/voxel_grid.py (100%) create mode 100644 nvblox/evaluation/nvblox_evaluation/replica_reconstruction_evaluation/.gitignore rename nvblox/evaluation/{replica => nvblox_evaluation/replica_reconstruction_evaluation}/README.md (100%) create mode 100644 nvblox/evaluation/nvblox_evaluation/replica_reconstruction_evaluation/__init__.py rename nvblox/evaluation/{replica => nvblox_evaluation/replica_reconstruction_evaluation}/replica.py (98%) rename nvblox/evaluation/{replica => nvblox_evaluation/replica_reconstruction_evaluation}/replica_esdf_evaluation.py (97%) rename nvblox/evaluation/{replica => nvblox_evaluation/replica_reconstruction_evaluation}/replica_reconstruction.py (97%) rename nvblox/evaluation/{replica => nvblox_evaluation/replica_reconstruction_evaluation}/replica_surface_evaluation.py (98%) create mode 100644 nvblox/evaluation/requirements.txt create mode 100644 nvblox/evaluation/setup.py delete mode 100644 nvblox/experiments/.gitignore create mode 100644 nvblox/experiments/README.md delete mode 100644 nvblox/experiments/experiments/compare_branches/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/isolate_tsdf_block_update/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/isolate_tsdf_block_update/main.cpp delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/cake_common.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/cake_dynamic.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/cake_static.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/cake_type_erasure.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/impl/cake_common_impl.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/impl/cake_dynamic_impl.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/impl/cake_static_impl.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/impl/load_impl.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/load.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/include/nvblox/experiments/user_defined_block.h delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/main_dynamic.cpp delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/main_static.cpp delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/main_type_erasure.cpp delete mode 100644 nvblox/experiments/experiments/layer_cake_interface/src/cuda/user_defined_block.cu delete mode 100644 nvblox/experiments/experiments/ratio_of_freespace/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/ratio_of_freespace/main.cpp delete mode 100755 nvblox/experiments/experiments/ratio_of_freespace/run_experiment.py delete mode 100644 nvblox/experiments/experiments/realistic_timings/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/realistic_timings/compare_platforms.py delete mode 100644 nvblox/experiments/experiments/realistic_timings/gather_timings.py delete mode 100644 nvblox/experiments/experiments/realistic_timings/plot_timings.py delete mode 100644 nvblox/experiments/experiments/stream_compaction/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/stream_compaction/include/nvblox/experiments/cached_allocator.h delete mode 100644 nvblox/experiments/experiments/stream_compaction/include/nvblox/experiments/stream_compaction.h delete mode 100644 nvblox/experiments/experiments/stream_compaction/lib/cached_allocator.cu delete mode 100644 nvblox/experiments/experiments/stream_compaction/lib/stream_compaction.cu delete mode 100644 nvblox/experiments/experiments/stream_compaction/main.cpp delete mode 100644 nvblox/experiments/experiments/stream_compaction/plot.py delete mode 100644 nvblox/experiments/experiments/stream_compaction/run.py delete mode 100644 nvblox/experiments/experiments/texture_vs_global_memory_interpolation/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/texture_vs_global_memory_interpolation/main.cpp delete mode 100644 nvblox/experiments/experiments/threaded_image_loading/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/threaded_image_loading/main.cpp delete mode 100644 nvblox/experiments/experiments/threaded_image_loading/plot_comparison.py delete mode 100644 nvblox/experiments/experiments/threaded_image_loading/run.py delete mode 100644 nvblox/experiments/experiments/unified_vs_device_memory/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/unified_vs_device_memory/analyze_results.py delete mode 100644 nvblox/experiments/experiments/unified_vs_device_memory/main.cpp delete mode 100755 nvblox/experiments/experiments/unified_vs_device_memory/run.py delete mode 100644 nvblox/experiments/experiments/vector_copies/CMakeLists.txt delete mode 100644 nvblox/experiments/experiments/vector_copies/main.cpp delete mode 100644 nvblox/experiments/experiments/vector_copies/plot_timings.py delete mode 100644 nvblox/experiments/experiments/vector_copies/vector_copies.cu delete mode 100644 nvblox/experiments/experiments/vector_copies/vector_copies.h delete mode 100644 nvblox/experiments/include/nvblox/experiments/integrators/cuda/experimental_integrator_input_frames.cuh delete mode 100644 nvblox/experiments/include/nvblox/experiments/integrators/experimental_projective_tsdf_integrators.h delete mode 100644 nvblox/experiments/python/MANIFEST.in delete mode 100644 nvblox/experiments/python/README.md delete mode 100644 nvblox/experiments/python/nvblox_experiments/timing.py delete mode 100644 nvblox/experiments/python/requirements.txt delete mode 100644 nvblox/experiments/python/setup.py delete mode 100644 nvblox/experiments/src/integrators/cuda/depth_frame_texture.cu delete mode 100644 nvblox/experiments/src/integrators/cuda/experimental_integrator_input_frames.cu delete mode 100644 nvblox/experiments/src/integrators/cuda/experimental_projective_tsdf_integrators.cu create mode 100644 nvblox/experiments/src/test_bench.cpp create mode 100644 nvblox/experiments/test_bench/include/nvblox/experiments/.gitkeep delete mode 100644 nvblox/include/nvblox/core/cuda/image_cuda.h delete mode 100644 nvblox/include/nvblox/core/image.h delete mode 100644 nvblox/include/nvblox/core/impl/image_impl.h rename nvblox/include/nvblox/core/{ => internal}/cuda/atomic_float.cuh (83%) rename nvblox/include/nvblox/core/{ => internal}/cuda/impl/atomic_float_impl.cuh (77%) rename nvblox/include/nvblox/core/{cuda/error_check.cuh => internal/error_check.h} (96%) rename nvblox/include/nvblox/core/{ => internal}/impl/indexing_impl.h (98%) rename nvblox/include/nvblox/core/{ => internal}/impl/unified_ptr_impl.h (92%) rename nvblox/include/nvblox/core/{ => internal}/impl/unified_vector_impl.h (99%) rename nvblox/include/nvblox/core/{ => internal}/impl/variadic_template_tools_impl.h (100%) rename nvblox/include/nvblox/core/{cuda/warmup.h => internal/warmup_cuda.h} (96%) rename nvblox/{experiments/include/nvblox/experiments/integrators/cuda/depth_frame_texture.cuh => include/nvblox/core/log_odds.h} (55%) rename nvblox/include/nvblox/{core => geometry}/bounding_boxes.h (95%) rename nvblox/include/nvblox/{core => geometry}/bounding_spheres.h (97%) rename nvblox/include/nvblox/{core => geometry/internal}/impl/bounding_boxes_impl.h (98%) rename nvblox/include/nvblox/gpu_hash/{ => internal}/cuda/gpu_hash_interface.cuh (93%) rename nvblox/include/nvblox/gpu_hash/{ => internal}/cuda/gpu_indexing.cuh (91%) rename nvblox/include/nvblox/gpu_hash/{ => internal}/cuda/gpu_set.cuh (100%) rename nvblox/include/nvblox/gpu_hash/{ => internal}/cuda/impl/gpu_hash_interface_impl.cuh (100%) rename nvblox/include/nvblox/gpu_hash/{ => internal}/cuda/impl/gpu_layer_view_impl.cuh (95%) rename nvblox/{src/integrators/cuda/projective_tsdf_integrator.cu => include/nvblox/integrators/internal/cuda/impl/projective_integrator_impl.cuh} (60%) create mode 100644 nvblox/include/nvblox/integrators/internal/impl/projective_integrator_impl.h create mode 100644 nvblox/include/nvblox/integrators/internal/impl/weighting_function_impl.h create mode 100644 nvblox/include/nvblox/integrators/internal/projective_integrator.h create mode 100644 nvblox/include/nvblox/integrators/occupancy_decay_integrator.h delete mode 100644 nvblox/include/nvblox/integrators/projective_integrator_base.h create mode 100644 nvblox/include/nvblox/integrators/projective_occupancy_integrator.h create mode 100644 nvblox/include/nvblox/integrators/weighting_function.h rename nvblox/include/nvblox/{core => interpolation/internal}/impl/interpolation_2d_impl.h (95%) rename nvblox/include/nvblox/{core => interpolation/internal}/impl/interpolation_3d_impl.h (88%) rename nvblox/include/nvblox/{core => interpolation}/interpolation_2d.h (96%) rename nvblox/include/nvblox/{core => interpolation}/interpolation_3d.h (78%) create mode 100644 nvblox/include/nvblox/io/image_io.h rename nvblox/include/nvblox/io/{ => internal}/impl/csv_impl.h (96%) rename nvblox/include/nvblox/io/{ => internal}/impl/pointcloud_io_impl.h (98%) create mode 100644 nvblox/include/nvblox/io/internal/thirdparty/stb_image.h create mode 100644 nvblox/include/nvblox/io/internal/thirdparty/stb_image_write.h rename nvblox/include/nvblox/{core => map}/accessors.h (96%) rename nvblox/include/nvblox/{core => map}/blox.h (87%) rename nvblox/include/nvblox/{core => map}/common_names.h (83%) rename nvblox/include/nvblox/{core => map/internal}/cuda/impl/layer_impl.cuh (96%) rename nvblox/include/nvblox/{core => map/internal}/impl/accessors_impl.h (99%) rename nvblox/include/nvblox/{core => map/internal}/impl/blox_impl.h (100%) rename nvblox/include/nvblox/{core => map/internal}/impl/layer_cake_impl.h (100%) rename nvblox/include/nvblox/{core => map/internal}/impl/layer_impl.h (93%) rename nvblox/include/nvblox/{core => map}/layer.h (96%) rename nvblox/include/nvblox/{core => map}/layer_cake.h (91%) rename nvblox/include/nvblox/{core => map}/voxels.h (97%) rename nvblox/include/nvblox/{core => mapper}/mapper.h (65%) create mode 100644 nvblox/include/nvblox/mapper/multi_mapper.h rename nvblox/include/nvblox/mesh/{ => internal}/impl/marching_cubes_table.h (100%) rename nvblox/include/nvblox/mesh/{ => internal}/marching_cubes.h (90%) rename nvblox/include/nvblox/primitives/{ => internal}/impl/scene_impl.h (61%) rename nvblox/include/nvblox/rays/{ => internal}/impl/ray_caster_impl.h (86%) rename nvblox/include/nvblox/{core => sensors}/camera.h (95%) create mode 100644 nvblox/include/nvblox/sensors/image.h rename nvblox/include/nvblox/{core => sensors/internal}/impl/camera_impl.h (98%) rename nvblox/include/nvblox/{core/cuda/impl/image_cuda_impl.cuh => sensors/internal/impl/image_cuda_impl.h} (70%) create mode 100644 nvblox/include/nvblox/sensors/internal/impl/image_impl.h rename nvblox/include/nvblox/{core => sensors/internal}/impl/lidar_impl.h (99%) rename nvblox/include/nvblox/{core => sensors}/lidar.h (98%) rename nvblox/include/nvblox/{core => sensors}/pointcloud.h (97%) rename nvblox/include/nvblox/serialization/{ => internal}/block_serialization.h (93%) rename nvblox/include/nvblox/serialization/{ => internal}/common_types.h (70%) rename nvblox/include/nvblox/serialization/{ => internal}/impl/block_serialization_impl.h (100%) rename nvblox/include/nvblox/serialization/{ => internal}/impl/common_types_impl.h (95%) rename nvblox/include/nvblox/serialization/{ => internal}/impl/layer_serialization_impl.h (100%) rename nvblox/include/nvblox/serialization/{ => internal}/layer_serialization.h (91%) rename nvblox/include/nvblox/serialization/{ => internal}/layer_type_register.h (97%) rename nvblox/include/nvblox/serialization/{ => internal}/serializer.h (95%) rename nvblox/include/nvblox/serialization/{ => internal}/sqlite_database.h (97%) create mode 100644 nvblox/include/nvblox/utils/logging.h create mode 100644 nvblox/lint/format_everything.sh create mode 100644 nvblox/lint/lint_nvblox_h.sh delete mode 100644 nvblox/src/core/cuda/image_cuda.cu rename nvblox/src/core/{cuda => }/error_check.cu (95%) delete mode 100644 nvblox/src/core/image.cpp delete mode 100644 nvblox/src/core/interpolation_3d.cpp delete mode 100644 nvblox/src/core/mapper.cpp rename nvblox/src/core/{cuda => }/warmup.cu (92%) rename nvblox/src/{core => geometry}/bounding_boxes.cpp (98%) rename nvblox/src/{core => geometry}/bounding_spheres.cpp (96%) rename nvblox/src/gpu_hash/{cuda => }/gpu_layer_view.cu (86%) rename nvblox/src/gpu_hash/{cuda => }/gpu_set.cu (96%) rename nvblox/src/integrators/{cuda => }/esdf_integrator.cu (70%) create mode 100644 nvblox/src/integrators/occupancy_decay_integrator.cu rename nvblox/src/integrators/{cuda => }/projective_color_integrator.cu (83%) delete mode 100644 nvblox/src/integrators/projective_integrator_base.cpp create mode 100644 nvblox/src/integrators/projective_occupancy_integrator.cu create mode 100644 nvblox/src/integrators/projective_tsdf_integrator.cu delete mode 100644 nvblox/src/integrators/view_calculator.cpp rename nvblox/src/integrators/{cuda => }/view_calculator.cu (80%) create mode 100644 nvblox/src/interpolation/interpolation_3d.cpp delete mode 100644 nvblox/src/io/csv.cpp create mode 100644 nvblox/src/io/image_io.cpp rename nvblox/src/{core/cuda => map}/blox.cu (95%) rename nvblox/src/{core/cuda => map}/layer.cu (93%) create mode 100644 nvblox/src/mapper/mapper.cpp create mode 100644 nvblox/src/mapper/multi_mapper.cpp delete mode 100644 nvblox/src/mesh/mesh_integrator.cpp rename nvblox/src/rays/{cuda => }/sphere_tracer.cu (61%) rename nvblox/src/semantics/{cuda => }/image_masker.cu (57%) rename nvblox/src/semantics/{cuda => }/image_projector.cu (87%) rename nvblox/src/{core => sensors}/camera.cpp (81%) rename nvblox/src/{core => sensors}/color.cpp (100%) create mode 100644 nvblox/src/sensors/image.cu rename nvblox/src/{core/cuda => sensors}/pointcloud.cu (95%) create mode 100644 nvblox/tests/include/nvblox/tests/esdf_integrator_cpu.h create mode 100644 nvblox/tests/include/nvblox/tests/integrator_utils.h create mode 100644 nvblox/tests/include/nvblox/tests/weighting_utils.h create mode 100644 nvblox/tests/lib/cuda/weighting_utils.cu rename nvblox/{src/integrators/esdf_integrator.cpp => tests/lib/esdf_integrator_cpu.cpp} (90%) create mode 100644 nvblox/tests/lib/integrator_utils.cpp create mode 100644 nvblox/tests/test_image_io.cpp rename nvblox/tests/{test_human_mapper.cpp => test_multi_mapper.cpp} (65%) create mode 100644 nvblox/tests/test_occupancy_decay.cpp create mode 100644 nvblox/tests/test_occupancy_integrator.cpp create mode 100644 nvblox/tests/test_weighting_function.cpp delete mode 100755 nvblox/tests/visualization/visualize_csv_color_image.py delete mode 100755 nvblox/tests/visualization/visualize_csv_depth_image.py delete mode 100755 nvblox/tests/visualization/visualize_csv_pointcloud.py delete mode 100755 nvblox/visualization/visualize_mesh.py create mode 100644 python_scripts/COLCON_IGNORE create mode 100644 python_scripts/README.md create mode 100644 python_scripts/nvblox_visualize_mesh/__main__.py create mode 100644 python_scripts/requirements.txt create mode 100644 python_scripts/setup.py diff --git a/.gitignore b/.gitignore index eff634ad..28e00602 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,8 @@ # Python *.pyc +**/*.egg-info +**/__pycache__ # Reconstructions *.ply diff --git a/Jenkinsfile b/Jenkinsfile index b764229b..9402f779 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,6 +23,11 @@ pipeline { sh '''cd nvblox/build && cmake .. -DCMAKE_INSTALL_PREFIX=../install && make clean && make -j8 && make install''' } } + stage('Lint') { + steps { + sh '''bash nvblox/lint/lint_nvblox_h.sh''' + } + } stage('Test x86') { steps { sh '''cd nvblox/build/tests && ctest -T test --no-compress-output''' @@ -69,10 +74,10 @@ pipeline { } } } - stage("Jetson 5.0.2") { + stage("Jetson 5.1.1") { agent { dockerfile { - label 'jetson-5.0.2' + label 'jp-5.1.1' reuseNode true filename 'docker/Dockerfile.jetson_deps' args '-u root --runtime nvidia --gpus all -v /var/run/docker.sock:/var/run/docker.sock:rw' @@ -86,6 +91,11 @@ pipeline { sh '''cd nvblox/build && cmake .. -DCMAKE_INSTALL_PREFIX=../install && make clean && make -j8 && make install''' } } + stage('Lint') { + steps { + sh '''bash nvblox/lint/lint_nvblox_h.sh''' + } + } stage('Test Jetson') { steps { sh '''cd nvblox/build/tests && ctest -T test --no-compress-output''' diff --git a/README.md b/README.md index 3fee1530..59200b77 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,75 @@ -# nvblox +# nvblox ![nvblox_logo](docs/images/nvblox_logo_64.png) + Signed Distance Functions (SDFs) on NVIDIA GPUs. -
+
+ -An SDF library which offers -* Support for storage of various voxel types -* GPU accelerated agorithms such as: +A GPU SDF library which offers +* GPU accelerated algorithms such as: * TSDF construction + * Occupancy mapping * ESDF construction * Meshing -* ROS2 interface (see [isaac_ros_nvblox](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox)) -* ~~Python bindings~~ (coming soon) +* ROS 2 interface (see [isaac_ros_nvblox](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox)) +* Support for storage of various voxel types, and easily extended to custom voxel types. + +Above we show reconstruction using data from the [3DMatch dataset](https://3dmatch.cs.princeton.edu/), specifically the [Sun3D](http://sun3d.cs.princeton.edu/) `mit_76_studyroom` scene. + +## Table of Contents + +- [nvblox ](#nvblox-) + - [Table of Contents](#table-of-contents) +- [Why nvblox?](#why-nvblox) +- [How to use nvblox](#how-to-use-nvblox) + - [Out-of-the-box Reconstruction/ROS 2 Interface](#out-of-the-box-reconstructionros-2-interface) + - [Public Datasets](#public-datasets) + - [C++ Interface](#c-interface) +- [Native Installation](#native-installation) + - [Install dependencies](#install-dependencies) + - [Build and run tests](#build-and-run-tests) + - [Run an example](#run-an-example) +- [Docker](#docker) +- [Additional instructions for Jetson Xavier](#additional-instructions-for-jetson-xavier) + - [Open3D on Jetson](#open3d-on-jetson) +- [Building for multiple GPU architectures](#building-for-multiple-gpu-architectures) +- [Building redistributable binaries, with static dependencies](#building-redistributable-binaries-with-static-dependencies) +- [License](#license) + +# Why nvblox? Do we need another SDF library? That depends on your use case. If you're interested in: -* **Path planning**: We provide GPU accelerated, incremental algorithms for calculating the Euclidian Signed Distance Field (ESDF) which is useful for colision checking and therefore robotic pathplanning. In contrast, existing GPU-accelerated libraries target reconstruction only, and are therefore generally not useful in a robotics context. -* **GPU acceleration**: Our previous works [voxblox](https://github.com/ethz-asl/voxblox) and [voxgraph](https://github.com/ethz-asl/voxgraph) are used for path planning, however utilize CPU compute only, which limits the speed of these toolboxes (and therefore the resolution of the maps they can build in real-time). +* **Path planning**: We provide GPU accelerated, incremental algorithms for calculating the Euclidean Signed Distance Field (ESDF) which is useful for collision checking for robotic path-planning. +* **GPU acceleration**: Our previous works [voxblox](https://github.com/ethz-asl/voxblox) and [voxgraph](https://github.com/ethz-asl/voxgraph) are used for path-planning, however utilize CPU compute only, which limits the speed of these toolboxes, and therefore the resolution of the maps they can build in real-time. nvblox is *much* faster. +* **Jetson Platform**: nvblox is written with the [NVIDIA jetson](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/) in mind. If you want to run reconstruction on an embedded GPU, you're in the right place. -Here we show slices through a distance function generated from *nvblox* using data from the [3DMatch dataset](https://3dmatch.cs.princeton.edu/), specifically the [Sun3D](http://sun3d.cs.princeton.edu/) `mit_76_studyroom` scene: +Below we visualize slices through a distance function (ESDF):
-# Note from the authors -This package is under active development. Feel free to make an issue for bugs or feature requests, and we always welcome pull requests! -# ROS2 Interface -This repo contains the core library which can be linked into users' projects. If you want to use nvblox on a robot out-of-the-box, please see our [ROS2 interface](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox), which downloads and builds the core library during installation. +# How to use nvblox +How use nvblox depends on what you want to do. + +## Out-of-the-box Reconstruction/ROS 2 Interface + +For users who would like to use nvblox in a robotic system or connect easily to a sensor, we suggest using our [ROS 2 interface](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox). + +The ROS 2 interface includes examples which allow you to: +* Build a reconstruction from a realsense camera using nvblox and NVIDIA VSLAM [here](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox/blob/main/docs/tutorial-nvblox-vslam-realsense.md). +* Navigate a robot in Isaac Sim [here](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox/blob/main/docs/tutorial-isaac-sim.md). +* Combine 3D reconstruction with image segmentation with [realsense data](https://gitlab-master.nvidia.com/isaac_ros/isaac_ros_nvblox/-/blob/envoy-dev/docs/tutorial-human-reconstruction-realsense.md) and in [simulation](https://gitlab-master.nvidia.com/isaac_ros/isaac_ros_nvblox/-/blob/envoy-dev/docs/tutorial-human-reconstruction-isaac-sim.md). + +The ROS 2 interface downloads and builds the library contained in this repository during installation, so you don't need to clone and build this repository at all. + +## Public Datasets + +If you would like to run nvblox on a public datasets, we include some executables for running reconstructions on [3DMatch](https://3dmatch.cs.princeton.edu/), [Replica](https://github.com/facebookresearch/Replica-Dataset), and [Redwood](http://redwood-data.org/indoor_lidar_rgbd/index.html) datasets. Please see our [tutorial](./docs/pages/tutorial_public_datasets.md) on running these. + +## C++ Interface + +If you want to build nvblox into a larger project, without ROS, or you would like to make modifications to nvblox's core reconstruction features, this repository contains the code you need. Our [tutorial](./docs/pages/tutorial_library_interface.md) provides some brief details of how to interact with the reconstruction in c++. + # Native Installation If you want to build natively, please follow these instructions. Instructions for docker are [further below](#docker). @@ -33,10 +78,11 @@ If you want to build natively, please follow these instructions. Instructions fo We depend on: - gtest - glog -- gflags (to run experiments) -- CUDA 11.0 - 11.6 (others might work but are untested) +- gflags +- SQLite 3 +- CUDA 11.0 - 11.8 (others might work but are untested) - Eigen (no need to explicitly install, a recent version is built into the library) -- SQLite 3 (for serialization) +- stdgpu (downloaded during compilation) Please run ``` sudo apt-get install -y libgoogle-glog-dev libgtest-dev libgflags-dev python3-dev libsqlite3-dev @@ -60,12 +106,11 @@ unzip ~/datasets/3dmatch/sun3d-mit_76_studyroom-76-1studyroom2.zip -d ~/datasets Navigate to and run the `fuse_3dmatch` binary. From the nvblox base folder run ``` cd nvblox/build/executables -./fuse_3dmatch ~/datasets/3dmatch/sun3d-mit_76_studyroom-76-1studyroom2/ --esdf_frame_subsampling 3000 --mesh_output_path mesh.ply +./fuse_3dmatch ~/datasets/3dmatch/sun3d-mit_76_studyroom-76-1studyroom2/ mesh.ply ``` -Once it's done we can view the output mesh using the Open3D viewer. +Once it's done we can view the output mesh using the Open3D viewer. Instructions for installing open3d-viewer can be found below. ``` -pip3 install open3d -python3 ../../visualization/visualize_mesh.py mesh.ply +Open3D mesh.ply ``` you should see a mesh of a room:
@@ -88,7 +133,7 @@ We have several dockerfiles (in the `docker` subfolder) which layer on top of on * * Runs ours tests. * * Useful for checking if things are likely to pass the tests in CI. -We are reliant on nvidia docker. Install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html) following the instructions on that website. +We rely on nvidia docker. Install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html) following the instructions on that website. We use the GPU during build, not only at run time. In the default configuration the GPU is only used at at runtime. One must therefore set the default runtime. Add `"default-runtime": "nvidia"` to `/etc/docker/daemon.json` such that it looks like: ``` @@ -106,10 +151,12 @@ Restart docker ``` sudo systemctl restart docker ``` -Now Let's build Dockerfile.deps docker image. This image install contains our dependencies. (In case you are running this on the Jetson, simply substitute docker/`Dockerfile.jetson_deps` below and the rest of the instructions remain the same. +Now Let's build Dockerfile.deps docker image. This image install contains our dependencies. ``` docker build -t nvblox_deps -f docker/Dockerfile.deps . ``` +> In case you are running this on the Jetson, substitute the dockerfile: `docker/Dockerfile.jetson_deps` + Now let's build the Dockerfile.build. This image layers on the last, and actually builds the nvblox library. ``` docker build -t nvblox -f docker/Dockerfile.build . @@ -125,15 +172,17 @@ apt-get update apt-get install unzip wget http://vision.princeton.edu/projects/2016/3DMatch/downloads/rgbd-datasets/sun3d-mit_76_studyroom-76-1studyroom2.zip -P ~/datasets/3dmatch unzip ~/datasets/3dmatch/sun3d-mit_76_studyroom-76-1studyroom2.zip -d ~/datasets/3dmatch -cd nvblox/nvblox/build/executables -./fuse_3dmatch ~/datasets/3dmatch/sun3d-mit_76_studyroom-76-1studyroom2/ --esdf_frame_subsampling 3000 --mesh_output_path mesh.ply +cd nvblox/nvblox/build/executables/ +./fuse_3dmatch ~/datasets/3dmatch/sun3d-mit_76_studyroom-76-1studyroom2/ mesh.ply ``` Now let's visualize. From the same executable folder run: ``` -apt-get install python3-pip libgl1-mesa-glx -pip3 install open3d -python3 ../../visualization/visualize_mesh.py mesh.ply +apt-get install libgl1-mesa-glx libc++1 libc++1-10 libc++abi1-10 libglfw3 libpng16-16 +wget https://github.com/isl-org/Open3D/releases/download/v0.13.0/open3d-app-0.13.0-Ubuntu_20.04.deb +dpkg -i open3d-app-0.13.0-Ubuntu_20.04.deb +Open3D mesh.ply ``` +to visualize on the jetson see [below](#open3d-on-jetson). # Additional instructions for Jetson Xavier These instructions are for a native build on the Jetson Xavier. You can see the instructions above for running in docker. @@ -149,7 +198,7 @@ wget -qO - https://apt.kitware.com/keys/kitware-archive-latest.asc | ``` 2. Add the repository to your sources list and update. ``` -sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' +sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main' sudo apt-get update ``` 3. Update! @@ -161,6 +210,19 @@ sudo apt-get install cmake export OPENBLAS_CORETYPE=ARMV8 ``` +## Open3D on Jetson +Open3D is available pre-compiled for the jetson ([details here](http://www.open3d.org/docs/release/arm.html)). Install via pip: +``` +apt-get install python3-pip +pip3 install open3d==0.16.0 +``` +> If version `0.16.0` is not available you need to upgrade your pip with `pip3 install -U pip`. You may additionally need to add the upgraded pip version to your path. + +View the mesh via: +``` +open3d draw mesh.ply +``` + # Building for multiple GPU architectures By default, the library builds ONLY for the compute capability (CC) of the machine it's being built on. To build binaries that can be used across multiple machines (i.e., pre-built binaries for CI, for example), you can use the `BUILD_FOR_ALL_ARCHS` flag and set it to true. Example: ``` @@ -168,7 +230,7 @@ cmake .. -DBUILD_FOR_ALL_ARCHS=True -DCMAKE_INSTALL_PREFIX=../install/ && make - ``` # Building redistributable binaries, with static dependencies -If you want to include nvblox in another CMake project, simply `find_package(nvblox)` should bring in the correct libraries and headers. However, if you want to include it in a different build system such as Bazel, you can see the instructions here: [docs/redistibutable.md]. +If you want to include nvblox in another CMake project, simply `find_package(nvblox)` should bring in the correct libraries and headers. However, if you want to include it in a different build system such as Bazel, you can see the instructions [here](./docs/pages/redistibutable.md). # License This code is under an [open-source license](LICENSE) (Apache 2.0). :) diff --git a/docs/conf.py b/docs/conf.py index e8a29822..af2a69e2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,34 +19,15 @@ } extensions = [ - 'sphinx.ext.autosectionlabel', 'myst_parser', #'breathe', 'exhale', + 'sphinx.ext.autosectionlabel' ] project = name master_doc = 'root' -# html_theme_options = {'logo_only': True} html_extra_path = ['doxyoutput/html'] - -# # Setup the breathe extension -# breathe_projects = {"project": "./doxyoutput/xml"} -# breathe_default_project = "project" - -# # Setup the exhale extension -# exhale_args = { -# "verboseBuild": False, -# "containmentFolder": "./api", -# "rootFileName": "library_root.rst", -# "rootFileTitle": "Library API", -# "doxygenStripFromPath": "..", -# "createTreeView": True, -# "exhaleExecutesDoxygen": True, # SWITCH TO TRUE -# "exhaleUseDoxyfile": True, # SWITCH TO TRUE -# "pageLevelConfigMeta": ":github_url: https://github.com/nvidia-isaac/" + name -# } - -source_suffix = ['.rst', '.md'] +source_suffix = ['.md'] # Tell sphinx what the primary language being documented is. primary_domain = 'cpp' diff --git a/docs/images/3dmatch.gif b/docs/images/3dmatch.gif new file mode 100644 index 0000000000000000000000000000000000000000..3efce54483df860b45e4ea35653d9b4759bb3817 GIT binary patch literal 3341785 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

w zxKr}BENy%fv%jvn%Xx18Ru>NZ>{BwOF#6*=5#`@M=Ph@>?+M;9d2sm-vNU7+qu)v@ z{7^ECUklqaOy z0p8yyPy2?~R@dugQyx7ZyYt_x?T>z_BVnZ=1 zj>Xivz5=YOLmtwie&F!pAZozIqG9l;+J@X!q-CR5!Oz8`j)yIq?j1MPfkXeFi8=~s z0xF=9|Ib8)|J8~b7S{C_5p{fOy#9X^)vZJ=r~MqGLf`vh)JR9u{j%SVe@HZ|*as*7 zXQCPfO*^rF`)4S;ICg%l!E3uQ@7+!{R=$PVzx!mH3r{XZ*qn|(5BH%8Toq5NeGtA5 zhzB}yNW=b2+w+LEC#pl{HJz>5-xtluq3RdHT~jJ_ysY2$<$jcIB9T+30)m0QTPmIk zbffsS=GZ^oH?Af&{{EMc8M=NeH9myHWb9~reWyFiDqKB+WU*o2>p^j5ayE z7pUA%`SsfTq*FqKU)RwFJTPlY!f%j#1Oo+|T_K`_m5s3I9ho4J5A{CKa>gE*1dFW2 zAHll759~4__tYl6>0`BL<71sFE7oE4bCbkKt-w)NxK@ww`>|ud6htH2%jfF$oJRf* zd|qFvm0|(?Y23rTvk|0H6Ny(G&T+}~D#oM{dMqNjExUgU4f+WpaxOzFB)iQU4j5KN z#&q)|42)#Y?{g_ShgIVFT7E9#Rp74PNXveLqxX(Ah-QO0;;L_IAG6QLW_ZQOn|koX z1^kf>+713LPbsta_OM8V8j%gfN-U-UdnFh8gD<{w6a!*jNdt02M2OjRjjlsCy%u0poYJmuX=z_v zAvk@mPw+kVrqCF0j-EX*Hi3dGZT+rTE0NA=nJlLJS0!satD#} zAJ5)9w#c5`gr}$<#g~$i@5i-ElVs3hf$?yNUq%n725QW>;29$QN|HC$wF1}i@Hd6RV%U1;3q=lV6BXsm#@(E;jMpX~5zPr(+*Izw6j58*j!udfHptfG zt#5OzwjL%ZLr-(fyg=IFlMFc^4Q3>}{`(QNxf%2+!vHp( zA~b(Qu?K^78x*+5RQ17fr=~COF_Q>44gmt~Jt--y%(Uob&UbW@MTz1AO#GK*Hotx zu@(Lwe9=Q=%V-$i)uXPpuK068T*S`zCtN?vm1(0ILZ?~q4S&+hbM7W)&ms%Wnq%|` zpPFlF3Wc+r>Dp5O$>;LlB5QIC-Wyuy^<&E!lNH69p6oc4X_hB!y&KwTpgdP&^HWzs zR)AB>w0VhWz;I$qiBlw2MJ(Ip06QQYgkWXKa3S@f;o*d8H*$FQ_GRN6jtL1zmRR&H^`?O&@dT-h z7=TP4w0&T~o%Eq-QG6vT30PKZ3ps3eMOVj3-)TZt&SX@$P278{eCKDpGj5MlaZP z)paml+81+R;z#nJYr1z!P)d(5XR`iRt5dVZI~kn3??lWI&|}y5eI7L?NFQXFms?8{ zYsPhKhx=hRa;Qr*ZSr&p9YTpyc}#>GgT0YxC!&ups@yv4d-T;sE%G#LBDGe}Uj2P$ z3X$jf6-QYx_F0+O<>+rh|P?#o9`7?3xWXQyd+pl!sv12z@$29Lk%-53j&=O@)t zhd7?e$oD7oMf}6`1+iVC2 zJ0c0zokz<8rFuiiOaUUFZ_z|_0{FDsicV`hRHkIhB{{o-aYy;=omosTJB%RueAwmVahH<{sSeN4TSVpnN}ZlOn1 z3T<))hz7prR~vL6fNGU!$AzQ2h_M4dkflpVk7D#l0?wCXR2M{WS2XKmVFm=LeROT&6 z(=Ut2%wG5*wzAQZ?oIiBf^G!k9