Skip to content

Nanobind #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(FetchContent)

# Make build a release build unless otherwise specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
set_property(
CACHE CMAKE_BUILD_TYPE
PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo"
)
endif()

# ------------------------- Dependencies ------------------------- #
# Pull eigen if it's not available already
FetchContent_Declare(
Expand Down
21 changes: 14 additions & 7 deletions cpp/bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,23 @@ endif()
message("###############################################################")

# ------------------------- Make Python Bindings ------------------------- #
set(PYBIND11_FINDPYTHON ON)
find_package(
Python
3.11
REQUIRED
COMPONENTS Interpreter Development.Module
OPTIONAL_COMPONENTS Development.SABIModule
)

FetchContent_Declare(
pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.13.6
FIND_PACKAGE_ARGS # uses find_package first, git if it fails
nanobind
GIT_REPOSITORY https://github.com/wjakob/nanobind
GIT_TAG v2.7.0
# FIND_PACKAGE_ARGS # uses find_package first, git if it fails
)
FetchContent_MakeAvailable(pybind11)
FetchContent_MakeAvailable(nanobind)

pybind11_add_module(_cpp main.cpp)
nanobind_add_module(_cpp STABLE_ABI NB_STATIC main.cpp)
target_link_libraries(_cpp PRIVATE ${LIBS})
target_compile_definitions(_cpp PRIVATE ${DEF})
install(TARGETS _cpp DESTINATION evalio)
Expand Down
11 changes: 6 additions & 5 deletions cpp/bindings/main.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#include <pybind11/eigen.h>
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <nanobind/nanobind.h>

#include "bindings/pipelines/bindings.h"
#include "bindings/ros_pc2.h"
#include "bindings/types.h"
#include "evalio/bindings.h"

PYBIND11_MODULE(_cpp, m) {
namespace nb = nanobind;

NB_MODULE(_cpp, m) {
m.def("abi_tag", []() { return nb::detail::abi_tag(); });

auto m_types = m.def_submodule(
"types",
"Common types used for conversion between datasets and pipelines.");
Expand Down
19 changes: 8 additions & 11 deletions cpp/bindings/pipelines/bindings.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
#pragma once

#include <pybind11/eigen.h>
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <nanobind/nanobind.h>

#include "evalio/pipeline.h"

namespace py = pybind11;
using namespace pybind11::literals;
namespace nb = nanobind;
using namespace nb::literals;

#ifdef EVALIO_KISS_ICP
#include "bindings/pipelines/kiss_icp.h"
Expand All @@ -19,20 +16,20 @@ using namespace pybind11::literals;
#endif

namespace evalio {
inline void makePipelines(py::module &m) {
inline void makePipelines(nb::module_ &m) {
// List all the pipelines here
#ifdef EVALIO_KISS_ICP
py::class_<KissICP, evalio::Pipeline>(m, "KissICP")
.def(py::init<>())
nb::class_<KissICP, evalio::Pipeline>(m, "KissICP")
.def(nb::init<>())
.def_static("name", &KissICP::name)
.def_static("url", &KissICP::url)
.def_static("default_params", &KissICP::default_params);

#endif

#ifdef EVALIO_LIO_SAM
py::class_<LioSam, evalio::Pipeline>(m, "LioSAM")
.def(py::init<>())
nb::class_<LioSam, evalio::Pipeline>(m, "LioSAM")
.def(nb::init<>())
.def_static("name", &LioSam::name)
.def_static("url", &LioSam::url)
.def_static("default_params", &LioSam::default_params);
Expand Down
59 changes: 31 additions & 28 deletions cpp/bindings/ros_pc2.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
#pragma once
#include <cmath>
#include <cstddef>
#include <pybind11/eigen.h>
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/nanobind.h>
#include <nanobind/operators.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>

#include <fstream>

#include "evalio/types.h"

namespace py = pybind11;
using namespace pybind11::literals;
namespace nb = nanobind;
using namespace nb::literals;

namespace evalio {

Expand Down Expand Up @@ -363,8 +364,8 @@ inline LidarMeasurement helipr_bin_to_evalio(const std::string &filename,
}

// ---------------------- Create python bindings ---------------------- //
inline void makeConversions(py::module &m) {
py::enum_<DataType>(m, "DataType")
inline void makeConversions(nb::module_ &m) {
nb::enum_<DataType>(m, "DataType")
.value("UINT8", DataType::UINT8)
.value("INT8", DataType::INT8)
.value("UINT16", DataType::UINT16)
Expand All @@ -374,29 +375,31 @@ inline void makeConversions(py::module &m) {
.value("FLOAT32", DataType::FLOAT32)
.value("FLOAT64", DataType::FLOAT64);

py::class_<Field>(m, "Field")
.def(py::init<std::string, DataType, uint32_t>(), py::kw_only(), "name"_a,
nb::class_<Field>(m, "Field")
.def(nb::init<std::string, DataType, uint32_t>(), nb::kw_only(), "name"_a,
"datatype"_a, "offset"_a)
.def_readwrite("name", &Field::name)
.def_readwrite("datatype", &Field::datatype)
.def_readwrite("offset", &Field::offset);
.def_rw("name", &Field::name)
.def_rw("datatype", &Field::datatype)
.def_rw("offset", &Field::offset);

py::class_<PointCloudMetadata>(m, "PointCloudMetadata")
.def(py::init<evalio::Stamp, int, int, int, int, int, int>(),
py::kw_only(), "stamp"_a, "width"_a, "height"_a, "point_step"_a,
nb::class_<PointCloudMetadata>(m, "PointCloudMetadata")
.def(nb::init<evalio::Stamp, int, int, int, int, int, int>(),
nb::kw_only(), "stamp"_a, "width"_a, "height"_a, "point_step"_a,
"row_step"_a, "is_bigendian"_a, "is_dense"_a)
.def_readwrite("stamp", &PointCloudMetadata::stamp)
.def_readwrite("width", &PointCloudMetadata::width)
.def_readwrite("height", &PointCloudMetadata::height)
.def_readwrite("point_step", &PointCloudMetadata::point_step)
.def_readwrite("row_step", &PointCloudMetadata::row_step)
.def_readwrite("is_bigendian", &PointCloudMetadata::is_bigendian)
.def_readwrite("is_dense", &PointCloudMetadata::is_dense);

m.def("pc2_to_evalio", [](const PointCloudMetadata &msg,
const std::vector<Field> &fields, char *c) {
return pc2_to_evalio(msg, fields, reinterpret_cast<uint8_t *>(c));
});
.def_rw("stamp", &PointCloudMetadata::stamp)
.def_rw("width", &PointCloudMetadata::width)
.def_rw("height", &PointCloudMetadata::height)
.def_rw("point_step", &PointCloudMetadata::point_step)
.def_rw("row_step", &PointCloudMetadata::row_step)
.def_rw("is_bigendian", &PointCloudMetadata::is_bigendian)
.def_rw("is_dense", &PointCloudMetadata::is_dense);

m.def("pc2_to_evalio",
[](const PointCloudMetadata &msg, const std::vector<Field> &fields,
nb::bytes c) -> evalio::LidarMeasurement {
return pc2_to_evalio(msg, fields,
reinterpret_cast<const uint8_t *>(c.c_str()));
});

m.def("fill_col_row_major", &fill_col_row_major);
m.def("fill_col_col_major", &fill_col_col_major);
Expand Down
Loading
Loading