Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pfernbac/curves
  • stonneau/curves
  • jchemin/curves
  • gsaurel/ndcurves
4 results
Show changes
Commits on Source (908)
Showing
with 3251 additions and 94 deletions
# pre-commit run -a (Guilhem Saurel, 2022-07-27)
ffb995161cba59619cec1b70088eb1dd7c527b37
# format (Guilhem Saurel, 2022-04-04)
1f1525de5b2ae9daef224cc8b0c4f6e12edccc12
# Format: yapf 0.32 (Guilhem Saurel, 2022-01-28)
906e28c6bbae602474778823dc2fd934dfd2c479
# format (Guilhem Saurel, 2022-01-07)
631b1a618da82af020e7b1fb2fe5662d49a32c13
# python tests: format (Guilhem Saurel, 2022-01-07)
d6a87cf82c953e89e403e2cd1ce057a768697a8c
# [Tests][Python] clean formatting (Pierre Fernbach, 2020-05-04)
810ba652943b272a3e86eb888e1fec89959fc2a3
# remove StringIO, not available in Python 3 (Guilhem Saurel, 2019-08-06)
2c88bfbe0b9775f9da51d550c352e493430d3e60
name: Build ndcurves for Mac OS X/Linux via pip
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_PARALLEL_LEVEL: 4
jobs:
ndcurves-pip:
name: "CI on ${{ matrix.os }} / python ${{ matrix.python-version }} with pip"
runs-on: "${{ matrix.os }}"
strategy:
matrix:
os: ["ubuntu-latest"] # , "macos-latest"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'
- uses: actions/setup-python@v5
with:
python-version: "${{ matrix.python-version }}"
- run: python -m pip install -U pip
- run: python -m pip install pin[build]
- run: echo "CMAKE_PREFIX_PATH=$(python -m cmeel cmake)" >> $GITHUB_ENV
- run: echo "LD_LIBRARY_PATH=$(python -m cmeel lib)" >> $GITHUB_ENV
- run: cmake -B build -S .
- run: cmake --build build
- run: cmake --build build -t test
name: "CI - Nix"
on:
push:
jobs:
nix:
runs-on: "${{ matrix.os }}-latest"
strategy:
matrix:
os: [ubuntu, macos]
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v27
- uses: cachix/cachix-action@v15
with:
name: gepetto
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix build -L
# Build and Release Folders
bin/
lib/
build/
build-rel/
# temp files
.*~
*.user
*.pyc
*.ipynb_checkpoints
include: http://rainboard.laas.fr/project/ndcurves/.gitlab-ci.yml
pull_request_rules:
- name: merge automatically when CI passes and PR is approved
conditions:
- check-success = "CI on ubuntu-latest / python 3.8 with pip"
- check-success = "CI on ubuntu-latest / python 3.9 with pip"
- check-success = "CI on ubuntu-latest / python 3.10 with pip"
- check-success = "CI on ubuntu-latest / python 3.11 with pip"
- check-success = "CI on ubuntu-latest / python 3.12 with pip"
- check-success = "gitlab-ci"
- check-success = "nix (macos)"
- check-success = "nix (ubuntu)"
- check-success = "pre-commit.ci - pr"
- or:
- author = pre-commit-ci[bot]
- author = dependabot[bot]
actions:
merge:
ci:
autoupdate_branch: devel
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.2
hooks:
- id: ruff
args:
- --fix
- --exit-non-zero-on-fix
- id: ruff-format
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: v0.6.13
hooks:
- id: cmake-format
- repo: https://github.com/pappasam/toml-sort
rev: v0.24.2
hooks:
- id: toml-sort-fix
exclude: poetry.lock
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v19.1.4
hooks:
- id: clang-format
args:
- --style=Google
exclude: python/test/sandbox/test.ipynb
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-added-large-files
- id: check-ast
- id: check-executables-have-shebangs
- id: check-json
- id: check-merge-conflict
- id: check-symlinks
- id: check-toml
- id: check-yaml
- id: debug-statements
- id: destroyed-symlinks
- id: detect-private-key
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: trailing-whitespace
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [2.0.0] - 2024-12-05
- :warning: BREAKING: switch from boost smart pointers to std ones
- setup nix
- setup mergify
## [1.4.1] - 2024-04-12
- tests: fix use of np.random in tests
- CMake: enable python bindings by default
## [1.4.0] - 2024-04-12
- Add a SO3 curves which is C2. It's called S03Smooth
- Add some typedef on using 3D curves.
- Fix typos around the package
- Add some tests on polynomials and the new structs.
- update tooling
- update packaging
- add pip CI
## [1.3.1] - 2023-11-29
### Changed
- ⚠️ require CMake 3.10 ⚠️
### Added
- python: define CopyableVisitor, fix SerializableVisitor and use them
### Fixed
- cmake generation on macosx
- Supporting pinocchio installed with cppad (#108)
- fix E721
## [1.3.0] - 2023-07-19
- add stubs support
- fix RPATH for OSX
## [1.2.0] - 2023-05-13
- [python] Enabled support to copy and deepcopy
- [python] Removed deprecated macros in eigenpy
- update for eigenpy v3
- pre-commit update
- sync submodule
- CMake: fetch submodule, set default build type, bump standard
## [1.1.6] - 2023-01-24
- don't build python bindings by default, to be more gentle with PAL robotics buildfarm.
## [1.1.5] - 2022-08-29
- fix allocator
- modernize cmake
## [1.1.4] - 2022-06-29
- remove unary function, deprecated since C++11 and removed in C++17
## [1.1.3] - 2022-05-31
## [1.1.2] - 2022-02-09
- [cmake] Improve Eigen detection/usage
- fix format
## [1.1.1] - 2022-01-06
- fix virtual functions
- fix optional dependency to pinocchio
- primitive now accept initial value\n
## [1.1.0] - 2021-05-03
- make dependency on pinocchio not mandatory
- fix link to Boost::serialization
- use eigen matrix serialization from pinocchio >= 2.6.0 if available
- export -DCURVES_WITH_PINOCCHIO_SUPPORT
## [1.0.0] - 2021-03-18
- ⚠️ library renamed from curves to ndcurves ⚠️
- added arithmetic operations on curves
## [0.5.2] - 2020-09-24
- fix CMake for fedora
## [0.5.1] - 2020-07-27
- fix serialization versioning
## [0.5.0] - 2020-07-25
- Add piecewise::load_from_text_file
- New curves type required by sot-talos-balance
- Use Bezier formulation for cubic hermite
- Check input degree before converting curve to bezier or hermite
- remove cubic and quintic classes
## [0.4.1] - 2020-04-02
Changes since v0.4.0:
- [CMake] fix pinocchio detection
- [CMake] export CURVES_WITH_PINOCCHIO_SUPPORT
## [0.4.0] - 2020-03-30
Changes since v0.3.3:
- [Python] Add pickle support
- Add serialization/curves header
## [0.3.3] - 2020-03-11
Changes since v0.3.2:
- CMake Exports
## [0.3.2] - 2020-02-13
Changes since v0.3.1:
- [Python] Fix binding of Piecewise.curve_at_index
- Replace several critical asserts with exceptions
- Install the header python_definitions.h in include/python
- Add python API to retrieve bezier waypoints as 2D array
- Add C++ and python API to retrieve the translation or rotation curve contained in a SE3 curve
- Correctly specify the corresponding shared_pointer to all python class
- Fix SO3 constructors when t_min == t_max
- Correctly check and raise error when trying to use polynomial constructors from boundary condition when t_min == t_max
- Reworking of the exposition of the abstract class in Python (fix https://gepgitlab.laas.fr/loco-3d/curves/issues/32)
- Correctly register the shared_pointer of the base abstract classes in boost::Python
## [0.3.1] - 2020-02-13
Changes since v0.3.0:
- [CMake] add INSTALL_PYTHON_INTERFACE_ONLY option
- Update README
## [0.3.0] - 2020-01-10
Changes since v0.2.0:
- [CMake] update minimal eigenpy version
- Add operator == and != for all curves
- Add methods isApprox() and isEquivalent() to all curves
- Fix optional dependency to pinocchio for python bindings
- [Python][Tests] remove all unecessary reshape(-1,1) in python
- Rework the class piecewise_curve to make it generic and remove the need to specify the type of curve used as a template argument, can now mix any kind of curves inside
- Rework the methods convert_to_X_from_Y to convert_to_X and remove the need to specify the input type as template argument
- Add compute_derivate_ptr() method to curve_abc and implement it in all child classes
- Add degree() method to curve_abc and implement it in all child class
- Factorize the most commonly used typedef with template argument in fwd.h
- [Python] correctly define eigenpy matrix type for point3 and point6
- [CMake] fix hardcoded path
- [CMake] fix install path of optimization files
- [Tests][Python] use Quaternion.isApprox to test equality instead of ==
- Add SE3 with pinocchio
- Add conversion functions from piecewise curve to python bindings
- Optimization
- Fix all compiler warnings
- Export plot
## [0.2.0] - 2019-10-04
- Initial release
[Unreleased]: https://github.com/loco-3d/ndcurves/compare/v2.0.0...HEAD
[2.0.0]: https://github.com/loco-3d/ndcurves/compare/v1.4.1...v2.0.0
[1.4.1]: https://github.com/loco-3d/ndcurves/compare/v1.4.0...v1.4.1
[1.4.0]: https://github.com/loco-3d/ndcurves/compare/v1.3.1...v1.4.0
[1.3.1]: https://github.com/loco-3d/ndcurves/compare/v1.3.0...v1.3.1
[1.3.0]: https://github.com/loco-3d/ndcurves/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/loco-3d/ndcurves/compare/v1.1.6...v1.2.0
[1.1.6]: https://github.com/loco-3d/ndcurves/compare/v1.1.5...v1.1.6
[1.1.5]: https://github.com/loco-3d/ndcurves/compare/v1.1.4...v1.1.5
[1.1.4]: https://github.com/loco-3d/ndcurves/compare/v1.1.3...v1.1.4
[1.1.3]: https://github.com/loco-3d/ndcurves/compare/v1.1.2...v1.1.3
[1.1.2]: https://github.com/loco-3d/ndcurves/compare/v1.1.1...v1.1.2
[1.1.1]: https://github.com/loco-3d/ndcurves/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/loco-3d/ndcurves/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/loco-3d/ndcurves/compare/v0.5.2...v1.0.0
[0.5.2]: https://github.com/loco-3d/ndcurves/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/loco-3d/ndcurves/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/loco-3d/ndcurves/compare/v0.4.1...v0.5.0
[0.4.1]: https://github.com/loco-3d/ndcurves/compare/v0.4.0...v0.4.1
[0.4.0]: https://github.com/loco-3d/ndcurves/compare/v0.3.3...v0.4.0
[0.3.3]: https://github.com/loco-3d/ndcurves/compare/v0.3.2...v0.3.3
[0.3.2]: https://github.com/loco-3d/ndcurves/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/loco-3d/ndcurves/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/loco-3d/ndcurves/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/loco-3d/ndcurves/releases/tag/v0.2.0
cmake_minimum_required(VERSION 2.6)
project(spline)
INCLUDE(cmake/base.cmake)
INCLUDE(cmake/python.cmake)
cmake_minimum_required(VERSION 3.10)
SET(PROJECT_NAME spline)
SET(PROJECT_DESCRIPTION
"template based classes for creating and manipulating spline and bezier curves. Comes with extra options specific to end-effector trajectories in robotics."
)
SET(PROJECT_URL "")
# Project properties
set(PROJECT_ORG loco-3d)
set(PROJECT_NAME ndcurves)
set(PROJECT_DESCRIPTION "creatie and manipulate spline and bezier curves.")
set(PROJECT_URL "https://github.com/${PROJECT_ORG}/${PROJECT_NAME}")
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/build/")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/")
set(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib/")
# Disable -Werror on Unix for now.
SET(CXX_DISABLE_WERROR True)
SET(CMAKE_VERBOSE_MAKEFILE True)
# Project options
option(BUILD_PYTHON_INTERFACE "Build the python bindings" ON)
option(INSTALL_PYTHON_INTERFACE_ONLY "Install *ONLY* the python bindings" OFF)
option(SUFFIX_SO_VERSION "Suffix library name with its version" ON)
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
# Project configuration
if(NOT INSTALL_PYTHON_INTERFACE_ONLY)
set(PROJECT_USE_CMAKE_EXPORT TRUE)
endif(NOT INSTALL_PYTHON_INTERFACE_ONLY)
set(CXX_DISABLE_WERROR TRUE)
SETUP_PROJECT()
# JRL-cmakemodule setup
set(JRL_CMAKE_MODULES "${CMAKE_CURRENT_LIST_DIR}/cmake")
if(EXISTS "${JRL_CMAKE_MODULES}/base.cmake")
message(STATUS "JRL cmakemodules found in 'cmake/' git submodule")
else()
find_package(jrl-cmakemodules QUIET CONFIG)
if(jrl-cmakemodules_FOUND)
get_property(
JRL_CMAKE_MODULES
TARGET jrl-cmakemodules::jrl-cmakemodules
PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
message(STATUS "JRL cmakemodules found on system at ${JRL_CMAKE_MODULES}")
elseif(${CMAKE_VERSION} VERSION_LESS "3.14.0")
message(
FATAL_ERROR
"\nCan't find jrl-cmakemodules. Please either:\n"
" - use git submodule: 'git submodule update --init'\n"
" - or install https://github.com/jrl-umi3218/jrl-cmakemodules\n"
" - or upgrade your CMake version to >= 3.14 to allow automatic fetching\n"
)
else()
message(STATUS "JRL cmakemodules not found. Let's fetch it.")
include(FetchContent)
FetchContent_Declare(
"jrl-cmakemodules"
GIT_REPOSITORY "https://github.com/jrl-umi3218/jrl-cmakemodules.git")
FetchContent_MakeAvailable("jrl-cmakemodules")
FetchContent_GetProperties("jrl-cmakemodules" SOURCE_DIR JRL_CMAKE_MODULES)
endif()
endif()
OPTION (BUILD_PYTHON_INTERFACE "Build the python binding" ON)
IF(BUILD_PYTHON_INTERFACE)
# search for python
FINDPYTHON(2.7 REQUIRED)
find_package( PythonLibs 2.7 REQUIRED )
include_directories( ${PYTHON_INCLUDE_DIRS} )
include("${JRL_CMAKE_MODULES}/base.cmake")
include("${JRL_CMAKE_MODULES}/boost.cmake")
include(CMakeDependentOption)
find_package( Boost COMPONENTS python REQUIRED )
include_directories( ${Boost_INCLUDE_DIR} )
cmake_dependent_option(
GENERATE_PYTHON_STUBS
"Generate the Python stubs associated to the Python library" OFF
BUILD_PYTHON_INTERFACE ON)
add_subdirectory (python)
set_default_cmake_build_type("Release")
ENDIF(BUILD_PYTHON_INTERFACE)
# Project definition
compute_project_args(PROJECT_ARGS LANGUAGES CXX)
project(${PROJECT_NAME} ${PROJECT_ARGS})
check_minimal_cxx_standard(14 ENFORCE)
add_subdirectory (src/tests/spline_test)
# Project dependencies
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/find-external/CppAD/"
${CMAKE_MODULE_PATH})
find_package(Eigen3 QUIET NO_CMAKE_PACKAGE_REGISTRY)
if(Eigen3_FOUND)
add_project_dependency(Eigen3 REQUIRED NO_CMAKE_PACKAGE_REGISTRY
PKG_CONFIG_REQUIRES eigen3)
else(Eigen3_FOUND)
add_project_dependency(Eigen3 MODULE REQUIRED PKG_CONFIG_REQUIRES eigen3)
endif(Eigen3_FOUND)
find_package(pinocchio QUIET)
option(CURVES_WITH_PINOCCHIO_SUPPORT "Build with pinocchio support"
${pinocchio_FOUND})
if(CURVES_WITH_PINOCCHIO_SUPPORT)
if(NOT pinocchio_FOUND)
message(
FATAL_ERROR
"CURVES_WITH_PINOCCHIO_SUPPORT selected, but pinocchio has not been found"
)
endif(NOT pinocchio_FOUND)
add_project_dependency(pinocchio REQUIRED PKG_CONFIG_REQUIRES)
pkg_config_append_cflags("-DCURVES_WITH_PINOCCHIO_SUPPORT")
endif(CURVES_WITH_PINOCCHIO_SUPPORT)
set(PACKAGE_EXTRA_MACROS
"SET(CURVES_WITH_PINOCCHIO_SUPPORT ${CURVES_WITH_PINOCCHIO_SUPPORT})")
add_project_dependency(Boost REQUIRED COMPONENTS serialization)
SETUP_PROJECT_FINALIZE()
if(BUILD_PYTHON_INTERFACE)
add_project_dependency(eigenpy 3.0.0 REQUIRED PKG_CONFIG_REQUIRES
"eigenpy >= 3.0.0")
endif(BUILD_PYTHON_INTERFACE)
# Main Library
set(${PROJECT_NAME}_HEADERS
include/${PROJECT_NAME}/bernstein.h
include/${PROJECT_NAME}/bezier_curve.h
include/${PROJECT_NAME}/constant_curve.h
include/${PROJECT_NAME}/cross_implementation.h
include/${PROJECT_NAME}/cubic_hermite_spline.h
include/${PROJECT_NAME}/curve_abc.h
include/${PROJECT_NAME}/curve_constraint.h
include/${PROJECT_NAME}/curve_conversion.h
include/${PROJECT_NAME}/exact_cubic.h
include/${PROJECT_NAME}/fwd.h
include/${PROJECT_NAME}/helpers/effector_spline.h
include/${PROJECT_NAME}/helpers/effector_spline_rotation.h
include/${PROJECT_NAME}/linear_variable.h
include/${PROJECT_NAME}/MathDefs.h
include/${PROJECT_NAME}/optimization/definitions.h
include/${PROJECT_NAME}/optimization/details.h
include/${PROJECT_NAME}/optimization/integral_cost.h
include/${PROJECT_NAME}/optimization/quadratic_problem.h
include/${PROJECT_NAME}/piecewise_curve.h
include/${PROJECT_NAME}/polynomial.h
include/${PROJECT_NAME}/python/python_definitions.h
include/${PROJECT_NAME}/quadratic_variable.h
include/${PROJECT_NAME}/se3_curve.h
include/${PROJECT_NAME}/serialization/archive.hpp
include/${PROJECT_NAME}/serialization/curves.hpp
include/${PROJECT_NAME}/serialization/eigen-matrix.hpp
include/${PROJECT_NAME}/serialization/registeration.hpp
include/${PROJECT_NAME}/sinusoidal.h
include/${PROJECT_NAME}/so3_linear.h
include/${PROJECT_NAME}/so3_smooth.h)
add_library(${PROJECT_NAME} INTERFACE)
modernize_target_link_libraries(
${PROJECT_NAME}
SCOPE
INTERFACE
TARGETS
Eigen3::Eigen
INCLUDE_DIRS
${EIGEN3_INCLUDE_DIR})
target_include_directories(
${PROJECT_NAME} INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_link_libraries(${PROJECT_NAME} INTERFACE Boost::serialization)
if(CURVES_WITH_PINOCCHIO_SUPPORT)
target_link_libraries(${PROJECT_NAME} INTERFACE pinocchio::pinocchio)
target_compile_definitions(${PROJECT_NAME}
INTERFACE -DCURVES_WITH_PINOCCHIO_SUPPORT)
endif(CURVES_WITH_PINOCCHIO_SUPPORT)
if(NOT INSTALL_PYTHON_INTERFACE_ONLY)
install(
TARGETS ${PROJECT_NAME}
EXPORT ${TARGETS_EXPORT_NAME}
DESTINATION lib)
install(FILES package.xml DESTINATION share/${PROJECT_NAME})
endif(NOT INSTALL_PYTHON_INTERFACE_ONLY)
if(BUILD_PYTHON_INTERFACE)
add_subdirectory(python)
endif(BUILD_PYTHON_INTERFACE)
add_subdirectory(tests)
Spline
===================
# NDCurves
[![Pipeline status](https://gitlab.laas.fr/loco-3d/ndcurves/badges/master/pipeline.svg)](https://gitlab.laas.fr/loco-3d/ndcurves/commits/master)
[![Coverage report](https://gitlab.laas.fr/loco-3d/ndcurves/badges/master/coverage.svg?job=doc-coverage)](https://gepettoweb.laas.fr/doc/loco-3d/ndcurves/master/coverage/)
[![PyPI version](https://badge.fury.io/py/ndcurves.svg)](https://pypi.org/project/ndcurves)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/loco-3d/ndcurves/master.svg)](https://results.pre-commit.ci/latest/github/loco-3d/ndcurves)
A template-based Library for creating curves of arbitrary order and dimension, eventually subject to derivative constraints. The main use of the library is the creation of end-effector trajectories for legged robots.
To do so, tools are provided to:
> - create **exact** splines of arbitrary order (that pass exactly by an arbitrary number waypoints)
> - constrain initial / end velocities and acceleration for the spline.
> - constrain take-off and landing phases to follow a straight line along a given normal (to avoid undesired collisions between the effector and the contact surface)
> - automatically handle 3d rotation of the effector.
- create **exact** splines of arbitrary order (that pass exactly by an arbitrary number waypoints)
- constrain initial / end velocities and acceleration for the spline.
- constrain take-off and landing phases to follow a straight line along a given normal (to avoid undesired collisions between the effector and the contact surface)
- automatically handle 3d rotation of the effector.
- create curves in SO3
- support partial symbolic differentiation of curves. You can represent control points as linear variables, and integrate / differentiate those variable curves. You can also compute the cross product of two curves, which is relevant for centroidal dynamics.
Several type of formulation are provided:
- Polynomials
- Bezier
- Hermite (only cubic hermite for now)
The library is template-based, thus generic: the curves can be of any dimension, and can be implemented in double or float and can work with kind variables like Vector, Transform, Matrix, ...
## Installation
### Installation through robotpkg
The library is template-based, thus generic: the curves can be of any dimension, and can be implemented in double, float ...
You can install this package through robotpkg. robotpkg is a package manager tailored for robotics softwares.
It greatly simplifies the release of new versions along with the management of their dependencies.
You just need to add the robotpkg apt repository to your sources.list and then use `sudo apt install robotpkg-py3\*-ndcurves`.
While a Bezier curve implementation is provided, the main interest
of this library is to create spline curves of arbitrary order
If you have never added robotpkg as a softwares repository, please follow first the instructions from 1 to 3; otherwise, go directly to instruction 4.
Those instructions are similar to the installation procedures presented in [http://robotpkg.openrobots.org/debian.html](http://robotpkg.openrobots.org/debian.html).
----------
Example of use for and end-effector trajectory
-------------
The library comes with an helper class to automatically generate end-effector trajectories.
For instance, to create a 2 second long trajectory from the point (0,0,0) to (1,1,0), with a waypoint
at (0.5,0.5,0.5), one can use the following code:
1. Add robotpkg as source repository to apt:
```bash
sudo tee /etc/apt/sources.list.d/robotpkg.list <<EOF
deb [arch=amd64] http://robotpkg.openrobots.org/wip/packages/debian/pub $(lsb_release -sc) robotpkg
deb [arch=amd64] http://robotpkg.openrobots.org/packages/debian/pub $(lsb_release -sc) robotpkg
EOF
```
typedef std::pair<double, Eigen::Vector3d> Waypoint;
typedef std::vector<Waypoint> T_Waypoint;
// loading helper class namespace
using namespace spline::helpers;
2. Register the authentication certificate of robotpkg:
// Create waypoints
waypoints.push_back(std::make_pair(0., Eigen::Vector3d(0,0,0)));
waypoints.push_back(std::make_pair(1., Eigen::Vector3d(0.5,0.5,0.5)));
waypoints.push_back(std::make_pair(2., Eigen::Vector3d(1,1,0)));
```bash
curl http://robotpkg.openrobots.org/packages/debian/robotpkg.key | sudo apt-key add -
```
exact_cubic_t* eff_traj = effector_spline(waypoints.begin(),waypoints.end());
3. You need to run at least once apt update to fetch the package descriptions:
// evaluate spline
(*eff_traj)(0.); // (0,0,0)
(*eff_traj)(2.); // (1,1,0)
```bash
sudo apt-get update
```
If rotation of the effector must be considered, the code is almost the same:
4. The installation of nd-curves:
```bash
sudo apt install robotpkg-py3\*-ndcurves # for Python 3
sudo apt install robotpkg-py27-ndcurves # for Python 2
```
// initial rotation is 0, end rotation is a rotation by Pi around x axis
quat_t init_rot(0,0,0,1), end_rot(1,0,0,0);
effector_spline_rotation eff_traj_rot(waypoints.begin(),waypoints.end(), init_quat, end_quat);
// evaluate spline
eff_traj_rot(0.); // (0,0,0,0,0,0,1)
eff_traj_rot(1.); // (0.5,0.5,0.5,0.707107,0,0,0.707107) // Pi/2 around x axis
eff_traj_rot(2.); // (0,0,0,1,0,0,0)
Finally you will need to configure your environment variables, e.g.:
```bash
export PATH=/opt/openrobots/bin:$PATH
export PKG_CONFIG_PATH=/opt/openrobots/lib/pkgconfig:$PKG_CONFIG_PATH
export LD_LIBRARY_PATH=/opt/openrobots/lib:$LD_LIBRARY_PATH
export PYTHONPATH=/opt/openrobots/lib/python2.7/site-packages:$PYTHONPATH
```
Additional parameters for the same methods an be used to specify parameters for the take off and
landing phases: height and duration of the phase, and along which normal.
Please refer to the Main.cpp files to see all the unit tests and possibilities offered by the library
### Installation from source
Installation
-------------
## Dependencies
#### Dependencies
* [Eigen (version >= 3.2.2)](http://eigen.tuxfamily.org/index.php?title=Main_Page)
## Additional dependencies for python bindings
#### Additional dependencies for python bindings
* [Boost.Python](http://www.boost.org/doc/libs/1_63_0/libs/python/doc/html/index.html)
* [eigenpy](https://github.com/stack-of-tasks/eigenpy)
To handle this with cmake, use the recursive option to clone the repository.
For instance, using http:
```
git clone --recursive https://github.com/stonneau/spline.git $SPLINE_DIR
git clone --recursive https://github.com/loco-3d/ndcurves $NDCURVES_DIR
```
Where $NDCURVES_DIR is to be replaced to your selected source folder.
The library is header only, so the build only serves to build the tests and python bindings:
```sh
cd $NDCURVES_DIR && mkdir build && cd build
cmake -DBUILD_PYTHON_INTERFACE=ON .. && make && make test
```
cd $SPLINE_DIR && mkdir build && cd build
cmake .. && make
../bin/tests
```
Switch the BUILD_PYTHON argument to OFF if you don't want to use the python bindings of the package.
If everything went fine you should obtain the following output:
```sh
100% tests passed, 0 tests failed out of 3
```
performing tests...
no errors found
```
### Optional: Python bindings installation
To install the Python bindings, in the CMakeLists.txt file, first enable the BUILD_PYTHON_INTERFACE option:
#### Optional: Python bindings installation
To install the Python bindings first enable the `BUILD_PYTHON_INTERFACE` option:
```
OPTION (BUILD_PYTHON_INTERFACE "Build the python binding" ON)
cmake -DBUILD_PYTHON_INTERFACE=ON ..
```
Then rebuild the library:
```
cd $SPLINE_DIR/build
cmake -DCMAKE_INSTALL_PREFIX=${DEVEL_DIR}/install ..
make install
cd ${NDCURVES_DIR}/build
make && make test
```
The python bindings should then be accessible through the package centroidal_dynamics.
To see example of use, you can refer to the [test file](https://github.com/stonneau/spline/blob/master/python/test/test.py)
To see example of use, you can refer to the [test file](https://github.com/loco-3d/ndcurves/blob/master/python/test/test.py)
which is rather self explanatory:
In spite of an exhaustive documentation, please refer to the C++ documentation, which mostly applies
to python. For the moment, only bezier curves are binded.
In spite of an exhaustive documentation, please refer to the C++ documentation, which mostly applies to python.
## Documentation and tutorial
For the C++ / Python detailed documentation, you can consult [this pdf](https://github.com/loco-3d/ndcurves/blob/devel/doc/curves.pdf) available in the doc folder
For a python tutorial, you can refer to the [jupyter notebook](https://github.com/loco-3d/ndcurves/blob/master/python/test/sandbox/test.ipynb).
The [test file](https://github.com/loco-3d/ndcurves/blob/master/python/test/test.py) is more exhaustive and rather self explanatory.
## Citation
If you wish to cite this work please use the bibtex below:
```bib
@software{ndcurves,
author = {Tonneau, Steve and Chemin, Jason and Fernbach, Pierre and Saurel, Guilhem},
title = {ndcurves},
url = {https://github.com/loco-3d/ndcurves},
year = {2013}
}
```
Subproject commit 7b0b47cae2b082521ad674c8ee575f594f483cd7
Subproject commit 29c0eb4e659304f44d55a0389e2749812d858659
File added
This diff is collapsed.
doc/source/images/De_Casteljau_construction.png

34.7 KiB

{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1733312601,
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1733380312,
"narHash": "sha256-ywntxT10Om755wkB9tYgJwEwELQZKYAO5WcNuHv1vjI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a772498086eac57d97065a980a21fc0f304e3192",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1733096140,
"narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
{
description = "Library for creating smooth cubic splines";
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = inputs.nixpkgs.lib.systems.flakeExposed;
perSystem =
{ pkgs, self', ... }:
{
apps.default = {
type = "app";
program = pkgs.python3.withPackages (_: [ self'.packages.default ]);
};
devShells.default = pkgs.mkShell { inputsFrom = [ self'.packages.default ]; };
packages = {
default = self'.packages.ndcurves;
ndcurves = pkgs.python3Packages.ndcurves.overrideAttrs (_: {
src = pkgs.lib.fileset.toSource {
root = ./.;
fileset = pkgs.lib.fileset.unions [
./CMakeLists.txt
./doc
./include
./package.xml
./python
./tests
];
};
});
};
};
};
}
/**
* \file Math.h
* \brief Linear algebra and other maths definitions. Based on Eigen 3 or more
* \author Steve T.
* \version 0.1
* \date 06/17/2013
*
* This file contains math definitions used
* used throughout the library.
* Preprocessors definition are used to use eitheir float
* or double values, and 3 dimensional vectors for
* the Point structure.
*/
#ifndef _SPLINEMATH
#define _SPLINEMATH
#include <Eigen/Dense>
#include <Eigen/SVD>
#include <utility>
#include <vector>
namespace ndcurves {
/// \brief An inverse kinematics architecture enforcing an arbitrary number of
/// strict priority levels (Reference : Boulic et Al. 2003)
template <typename _Matrix_Type_>
void PseudoInverse(_Matrix_Type_& pinvmat) {
Eigen::JacobiSVD<_Matrix_Type_> svd(
pinvmat, Eigen::ComputeFullU | Eigen::ComputeFullV);
_Matrix_Type_ m_sigma = svd.singularValues();
double pinvtoler = 1.e-6; // choose your tolerance widely!
_Matrix_Type_ m_sigma_inv =
_Matrix_Type_::Zero(pinvmat.cols(), pinvmat.rows());
for (long i = 0; i < m_sigma.rows(); ++i) {
if (m_sigma(i) > pinvtoler) {
m_sigma_inv(i, i) = 1.0 / m_sigma(i);
}
}
pinvmat = (svd.matrixV() * m_sigma_inv * svd.matrixU().transpose());
}
template <typename Matrix3, typename Point>
Matrix3 skew(const Point& x) {
Matrix3 res = Matrix3::Zero(3, 3);
res(0, 1) = -x(2);
res(0, 2) = x(1);
res(1, 0) = x(2);
res(1, 2) = -x(0);
res(2, 0) = -x(1);
res(2, 1) = x(0);
return res;
}
static const double MARGIN(0.001);
} // namespace ndcurves
#endif //_SPLINEMATH
/**
* \file bezier_curve.h
* \brief class allowing to create a Bezier curve of dimension 1 <= n <= 3.
* \author Steve T.
* \version 0.1
* \date 06/17/2013
*/
#ifndef _CLASS_BERNSTEIN
#define _CLASS_BERNSTEIN
#include <math.h>
#include <stdexcept>
#include <vector>
#include "MathDefs.h"
#include "curve_abc.h"
namespace ndcurves {
/// \brief Computes a binomial coefficient .
/// \param n : an unsigned integer.
/// \param k : an unsigned integer.
/// \return \f$\binom{n}{k}f$
///
inline unsigned int bin(const unsigned int n, const unsigned int k) {
if (k > n)
throw std::runtime_error("binomial coefficient higher than degree");
if (k == 0) return 1;
if (k > n / 2) return bin(n, n - k);
return n * bin(n - 1, k - 1) / k;
}
/// \class Bernstein.
/// \brief Computes a Bernstein polynomial.
///
template <typename Numeric = double>
struct Bern {
Bern() {}
Bern(const unsigned int m, const unsigned int i)
: m_minus_i(m - i), i_(i), bin_m_i_(bin(m, i)) {}
virtual ~Bern() {}
/// \brief Evaluation of Bernstein polynomial at value u.
/// \param u : value between 0 and 1.
/// \return Evaluation corresponding at value u.
Numeric operator()(const Numeric u) const {
if (!(u >= 0. && u <= 1.)) {
throw std::invalid_argument("u needs to be betwen 0 and 1.");
}
return bin_m_i_ * (pow(u, i_))*pow((1 - u), m_minus_i);
}
/// \brief Check if actual Bernstein polynomial and other are approximately
/// equal. \param other : the other Bernstein polynomial to check. \return
/// true if the two Bernstein polynomials are approximately equals.
virtual bool operator==(const Bern& other) const {
return ndcurves::isApprox<Numeric>(m_minus_i, other.m_minus_i) &&
ndcurves::isApprox<Numeric>(i_, other.i_) &&
ndcurves::isApprox<Numeric>(bin_m_i_, other.bin_m_i_);
}
/// \brief Check if actual Bernstein polynomial and other are different.
/// \param other : the other Bernstein polynomial to check.
/// \return true if the two Bernstein polynomials are different.
virtual bool operator!=(const Bern& other) const { return !(*this == other); }
/* Attributes */
Numeric m_minus_i;
Numeric i_;
Numeric bin_m_i_;
/* Attributes */
// Serialization of the class
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int version) {
if (version) {
// Do something depending on version ?
}
ar& boost::serialization::make_nvp("m_minus_i", m_minus_i);
ar& boost::serialization::make_nvp("i", i_);
ar& boost::serialization::make_nvp("bin_m_i", bin_m_i_);
}
}; // End struct Bern
/// \brief Computes all Bernstein polynomes for a certain degree.
///
template <typename Numeric>
std::vector<Bern<Numeric> > makeBernstein(const unsigned int n) {
std::vector<Bern<Numeric> > res;
for (unsigned int i = 0; i <= n; ++i) {
res.push_back(Bern<Numeric>(n, i));
}
return res;
}
} // namespace ndcurves
DEFINE_CLASS_TEMPLATE_VERSION(typename Numeric, ndcurves::Bern<Numeric>)
#endif //_CLASS_BERNSTEIN
This diff is collapsed.
/**
* \file constant_curve.h
* \brief class allowing to create a constant_curve curve.
* \author Pierre Fernbach
* \version 0.4
* \date 29/04/2020
*/
#ifndef _CLASS_CONSTANTCURVE
#define _CLASS_CONSTANTCURVE
#include "curve_abc.h"
namespace ndcurves {
/// \class constant_curve.
/// \brief Represents a constant_curve curve, always returning the same value
/// and a null derivative
///
template <typename Time = double, typename Numeric = Time, bool Safe = false,
typename Point = Eigen::Matrix<Numeric, Eigen::Dynamic, 1>,
typename Point_derivate = Point>
struct constant_curve
: public curve_abc<Time, Numeric, Safe, Point, Point_derivate> {
typedef Point point_t;
typedef Point_derivate point_derivate_t;
typedef Time time_t;
typedef Numeric num_t;
typedef constant_curve<Time, Numeric, Safe, Point, Point_derivate>
constant_curve_t;
typedef constant_curve<Time, Numeric, Safe, Point_derivate> curve_derivate_t;
typedef curve_abc<Time, Numeric, Safe, point_t, Point_derivate>
curve_abc_t; // parent class
/* Constructors - destructors */
public:
/// \brief Empty constructor. Curve obtained this way can not perform other
/// class functions.
///
constant_curve() : T_min_(0), T_max_(0), dim_(0) {}
/// \brief Constructor..
/// \param value : The constant value
/// \param T_min : lower bound of the time interval
/// \param T_max : upper bound of the time interval
///
constant_curve(const Point& value, const time_t T_min = 0.,
const time_t T_max = std::numeric_limits<time_t>::max())
: value_(value), T_min_(T_min), T_max_(T_max), dim_(value.size()) {
if (Safe && T_min_ > T_max_) {
throw std::invalid_argument(
"can't create constant curve: min bound is higher than max bound");
}
}
/// \brief Copy constructor
/// \param other
constant_curve(const constant_curve_t& other)
: value_(other.value_),
T_min_(other.T_min_),
T_max_(other.T_max_),
dim_(other.dim_) {}
/// \brief Destructor.
virtual ~constant_curve() {}
/* Constructors - destructors */
/*Operations*/
/// \brief Evaluation of the cubic spline at time t.
/// \param t : time when to evaluate the spine
/// \return \f$x(t)\f$, point corresponding on curve at time t.
virtual point_t operator()(const time_t t) const {
if (Safe && (t < T_min_ || t > T_max_)) {
throw std::invalid_argument(
"error in constant curve : time t to evaluate should be in range "
"[Tmin, Tmax] of the curve");
}
return value_;
}
/// \brief Compute the derived curve at order N.
/// Computes the derivative order N, \f$\frac{d^Nx(t)}{dt^N}\f$ of bezier
/// curve of parametric equation x(t). \param order : order of derivative.
/// \return \f$\frac{d^Nx(t)}{dt^N}\f$ derivative order N of the curve.
curve_derivate_t compute_derivate() const {
size_t derivate_size;
if (point_derivate_t::RowsAtCompileTime == Eigen::Dynamic) {
derivate_size = dim_;
} else {
derivate_size = point_derivate_t::RowsAtCompileTime;
}
point_derivate_t value(point_derivate_t::Zero(derivate_size));
return curve_derivate_t(value, T_min_, T_max_);
}
/// \brief Compute the derived curve at order N.
/// \param order : order of derivative.
/// \return A pointer to \f$\frac{d^Nx(t)}{dt^N}\f$ derivative order N of the
/// curve.
virtual curve_derivate_t* compute_derivate_ptr(const std::size_t) const {
return new curve_derivate_t(compute_derivate());
}
/// \brief Evaluate the derivative of order N of curve at time t.
/// \param t : time when to evaluate the spline.
/// \param order : order of derivative.
/// \return \f$\frac{d^Nx(t)}{dt^N}\f$, point corresponding on derivative
/// curve of order N at time t.
virtual point_derivate_t derivate(const time_t t, const std::size_t) const {
if (Safe && (t < T_min_ || t > T_max_)) {
throw std::invalid_argument(
"error in constant curve : time t to derivate should be in range "
"[Tmin, Tmax] of the curve");
}
size_t derivate_size;
if (point_derivate_t::RowsAtCompileTime == Eigen::Dynamic) {
derivate_size = dim_;
} else {
derivate_size = point_derivate_t::RowsAtCompileTime;
}
return point_derivate_t::Zero(derivate_size);
}
/**
* @brief isApprox check if other and *this are approximately equals given a
* precision threshold Only two curves of the same class can be approximately
* equals, for comparison between different type of curves see isEquivalent.
* @param other the other curve to check
* @param prec the precision threshold, default
* Eigen::NumTraits<Numeric>::dummy_precision()
* @return true is the two curves are approximately equals
*/
virtual bool isApprox(
const constant_curve_t& other,
const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision()) const {
return ndcurves::isApprox<num_t>(T_min_, other.min()) &&
ndcurves::isApprox<num_t>(T_max_, other.max()) &&
dim_ == other.dim() && value_.isApprox(other.value_, prec);
}
virtual bool isApprox(
const curve_abc_t* other,
const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision()) const {
const constant_curve_t* other_cast =
dynamic_cast<const constant_curve_t*>(other);
if (other_cast)
return isApprox(*other_cast, prec);
else
return false;
}
virtual bool operator==(const constant_curve_t& other) const {
return isApprox(other);
}
virtual bool operator!=(const constant_curve_t& other) const {
return !(*this == other);
}
/*Helpers*/
/// \brief Get dimension of curve.
/// \return dimension of curve.
std::size_t virtual dim() const { return dim_; }
/// \brief Get the minimum time for which the curve is defined
/// \return \f$t_{min}\f$ lower bound of time range.
num_t virtual min() const { return T_min_; }
/// \brief Get the maximum time for which the curve is defined.
/// \return \f$t_{max}\f$ upper bound of time range.
num_t virtual max() const { return T_max_; }
/// \brief Get the degree of the curve.
/// \return \f$degree\f$, the degree of the curve.
virtual std::size_t degree() const { return 0; }
/*Helpers*/
/*Attributes*/
Point value_;
time_t T_min_, T_max_; // const
std::size_t dim_; // const
/*Attributes*/
// Serialization of the class
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int version) {
if (version) {
// Do something depending on version ?
}
ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(curve_abc_t);
ar& boost::serialization::make_nvp("value", value_);
ar& boost::serialization::make_nvp("T_min", T_min_);
ar& boost::serialization::make_nvp("T_max", T_max_);
ar& boost::serialization::make_nvp("dim", dim_);
}
}; // struct constant_curve
} // namespace ndcurves
DEFINE_CLASS_TEMPLATE_VERSION(
SINGLE_ARG(typename Time, typename Numeric, bool Safe, typename Point,
typename Point_derivate),
SINGLE_ARG(
ndcurves::constant_curve<Time, Numeric, Safe, Point, Point_derivate>))
#endif // _CLASS_CONSTANTCURVE