Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
185 commits
Select commit Hold shift + click to select a range
81fb500
Joints - Add a first implementation of joint spline
MegMll Oct 8, 2025
6d10338
Unittest - Add TU for spline joint
MegMll Oct 8, 2025
03cff56
Bindings - add bindings for spline joint
MegMll Oct 8, 2025
acf9c52
Spatial - Weird fix to make spline joint work for now (to remove)
MegMll Oct 8, 2025
601c202
Unittest - update joint unittests to include spline joints
MegMll Oct 10, 2025
9227017
SplineJoint - apply pre-commit
MegMll Oct 10, 2025
7fa9883
Spline - use the true cumulative form of the spline
MegMll Oct 10, 2025
2a376bc
Spline - Add isEqual Method
MegMll Oct 13, 2025
ba8dafb
Spline - Add TU with finite difference
MegMll Oct 13, 2025
349758d
Unittest - fix tests for spline joint
MegMll Oct 13, 2025
697a984
Spline joint - change if/else to be casadi compatible
MegMll Oct 14, 2025
4f1b461
Joint Spline - Remove useless comments
MegMll Oct 15, 2025
7df1feb
Joint Spline - Fix indexing
MegMll Oct 15, 2025
d557795
Joint Spline - Eigen No Malloc checked and passed
MegMll Oct 15, 2025
76f9ef3
Spline joints - fix casadi joints tests
MegMll Oct 15, 2025
8b0a4db
Joint Spline - Add a build method
MegMll Oct 16, 2025
1e0bbed
Unittest - Fix joint spline's unittests
MegMll Oct 16, 2025
7b3210c
Model-graph - Add spline joint to model graph
MegMll Oct 16, 2025
1f3c5ca
JointSpline - make some correction to the joint
MegMll Oct 20, 2025
5a3bbd8
TU - apply new jointSpline constructor
MegMll Oct 20, 2025
62866a4
ModelGraph - use new JointSpline method
MegMll Oct 20, 2025
17da33e
Serialization - Add attributes from spline model and data
MegMll Oct 21, 2025
c7766c7
Unittest - use std vector instead of se3
MegMll Oct 21, 2025
2474c2a
JointSpline - Diverse Changes
MegMll Oct 21, 2025
fe623c0
Casadi - Add a separated file for findSpan to be able to do specializ…
MegMll Oct 21, 2025
0d44830
Bindings - modify joint spline binding
MegMll Oct 21, 2025
c5bef24
JointSpline - Remove findSpan
MegMll Oct 21, 2025
5570819
Unittest - remove buildJoint function
MegMll Oct 21, 2025
8f71dc3
ModelGraph - finish adding jointSpline to model graph + unittest
MegMll Oct 21, 2025
5477879
cppadcg: Fix cppadcg cast test with spline joint
jorisv Oct 22, 2025
a2706dc
multiprecision: Fix multiprecision cast test with Spline joint
jorisv Oct 22, 2025
06f8cfa
multiprecision: Add missing header
jorisv Oct 22, 2025
aa227a3
lint: Run linter
jorisv Oct 22, 2025
e5160f9
JointSpline - Removed comments
MegMll Oct 22, 2025
8f48978
JointSpline - move bspline functions in public to be able to test it
MegMll Oct 22, 2025
25053c8
Unittest - add more test for joint spline
MegMll Oct 22, 2025
93e0b9e
Bindings - Add another constructor for joint spline
MegMll Oct 23, 2025
7ba95a6
Unittest - put full knee trajectory
MegMll Oct 23, 2025
f6500f3
Unittest - fix getTrajectory function
MegMll Oct 23, 2025
01758ec
Bindings - add modelgraph bindings constant
MegMll Oct 27, 2025
b571c7b
JointSpline - Fix indexing
MegMll Oct 27, 2025
6b17353
JointSpline - Add a doc
MegMll Oct 27, 2025
49164a9
JointSpline - Fix bias computation
MegMll Oct 27, 2025
5855b08
Unittest - add a finite difference test for S and bias c for JointSpline
MegMll Oct 27, 2025
3779f4e
JointSpline - Add comments and complete isEqual function
MegMll Oct 28, 2025
d1afd72
Unittest - Try to add tolerance to see if it fixes macos-intel problem
MegMll Oct 28, 2025
647676b
Unittest - fix compilation error
MegMll Oct 28, 2025
21f7094
JointSpline - add assert for configuration to be between 0 and 1
MegMll Oct 30, 2025
49f7d44
Bindings - Add graph spline joints bindings
MegMll Oct 30, 2025
119145e
Algo/Splines - remove comments
MegMll Oct 30, 2025
d9cd11a
Unittest - add find span test for q = 0
MegMll Oct 30, 2025
ea020af
Changelog - update
MegMll Oct 30, 2025
3f688ea
JointSpline - remove SE3 and use Transformation_t
MegMll Oct 30, 2025
ba770e4
Unittest - remove comments
MegMll Oct 30, 2025
2cbb266
JointSpline - Use transformation_t and motion_t
MegMll Oct 30, 2025
6dbfa5b
Examples - Add a small examples on what the spline joint can do
MegMll Oct 30, 2025
5110376
Unittest - Specialize for joint spline
MegMll Oct 30, 2025
4c94147
Examples - add spline joint examples
MegMll Oct 30, 2025
bba1873
Unittest - Fix joint generic test for joint spline
MegMll Nov 3, 2025
574a334
Examples - Fix some linting errors
MegMll Nov 3, 2025
78caac0
JointSpline - Disable assert
MegMll Nov 4, 2025
7fa6da1
core: Apply small changes
jorisv Nov 25, 2025
93d513d
Algo/splines - add doc
MegMll Nov 26, 2025
6e56942
Unittest - Avoid code duplication for randomConfig vector generation
MegMll Nov 26, 2025
83fa3f5
Unittest - more complex and complete tests
MegMll Nov 26, 2025
6d64dda
Unittest/cppad - use degree 3 spline joint
MegMll Nov 27, 2025
89ccc56
unittest - change name of struct to be more generic
MegMll Nov 27, 2025
b08c065
unittest - avoid code duplication
MegMll Nov 27, 2025
3521f46
unittest - avoid code duplication
MegMll Nov 27, 2025
807bd1a
Unittest - fix casadi/joints test
MegMll Dec 9, 2025
d5a6c3d
Unittest - add forgotten helical unaligned joint
MegMll Dec 10, 2025
aef9a2b
Unittest - Fix casadi test for universal joints
MegMll Dec 11, 2025
e9073a7
Mode-graph - use new function for joint spline
MegMll Dec 11, 2025
e25fe62
Linting
MegMll Dec 12, 2025
59f468d
unittest - fix new joint
MegMll Dec 12, 2025
2c0c8c1
JointSpline - Fix bias computation
MegMll Dec 12, 2025
4daa8cf
Unittest - Fix finite-difference test
MegMll Dec 12, 2025
3b52146
unittest - use config vector of joints
MegMll Dec 12, 2025
ec96115
unittest - remove useless lines
MegMll Dec 12, 2025
8d3f757
Unittest - Add a utils file to centralize init of joints with parameters
MegMll Dec 15, 2025
0865814
Run pre-commit
MegMll Dec 15, 2025
94ab562
unittest/utils - Fix mimic init
MegMll Dec 15, 2025
e069d70
Core - update spline to allow spans to be between min and max, instea…
MegMll Apr 14, 2026
33dcdd5
core - move joint spline definition
MegMll Apr 14, 2026
fd0b9ba
core - update splines algorithms
MegMll Apr 14, 2026
3a6e54e
core - add spline joint
MegMll Apr 14, 2026
7fc4873
parser - add spline joint
MegMll Apr 14, 2026
ff6cced
core - fix some errors and warnings (some errors due to rebase still …
MegMll Apr 14, 2026
caaa9b7
unittest - use jointModelWithParameters
MegMll Apr 15, 2026
6d59876
unittest - use std::vector
MegMll Apr 15, 2026
b9336be
remove useless file
MegMll Apr 15, 2026
66fb5ec
unittest - fix compilation warnings
MegMll Apr 15, 2026
e1ba833
unittest - add spline joint to serialization test
MegMll Apr 15, 2026
72209ea
unittest - update serialization test to use jointModelWithParameters
MegMll Apr 17, 2026
a4edad8
unittest - clean, remove comments
MegMll Apr 17, 2026
ccf1933
fix cmake: @lucasJoseph
Ipuch Apr 23, 2026
2c0cf6b
fix: splines.hpp to sources.cmake
Ipuch May 5, 2026
4e1dea2
core : factorize code calc functions
MegMll May 6, 2026
662fd62
core : finish adding min/max for the knot vector + fix knot vector co…
MegMll May 6, 2026
1ba06c9
unittest : modify knot unittest to test min/max
MegMll May 6, 2026
900749f
core : add min/max for spline joint
MegMll May 6, 2026
f3f0773
refactor: decoupling the knotvector scaling
Ipuch May 6, 2026
6568415
tests: joint-generic bounding q with joint limits
Ipuch May 7, 2026
5b1aadf
spline: Apply new header convention
jorisv Jun 2, 2026
94666c1
spline: Fix build
jorisv Jun 3, 2026
d6fd9b6
core - add a new struct JointSplineBuilder
MegMll Jun 3, 2026
4fb8cf5
unittest - update tests to use new builder struct
MegMll Jun 3, 2026
055ff4e
model-graph - update jointSpline
MegMll Jun 3, 2026
d2cedc4
bindings - update jointSpline bindings
MegMll Jun 3, 2026
9eeb5b4
graph: Explain why we can't reverse the joint
jorisv Jun 5, 2026
a53580b
core - move splines algos into internal and/or private
MegMll Jun 5, 2026
96a0e70
core - make test casadi compatible
MegMll Jun 8, 2026
03021bc
unittest - Fix degree
MegMll Jun 8, 2026
5eee4c9
unittest - Make tset compatible with new internal api
MegMll Jun 8, 2026
50da261
unittest: Fix joint-init.hpp build
jorisv Jun 5, 2026
95a7da8
unittest: Use joint-init.hpp in visitor.cpp
jorisv Jun 5, 2026
033f98f
unittest: Use joint-init.hpp in joint-motion-subspace.cpp
jorisv Jun 5, 2026
2b9ffdb
unittest: Use joint-init.hpp in all-joints.cpp
jorisv Jun 5, 2026
91862d7
unittest: Remove dead code
jorisv Jun 5, 2026
9f47ca3
mpfr: Remove useless include
jorisv Jun 5, 2026
46383e2
changelog: Set in Unreleased and add example link
jorisv Jun 5, 2026
f13ce81
casadi: Fix scalar casting
jorisv Jun 5, 2026
e99121a
casadi: Fix expression evaluation
jorisv Jun 5, 2026
7e6ecc5
graph: Add JointSplineBuilder
jorisv Jun 8, 2026
48119c9
joint: Remove moved methods
jorisv Jun 8, 2026
dccd5eb
joint: Remove one warning
jorisv Jun 8, 2026
fc461a0
casadi: Fix build
jorisv Jun 8, 2026
1df18ab
python: Fix binding build and add graph::JointSplineBuilder
jorisv Jun 8, 2026
dfe87cc
examples: Use coal and run when running ctest
jorisv Jun 8, 2026
2623fca
python: Add JointModelSplineBuilder binding
jorisv Jun 8, 2026
e83419f
lint: Apply clang-format
jorisv Jun 8, 2026
90585c2
joint: Remove warning
jorisv Jun 8, 2026
c5a9e7c
unittest: Use builder to build joint
jorisv Jun 8, 2026
ee6aff9
unittest: Fix cppad-joints build
jorisv Jun 8, 2026
74045b9
unittest - rewrite most tests to use internal functions directly
MegMll Jun 9, 2026
dab1e19
core - write correct test for range inside basis function computation
MegMll Jun 9, 2026
1d04d23
example: knee with spline joint.
Ipuch Jun 10, 2026
d18ce5a
example: spline knee joint with better curves.
Ipuch Jun 10, 2026
8f52386
example: spline knee joint make it minimal
Ipuch Jun 11, 2026
0ac2e30
example: parabola in spline-joint.py
Ipuch Jun 11, 2026
031e09e
spline: Fix FindSpan and improve tests
jorisv Jun 11, 2026
6f5f1f5
test: Relax precision on finite-differences test
jorisv Jun 11, 2026
7e23049
test: fix some assert and remove warnings
jorisv Jun 11, 2026
67d1337
spline: Remove more warnings
jorisv Jun 11, 2026
eadca27
unittest: Use an open uniform spline by default to help numerical pre…
jorisv Jun 12, 2026
2a44e69
unittest: Add a bound test to bsplineBasis
jorisv Jun 12, 2026
c2fdc01
python: Expose JointDataSpline specialized members
jorisv Jun 12, 2026
ad9fa91
warning: Remove a bunch of clang warning
jorisv Jun 12, 2026
de73179
core - add Continuity check over knot vector
MegMll Jun 17, 2026
a975b4d
unittest - add test for basis function continuity
MegMll Jun 17, 2026
64a2969
unittest - fix unittest for basis function derivatives (finite differ…
MegMll Jun 17, 2026
e727de6
examples - apply linting
MegMll Jun 17, 2026
f152bbe
spline: Add deBoor algorithm to evaluate the BSpline
jorisv Jul 9, 2026
eed08d3
spline: Remove warnings
jorisv Jul 9, 2026
a450e92
spline: Implement deBoorCumBasisSparse
jorisv Jul 9, 2026
8abff51
spline: Rename deBoorBasis into deBoor
jorisv Jul 9, 2026
1fd24cc
spline: Add bsplineBasis to compute all basis function with minimal c…
jorisv Jul 15, 2026
45c028e
spline: Remove other deBoor like algorithm
jorisv Jul 15, 2026
4f42559
spline: Add comments
jorisv Jul 15, 2026
ea7c347
spline: First working version with deBoorBasis
jorisv Jul 15, 2026
132b721
spline: Add standalone function to compute cumulative bspline derivat…
jorisv Jul 16, 2026
a3cb088
spline: Move bsplineBasis in unit tests and test cumulativeBasisDeriv…
jorisv Jul 16, 2026
be553d0
spline: Fix build
jorisv Jul 16, 2026
3c16950
spline: Add deBoorFullBasis function
jorisv Jul 17, 2026
b1748b4
spline: Improve doc and comments
jorisv Jul 17, 2026
8a94293
spline: Add Full variant to support casadi
jorisv Jul 17, 2026
1a2b1e6
spline: Refactor code to implement spline transformation on minimal a…
jorisv Jul 17, 2026
5a078cf
spline: Add computeSplineKinematicsFull
jorisv Jul 17, 2026
763bbe9
spline: Fix changelog
jorisv Jul 20, 2026
bab7deb
spline: Test computeSplineKinematicsFull.
jorisv Jul 20, 2026
531ab79
Spline: Setup SplineKinematics structure
jorisv Jul 20, 2026
f479196
spline: Try to fix Windows build issue
jorisv Jul 21, 2026
acbc13e
examples: Add guards to stop example if meshcat is not installed
jorisv Jul 21, 2026
aa9848f
spline: Remove warnings
jorisv Jul 21, 2026
3bbe7e1
spline: Improve assert
jorisv Jul 22, 2026
8d6a79c
spline: Rename deBoorFulBasis into deBoorBasisFull
jorisv Jul 22, 2026
39da48f
spline: Store deBoorBasis in a dense vector
jorisv Jul 22, 2026
a90a403
spline: Enforce to evalute spline in valid range
jorisv Jul 22, 2026
f582c73
python: Add attributes
jorisv Jul 22, 2026
5a35c9d
spline: Remove useless macro
jorisv Jul 22, 2026
56dd6a3
spline: Fix check_expression_if_real use
jorisv Jul 22, 2026
a7c761e
unittest: Use degree 3 spline
jorisv Jul 23, 2026
cdc0b86
changelog: List second example
jorisv Jul 23, 2026
c8973cf
unittest: Use joint-init.hpp in cppad/joints.cpp
jorisv Jul 23, 2026
504fbc0
spline: Add spline constructor guards test
jorisv Jul 23, 2026
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Added
- Add `DataTpl::lastChild` deprecation notice in Python binding
- Add spline joint (JointModelSplineTpl) to default joint collection ([#2784](https://github.com/stack-of-tasks/pinocchio/pull/2784))
- Python example [here](./examples/spline-joint.py) and [here](./examples/spline-joint-knee.py)

## [4.1.0] - 2026-07-07

Expand Down
46 changes: 46 additions & 0 deletions bindings/python/parsers/graph/expose-edges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ namespace pinocchio

const int JointMimic::nq;
const int JointMimic::nv;

const int JointSpline::nq;
const int JointSpline::nv;
} // namespace graph

namespace python
Expand Down Expand Up @@ -160,6 +163,49 @@ namespace pinocchio
.def_readonly("nq", &JointUniversal::nq, "Number of configuration variables.")
.def_readonly("nv", &JointUniversal::nv, "Number of tangent variables.");

bp::class_<JointSpline>(
"JointSpline", "Represents a spline-based joint.",
bp::init<>(bp::args("self"), "Default constructor."))
.def(
bp::init<const std::vector<SE3> &, const Eigen::VectorXd &, std::size_t>(
bp::args("self", "ctrlFrame", "knots", "degree"),
"Constructor with a single control frame and degree."))
.def_readwrite("ctrlFrames", &JointSpline::ctrlFrames, "Control frames of the spline.")
.def_readwrite("knots", &JointSpline::knots, "Control frames of the spline.")
.def_readwrite("degree", &JointSpline::degree, "Degree of the spline.")
.def_readonly("nq", &JointSpline::nq, "Number of configuration variables.")
.def_readonly("nv", &JointSpline::nv, "Number of tangent variables.");

bp::class_<JointSplineBuilder>(
"JointSplineBuilder", "JointSpline builder helper.",
bp::init<>(bp::args("self"), "Default constructor."))
.def(
"addControlFrame", &JointSplineBuilder::addControlFrame, bp::return_self<>(),
(bp::arg("self"), bp::arg("frame")), "Add a B-spline control frame")
.def(
"withControlFrameVector", &JointSplineBuilder::withControlFrameVector,
bp::return_self<>(), (bp::arg("self"), bp::arg("frames")),
"Set B-spline control frame vector")
.def(
"withDegree", &JointSplineBuilder::withDegree, bp::return_self<>(),
(bp::arg("self"), bp::arg("degree")), "Set B-spline degree")
.def(
"withKnotVector",
+[](JointSplineBuilder & builder, const std::vector<double> & k) -> auto {
return builder.withKnotVector(k);
},
bp::return_self<>(), (bp::arg("self"), bp::arg("knots")), "Set B-spline knot vector")
.def(
"withOpenUniformKnots", &JointSplineBuilder::withOpenUniformKnots, bp::return_self<>(),
(bp::arg("self"), bp::arg("min"), bp::arg("max")),
"Set B-spline knot vector as open uniform")
.def(
"withUniformKnots", &JointSplineBuilder::withUniformKnots, bp::return_self<>(),
(bp::arg("self"), bp::arg("min"), bp::arg("max")), "Set B-spline knot vector as uniform")
.def(
"build", &JointSplineBuilder::build, (bp::arg("self")),
"Build a JointSpline from provided parameters");

bp::class_<JointComposite>(
"JointComposite", "Represents a composite joint.",
bp::init<>(bp::args("self"), "Default constructor."))
Expand Down
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ if(BUILD_PYTHON_INTERFACE)
simulation-closed-kinematic-chains
simulation-lcaba
model-graph-geometry
spline-joint
spline-joint-knee
)
if(BUILD_WITH_URDF_SUPPORT)
list(
Expand Down
153 changes: 153 additions & 0 deletions examples/spline-joint-knee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
"""Knee spline joint driven by its physical flexion angle.

This example uses the SE(3) spline joint (``pin.JointModelSpline`` /
``pin.JointModelSplineBuilder``) to reproduce experimental knee kinematics: the
joint constrains its child (tibia) frame to a cumulative B-spline on SE(3)
defined by a list of control frames, a knot vector and a degree

source: Lee, S. H., & Terzopoulos, D. (2008).
Spline joints for multibody dynamics. In ACM SIGGRAPH 2008 papers (pp. 1-8).

The 8 control frames below were fit offline (Gauss-Newton, degree=3, n_ctrl=8)
to a planar OpenSim knee, where the tx/ty translations the rotation
about Z (knee flexion) are driven by knee flexion itself.
"""

import time
from pathlib import Path

import coal

try:
import meshcat.geometry as mg
except ImportError as err:
import sys

print("Error while importing meshcat. It seems you should install Python meshcat")
print(err)
sys.exit(0)
import numpy as np
import pinocchio as pin
from pinocchio.visualize import MeshcatVisualizer

# Bones: mesh folder, OpenSim (subject-specific) scale factors and display color.
MESH_DIR = Path(__file__).resolve().parent.parent / "models" / "biomechanics"
FEMUR_SCALE, TIBIA_SCALE = 1.17378, 1.12373
BONE_COLOR = np.array([0.96, 0.94, 0.86, 0.7]) # bone ivory, semi-transparent.

# Recenter so the femoral condyle (knee) sits at the world origin instead of the
# hip: the fixed femur and the spline joint are both lifted by the knee offset.
KNEE_FROM_HIP = np.array([-0.0046, -0.4644, 0.0])
RECENTER = pin.SE3(np.eye(3), -KNEE_FROM_HIP)

# Control frames from the offline 2D-knee regression, as (yaw [rad], tx, ty [m]).
CONTROL_FRAMES = [
(-2.094400, -0.003842, -0.496205),
(-1.815147, 0.001278, -0.489246),
(-1.256640, 0.006243, -0.480186),
(-0.418880, -0.002220, -0.466444),
(0.418880, -0.008427, -0.463391),
(1.256640, -0.005740, -0.461613),
(1.815147, -0.006127, -0.464906),
(2.094400, -0.006285, -0.464416),
]


def mesh_object(name, parent_joint, stl, scale, placement):
"""Build a mesh GeometryObject fixed to ``parent_joint`` at ``placement``."""
mesh_scale = scale * np.ones(3)
geom = coal.MeshLoader().load(str(stl), mesh_scale)
obj = pin.GeometryObject(name, parent_joint, placement, geom, str(stl), mesh_scale)
obj.meshColor = BONE_COLOR
return obj


class PointTracer:
"""Trace a fixed point in Meshcat, keeping the dotted trail."""

def __init__(self, viz, name, point=None, color=0xFF3030, size=0.004):
self._world_to_femur = RECENTER.inverse()
self._point = np.zeros(3) if point is None else np.asarray(point, float)
self._material = mg.PointsMaterial(size=size, color=color)
self._trail = []
self._node = viz.viewer[f"tibia_traces/{name}"]
self._node.set_transform(RECENTER.homogeneous)

def add(self, tibia_pose):
self._trail.append(self._world_to_femur.act(tibia_pose.act(self._point)))
pts = np.asarray(self._trail, dtype=np.float32).T
self._node.set_object(mg.Points(mg.PointsGeometry(pts), self._material))


def main():
control_frames = [
pin.SE3(pin.rpy.rpyToMatrix(0.0, 0.0, yaw), np.array([tx, ty, 0.0]))
for (yaw, tx, ty) in CONTROL_FRAMES
]

# Knee-angle domain of the fitted spline (in degree).
THETA_MIN_DEG, THETA_MAX_DEG = -120.0, 120.0

knee = (
pin.JointModelSplineBuilder()
.withDegree(
3
) # degree of the splines, degree 3 means acceleration is continuous.
.withControlFrameVector(control_frames) # list of SE3 transforms
.withOpenUniformKnots(
THETA_MIN_DEG, THETA_MAX_DEG
) # Map knee flexion angle (degrees) to spline parameter q in [0, 1].
.build()
)
model = pin.Model()
joint_id = model.addJoint(0, knee, RECENTER, "knee")

# visual only code
try:
visual_model = pin.GeometryModel()
visual_model.addGeometryObject(
mesh_object("femur", 0, MESH_DIR / "femur_r.stl", FEMUR_SCALE, RECENTER)
)
visual_model.addGeometryObject(
mesh_object(
"tibia",
joint_id,
MESH_DIR / "tibia_r.stl",
TIBIA_SCALE,
pin.SE3.Identity(),
)
)

viz = MeshcatVisualizer(model, None, visual_model)
viz.initViewer(open=True)
viz.loadViewerModel()

except ImportError as e:
print("Error while initializing the viewer.")
print(e)
return

# Trace tibia-frame points and show the tibia frame as a triad, updated every step.
plateau = np.array([0.03100708, -0.03819558, -0.00347008])
tracers = [
PointTracer(viz, "origin", color=0xFF3030),
PointTracer(viz, "plateau", plateau, color=0x3060FF),
]
tibia_frame = viz.viewer["tibia_frame"]
tibia_frame.set_object(mg.triad(0.08))

# Sweep the physical knee angle (+10 deg hyperextension to -120 deg flexion),
angles = np.linspace(10.0, -120.0, 120)
angles = np.concatenate([angles, angles[::-1]])
for _ in range(5):
for theta_deg in angles:
viz.display(np.array([theta_deg]))
tibia_pose = viz.data.oMi[joint_id]
for tracer in tracers:
tracer.add(tibia_pose)
tibia_frame.set_transform(tibia_pose.homogeneous)
time.sleep(0.015)


if __name__ == "__main__":
main()
116 changes: 116 additions & 0 deletions examples/spline-joint.py
Comment thread
jorisv marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import time

try:
import meshcat.geometry as mg
except ImportError as err:
import sys

print("Error while importing meshcat. It seems you should install Python meshcat")
print(err)
sys.exit(0)
import numpy as np
import pinocchio as pin
from pinocchio.visualize import MeshcatVisualizer


class PointTracer:
"""Trace a fixed point in Meshcat, keeping the dotted trail."""

def __init__(self, viz):
self._material = mg.PointsMaterial(size=0.004, color=0xFF3030)
self._trail = []
self._node = viz.viewer["solid_pose"]

def add(self, solid_pose):
self._trail.append(solid_pose.translation.copy())
pts = np.asarray(self._trail, dtype=np.float32).T

line = mg.Line(
geometry=mg.PointsGeometry(pts),
material=mg.LineBasicMaterial(color=0xFF3030),
)
self._node.set_object(geometry=line)


def main():
PARABOLA_CONTROL_FRAMES = [
(-1.000000, 1.000000),
(-0.888889, 0.777778),
(-0.666667, 0.407407),
(-0.333333, 0.074074),
(0.000000, -0.037037),
(0.333333, 0.074074),
(0.666667, 0.407407),
(0.888889, 0.777778),
(1.000000, 1.000000),
]

control_frames = [
pin.SE3(np.eye(3), np.array([0, ty, tz]))
for (ty, tz) in PARABOLA_CONTROL_FRAMES
]

# Create a Pinocchio model with a single free-flyer joint
model = pin.Model()
spline_joint = (
pin.JointModelSplineBuilder()
.withDegree(3)
.withControlFrameVector(control_frames)
.withOpenUniformKnots(-1, 1)
.build()
)
joint_id = model.addJoint(0, spline_joint, pin.SE3.Identity(), "spline-joint")

# adding some inertia to drop the solid in the parabola
box_size = 1.0 # edge length of each cube [m]
box_mass = 1.0 # mass of each cube [kg]
box_inertia = pin.Inertia.FromBox(box_mass, box_size, box_size, box_size)
model.appendBodyToJoint(joint_id, box_inertia, pin.SE3.Identity())

# visual only code
try:
visual_model = pin.GeometryModel()

viz = MeshcatVisualizer(model, None, visual_model)
viz.initViewer(open=True)
viz.loadViewerModel()

except ImportError as e:
print("Error while initializing the viewer.")
print(e)
return

tracers = [PointTracer(viz)]
solid_frame = viz.viewer["solid_frame"]
solid_frame.set_object(mg.triad(0.2))

dt = 0.01
qs, _ = sim_loop(model, dt)

for theta in qs:
viz.display(np.array([theta]))
solid_pose = viz.data.oMi[joint_id]
for tracer in tracers:
tracer.add(solid_pose)
solid_frame.set_transform(solid_pose.homogeneous)
time.sleep(dt)


def sim_loop(model, dt=0.01, nsteps=800):
qs = [np.array([1.0])]
vs = [np.array([0])]
data = model.createData()
for i in range(nsteps):
q = qs[i]
v = vs[i]
tau = -1 * v # a little bit of damping
a1 = pin.aba(model, data, q, v, tau)
vnext = v + dt * a1
qnext = pin.integrate(model, q, dt * vnext)
qs.append(qnext)
vs.append(vnext)
return qs, vs


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions include/pinocchio/autodiff/casadi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "pinocchio/eigen-common.hpp"
#include "pinocchio/math.hpp"
#include "pinocchio/spatial.hpp"
#include "pinocchio/src/multibody/joint/spline-utils.hxx"
// IWYU pragma: end_keep

namespace boost
Expand Down Expand Up @@ -349,4 +350,5 @@ namespace Eigen
#include "pinocchio/src/autodiff/casadi/math/triangular-matrix.hxx"
#include "pinocchio/src/autodiff/casadi/spatial/se3-tpl.hxx"
#include "pinocchio/src/autodiff/casadi/utils/static-if.hxx"
#include "pinocchio/src/autodiff/casadi/multibody/joint/spline-utils.hxx"
// IWYU pragma: end_exports
4 changes: 4 additions & 0 deletions include/pinocchio/bindings/python/context/generic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ namespace pinocchio
typedef JointModelUniversalTpl<Scalar> JointModelUniversal;
typedef JointDataUniversalTpl<Scalar> JointDataUniversal;

typedef JointModelSplineTpl<Scalar> JointModelSpline;
typedef JointModelSplineBuilderTpl<Scalar> JointModelSplineBuilder;
typedef JointDataSplineTpl<Scalar> JointDataSpline;

typedef JointModelTranslationTpl<Scalar> JointModelTranslation;
typedef JointDataTranslationTpl<Scalar> JointDataTranslation;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,11 @@ namespace pinocchio
.add_property("StU", &JointDataComposite::StU);
}

template<>
inline bp::class_<JointDataSpline> &
expose_joint_data<JointDataSpline>(bp::class_<JointDataSpline> & cl)
{
return cl.add_property("N", &JointDataSpline::N);
}
} // namespace python
} // namespace pinocchio
Loading
Loading