Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a6ff885
add folder for STLIB
bakpaul Apr 14, 2025
60352a4
Add reusable methods
bakpaul Apr 14, 2025
d024105
Add working files
bakpaul Apr 14, 2025
10082bf
Created example scenes
bakpaul Apr 14, 2025
d167479
Fix example
bakpaul Apr 14, 2025
dd9cc34
orga folders
hugtalbot Apr 14, 2025
7589706
Fix package
bakpaul Apr 14, 2025
2f844d7
bootstrap examples
bakpaul Apr 14, 2025
2c55e7d
start beginner scene
hugtalbot Apr 14, 2025
9b9e057
Move around files
bakpaul Apr 14, 2025
b989159
Move examples into SofaPython3 main example folder
bakpaul Apr 14, 2025
b42833b
Add unsaved modifications
bakpaul Apr 14, 2025
fa0bd74
reoganisation after discussion
EulalieCoevoet Apr 14, 2025
4380356
Add gemetries
bakpaul Apr 14, 2025
ba978ce
WIP FileParameters
bakpaul Apr 14, 2025
fc88100
Add beginner example
bakpaul Apr 14, 2025
7c314c6
Add unsaved changes
bakpaul Apr 14, 2025
b70a52b
Start work on visual and collision
bakpaul Apr 14, 2025
7cedc42
work on Tuesday : visual, geometry
hugtalbot Apr 15, 2025
5f183d5
add basePrefabParameters.py
hugtalbot Apr 15, 2025
97a2381
Add extracted geometry
bakpaul Apr 15, 2025
00fd16b
Fix visual example
bakpaul Apr 15, 2025
423a484
Finished collisions
bakpaul Apr 15, 2025
c97bfa3
[stlib-splib] work on prefabs: cleaning (#501)
EulalieCoevoet Jun 2, 2025
995d1b3
[stlib] adds README
EulalieCoevoet Jun 2, 2025
01531ca
[stlib] minor changes from discussion
EulalieCoevoet Jun 2, 2025
fc1404a
[splib] updates entity
EulalieCoevoet Jun 3, 2025
dd230b9
update README
hugtalbot Jun 3, 2025
57efa1d
add init in prefab
hugtalbot Jun 3, 2025
938f05b
Add first implem of entity
bakpaul Jun 3, 2025
592c13d
before the train 3/3
hugtalbot Jun 3, 2025
ca864d8
very last commit befor train
EulalieCoevoet Jun 3, 2025
1d8cdd3
WIP
bakpaul Jun 3, 2025
bacb258
Retore original. Still crash due to wrong string conversion
bakpaul Jun 3, 2025
09f45c5
[stlib] Deformable Entity (#502)
EulalieCoevoet Jun 13, 2025
d4b6042
Fix linkpath by introducing init method + make addDeformableMaterial …
bakpaul Jun 13, 2025
aad2a5e
[STLIB] Add the unified "add" in Sofa.Core.Node (#503)
damienmarchal Jul 17, 2025
1b15154
Add new tests for prefabs
bakpaul Jul 17, 2025
e2fff56
Revert modification of __genericAdd
bakpaul Jul 17, 2025
9de87d4
update addMass using elementType
hugtalbot Jul 17, 2025
75fa28f
[Prefabs] Reorder files to match concepts (#547)
bakpaul Oct 28, 2025
ae1d496
[Prefabs] cleaning to fix deformable example (#549)
EulalieCoevoet Oct 28, 2025
ac3ed74
Fix by passing state link when using other topology than edges (#550)
bakpaul Oct 28, 2025
539badc
Squashed commit of the following:
bakpaul Mar 2, 2026
ed5e019
Fix constraint solvr name
bakpaul Mar 2, 2026
a1d91c8
Register in the PythonFactory Rigid3::Coord (#544)
damienmarchal Oct 30, 2025
6bc55e7
Squashed commit of the following:
bakpaul Mar 3, 2026
92dccd9
revert some changes
EulalieCoevoet Mar 3, 2026
9e3dda5
test modifier
EulalieCoevoet Mar 4, 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
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ SP3_add_python_package(
TARGET_DIRECTORY
splib
)
SP3_add_python_package(
SOURCE_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/stlib
TARGET_DIRECTORY
stlib
)

sofa_create_package(
PACKAGE_NAME ${PROJECT_NAME}
Expand Down
10 changes: 1 addition & 9 deletions Plugin/src/SofaPython3/DataHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,7 @@ std::ostream& operator<<(std::ostream& out, const py::buffer_info& p)

std::string getPathTo(Base* b)
{
BaseNode* node = dynamic_cast<BaseNode*>(b);
if(node)
return node->getPathName();
BaseObject* object = dynamic_cast<BaseObject*>(b);
if(object)
return object->getPathName();

assert(true && "Only Base & BaseObject are supported");
return "";
return b->getPathName();
}

const char* getFormat(const AbstractTypeInfo& nfo)
Expand Down
2 changes: 1 addition & 1 deletion Plugin/src/SofaPython3/PythonEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ void PythonEnvironment::Init()

// Workaround: try to import scipy from the main thread this prevents a deadlock when importing
// scipy from a worker thread when we use the SofaScene asynchronous loading
executePython([]{ PyRun_SimpleString("try:\n\tfrom scipy import misc, optimize\nexcept:\n\tpass\n");});
executePython([]{ PyRun_SimpleString("try:\n\tfrom scipy import optimize\nexcept:\n\tpass\n");});

// If the script directory is not available (e.g. if the interpreter is invoked interactively
// or if the script is read from standard input), path[0] is the empty string,
Expand Down
12 changes: 11 additions & 1 deletion Plugin/src/SofaPython3/PythonFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,17 @@ bool PythonFactory::registerDefaultTypes()
PythonFactory::registerType<sofa::core::topology::Topology::Hexa>("Hexa");
PythonFactory::registerType<sofa::core::topology::Topology::Penta>("Penta");

// State vectors
// Rigid
PythonFactory::registerType<sofa::defaulttype::Rigid3dTypes::Coord>("Rigid3d::Coord");
PythonFactory::registerType<sofa::defaulttype::Rigid3fTypes::Coord>("Rigid3f::Coord");
PythonFactory::registerType<sofa::defaulttype::Rigid3Types::Coord>("Rigid3::Coord");

// Quaternion
PythonFactory::registerType<sofa::type::Quat<double>>("Quatd");
PythonFactory::registerType<sofa::type::Quat<float>>("Quatf");
PythonFactory::registerType<sofa::type::Quat<SReal>>("Quat");

// Rigid3 vectors
PythonFactory::registerType<sofa::defaulttype::Rigid3dTypes::VecCoord>("Rigid3d::VecCoord");
PythonFactory::registerType<sofa::defaulttype::Rigid3fTypes::VecCoord>("Rigid3f::VecCoord");
PythonFactory::registerType<sofa::defaulttype::Rigid3Types::VecCoord>("Rigid3::VecCoord");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Returns the compliance matrix projected in constraint space, built in the constr
example:
------------

constraint_solver = root.addObject("ProjectedGaussSeidelConstraintSolver", tolerance=1e-9, maxIterations=1000)
constraint_solver = root.addObject("BlockGaussSeidelConstraintSolver", tolerance=1e-9, maxIterations=1000)
matrix = constraint_solver.W()
)";

Expand All @@ -45,7 +45,7 @@ Returns the force resulting from the constraints
example:
------------

constraint_solver = root.addObject("ProjectedGaussSeidelConstraintSolver", tolerance=1e-9, maxIterations=1000)
constraint_solver = root.addObject("BlockGaussSeidelConstraintSolver", tolerance=1e-9, maxIterations=1000)
lambda = constraint_solver.lambda_force()
)";

Expand All @@ -56,7 +56,7 @@ Returns the displacement computed without any constraint
example:
------------

constraint_solver = root.addObject("ProjectedGaussSeidelConstraintSolver", tolerance=1e-9, maxIterations=1000)
constraint_solver = root.addObject("BlockGaussSeidelConstraintSolver", tolerance=1e-9, maxIterations=1000)
dfree = constraint_solver.dfree()
)";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void bindLinearSolvers(py::module &m)

c.def("A", [](CRSLinearSolver& self) -> EigenSparseMatrix
{
if (CRS* matrix = self.getSystemMatrix())
if (CRS* matrix = self.l_linearSystem->getSystemMatrix())
{
return toEigen(*matrix);
}
Expand All @@ -76,7 +76,7 @@ void bindLinearSolvers(py::module &m)

c.def("b", [](CRSLinearSolver& self) -> Vector
{
if (auto* vector = self.getSystemRHVector())
if (auto* vector = self.l_linearSystem->getRHSVector())
{
return EigenVectorMap(vector->ptr(), vector->size());
}
Expand All @@ -85,7 +85,7 @@ void bindLinearSolvers(py::module &m)

c.def("x", [](CRSLinearSolver& self) -> Vector
{
if (auto* vector = self.getSystemLHVector())
if (auto* vector = self.l_linearSystem->getSolutionVector())
{
return EigenVectorMap(vector->ptr(), vector->size());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,12 @@
*******************************************************************************
* Contact information: contact@sofa-framework.org *
******************************************************************************/
#include <SofaPython3/SofaLinearSystem/Binding_LinearSystem.h>
#include <SofaPython3/SofaLinearSystem/Binding_LinearSystem_doc.h>
#include <pybind11/pybind11.h>
#include <SofaPython3/SofaLinearSystem/Binding_LinearSystem.inl>

#include <SofaPython3/Sofa/Core/Binding_Base.h>
#include <SofaPython3/PythonFactory.h>

#include <sofa/component/linearsystem/TypedMatrixLinearSystem.h>
#include <pybind11/eigen.h>
#include <sofa/linearalgebra/BTDMatrix.h>
#include <sofa/linearalgebra/BlockVector.h>
#include <sofa/linearalgebra/CompressedRowSparseMatrix.h>


Expand All @@ -39,12 +36,6 @@ using EigenSparseMatrix = Eigen::SparseMatrix<Real, Eigen::RowMajor>;
template<class Real>
using EigenMatrixMap = Eigen::Map<Eigen::SparseMatrix<Real, Eigen::RowMajor> >;

template<class Real>
using Vector = Eigen::Matrix<Real,Eigen::Dynamic, 1>;

template<class Real>
using EigenVectorMap = Eigen::Map<Vector<Real>>;

template<class TBlock>
EigenSparseMatrix<typename sofa::linearalgebra::CompressedRowSparseMatrix<TBlock>::Real>
toEigen(sofa::linearalgebra::CompressedRowSparseMatrix<TBlock>& matrix)
Expand All @@ -70,62 +61,104 @@ toEigen(sofa::linearalgebra::CompressedRowSparseMatrix<TBlock>& matrix)
}
}

template<class TBlock>
void bindLinearSystems(py::module &m)
template<class TMatrix, class TVector>
void bindMatrixAccessCRS(LinearSystemClass<TMatrix, TVector>& c)
{
using CRS = sofa::linearalgebra::CompressedRowSparseMatrix<TBlock>;
using Real = typename CRS::Real;
using CRSLinearSystem = sofa::component::linearsystem::TypedMatrixLinearSystem<CRS, sofa::linearalgebra::FullVector<Real> >;
using Real = typename TMatrix::Real;
using CRSLinearSystem = sofa::component::linearsystem::TypedMatrixLinearSystem<TMatrix, TVector>;

const std::string typeName = CRSLinearSystem::GetClass()->className + CRSLinearSystem::GetCustomTemplateName();

py::class_<CRSLinearSystem,
sofa::core::objectmodel::BaseObject,
sofapython3::py_shared_ptr<CRSLinearSystem> > c(m, typeName.c_str(), sofapython3::doc::linearsystem::linearSystemClass);

c.def("A", [](CRSLinearSystem& self) -> EigenSparseMatrix<Real>
{
if (CRS* matrix = self.getSystemMatrix())
const auto matrixAccess =
[](CRSLinearSystem& self) -> EigenSparseMatrix<Real>
{
if (matrix->colsValue.empty()) //null matrix: contains no entries
if (TMatrix* matrix = self.getSystemMatrix())
{
return EigenSparseMatrix<Real>{matrix->rows(), matrix->cols()};
if (matrix->colsValue.empty()) //null matrix: contains no entries
{
return EigenSparseMatrix<Real>{matrix->rows(), matrix->cols()};
}
return toEigen(*matrix);
}
return toEigen(*matrix);
}
return {};
}, sofapython3::doc::linearsystem::linearSystem_A);
return {};
};

c.def("b", [](CRSLinearSystem& self) -> Vector<Real>
{
if (auto* vector = self.getRHSVector())
{
return EigenVectorMap<Real>(vector->ptr(), vector->size());
}
return {};
}, sofapython3::doc::linearsystem::linearSystem_b);
c.def("A", matrixAccess, sofapython3::doc::linearsystem::linearSystem_CRS_A);
c.def("get_system_matrix", matrixAccess, sofapython3::doc::linearsystem::linearSystem_CRS_get_system_matrix);
}

c.def("x", [](CRSLinearSystem& self) -> Vector<Real>
{
if (auto* vector = self.getSolutionVector())
{
return EigenVectorMap<Real>(vector->ptr(), vector->size());
}
return {};
}, sofapython3::doc::linearsystem::linearSystem_x);
template<>
void bindMatrixAccess(LinearSystemClass<sofa::linearalgebra::CompressedRowSparseMatrix<SReal>, sofa::linearalgebra::FullVector<SReal>>& c)
{
bindMatrixAccessCRS(c);
}

template<>
void bindMatrixAccess(LinearSystemClass<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<2,2,SReal>>, sofa::linearalgebra::FullVector<SReal>>& c)
{
bindMatrixAccessCRS(c);
}

/// register the binding in the downcasting subsystem
PythonFactory::registerType<CRSLinearSystem>([](sofa::core::objectmodel::Base* object)
{
return py::cast(dynamic_cast<CRSLinearSystem*>(object));
});
template<>
void bindMatrixAccess(LinearSystemClass<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<3,3,SReal>>, sofa::linearalgebra::FullVector<SReal>>& c)
{
bindMatrixAccessCRS(c);
}

template<>
void bindMatrixAccess(LinearSystemClass<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<4,4,SReal>>, sofa::linearalgebra::FullVector<SReal>>& c)
{
bindMatrixAccessCRS(c);
}

template<>
void bindMatrixAccess(LinearSystemClass<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<6,6,SReal>>, sofa::linearalgebra::FullVector<SReal>>& c)
{
bindMatrixAccessCRS(c);
}

template<>
void bindMatrixAccess(LinearSystemClass<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<8,8,SReal>>, sofa::linearalgebra::FullVector<SReal>>& c)
{
bindMatrixAccessCRS(c);
}

template<class Real>
using DenseMatrix = Eigen::Matrix<Real,Eigen::Dynamic, Eigen::Dynamic>;

template<class Real>
using EigenDenseMatrixMap = Eigen::Map<DenseMatrix<Real>>;

template<>
void bindMatrixAccess(LinearSystemClass<sofa::linearalgebra::FullMatrix<SReal>, sofa::linearalgebra::FullVector<SReal>>& c)
{
using CRSLinearSystem = sofa::component::linearsystem::TypedMatrixLinearSystem<sofa::linearalgebra::FullMatrix<SReal>, sofa::linearalgebra::FullVector<SReal>>;

const auto matrixAccess =
[](CRSLinearSystem& self) -> EigenDenseMatrixMap<SReal>
{
sofa::linearalgebra::FullMatrix<SReal>* matrix = self.getSystemMatrix();
const auto row = matrix ? matrix->rows() : 0;
const auto col = matrix ? matrix->cols() : 0;
return EigenDenseMatrixMap<SReal>(matrix ? matrix->ptr() : nullptr, row, col);
};
c.def("A", matrixAccess, sofapython3::doc::linearsystem::linearSystem_FullMatrix_A);
c.def("get_system_matrix", matrixAccess, sofapython3::doc::linearsystem::linearSystem_FullMatrix_get_system_matrix);
}

void moduleAddLinearSystem(py::module &m)
{
bindLinearSystems<SReal>(m);
bindLinearSystems<sofa::type::Mat<3, 3, SReal> >(m);
bindLinearSystems<sofa::linearalgebra::FullMatrix<SReal>, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::SparseMatrix<SReal>, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::CompressedRowSparseMatrix<SReal>, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<2,2,SReal> >, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<3,3,SReal> >, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<4,4,SReal> >, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<6,6,SReal> >, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::CompressedRowSparseMatrix<sofa::type::Mat<8,8,SReal> >, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::DiagonalMatrix<SReal>, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::BlockDiagonalMatrix<3,SReal>, sofa::linearalgebra::FullVector<SReal> >(m);
bindLinearSystems<sofa::linearalgebra::RotationMatrix<SReal>, sofa::linearalgebra::FullVector<SReal> >(m);

bindLinearSystems<sofa::linearalgebra::BTDMatrix<6, SReal>, sofa::linearalgebra::BlockVector<6, SReal> >(m);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: contact@sofa-framework.org *
******************************************************************************/
#pragma once
#include <SofaPython3/SofaLinearSystem/Binding_LinearSystem.h>
#include <SofaPython3/SofaLinearSystem/Binding_LinearSystem_doc.h>
#include <sofa/component/linearsystem/TypedMatrixLinearSystem.h>
#include <pybind11/pybind11.h>

#include <SofaPython3/PythonFactory.h>
#include <SofaPython3/Sofa/Core/Binding_Base.h>
#include <sofa/linearalgebra/EigenSparseMatrix.h>

namespace py { using namespace pybind11; }

namespace sofapython3
{

template<class Real>
using Vector = Eigen::Matrix<Real,Eigen::Dynamic, 1>;

template<class Real>
using EigenVectorMap = Eigen::Map<Vector<Real>>;

template<class TVector>
Vector<typename TVector::Real>
getVector(TVector* vector)
{
using Real = typename TVector::Real;
if (vector)
{
return EigenVectorMap<Real>(vector->ptr(), vector->size());
}
return {};
}

template<class TMatrix, class TVector>
Vector<typename TVector::Real> getRHSVector(sofa::component::linearsystem::TypedMatrixLinearSystem<TMatrix, TVector>& linearSystem)
{
return getVector(linearSystem.getRHSVector());
}

template<class TMatrix, class TVector>
Vector<typename TVector::Real> getSolutionVector(sofa::component::linearsystem::TypedMatrixLinearSystem<TMatrix, TVector>& linearSystem)
{
return getVector(linearSystem.getSolutionVector());
}

template<class TMatrix, class TVector>
using LinearSystemClass =
py::class_<sofa::component::linearsystem::TypedMatrixLinearSystem<TMatrix, TVector>,
sofa::core::objectmodel::BaseObject,
sofapython3::py_shared_ptr<sofa::component::linearsystem::TypedMatrixLinearSystem<TMatrix, TVector>> >;

template<class TMatrix, class TVector>
void bindMatrixAccess(LinearSystemClass<TMatrix, TVector>& c)
{}

template<class TMatrix, class TVector>
void bindLinearSystems(py::module &m)
{
using LinearSystem = sofa::component::linearsystem::TypedMatrixLinearSystem<TMatrix, TVector>;

const std::string typeName =
LinearSystem::GetClass()->className
+ LinearSystem::GetCustomTemplateName();

LinearSystemClass<TMatrix, TVector> c(m, typeName.c_str(), sofapython3::doc::linearsystem::linearSystemClass);

c.def("b", getRHSVector<TMatrix, TVector>, sofapython3::doc::linearsystem::linearSystem_b);
c.def("get_rhs_vector", getRHSVector<TMatrix, TVector>, sofapython3::doc::linearsystem::linearSystem_b);

c.def("x", getSolutionVector<TMatrix, TVector>, sofapython3::doc::linearsystem::linearSystem_x);
c.def("get_solution_vector", getSolutionVector<TMatrix, TVector>, sofapython3::doc::linearsystem::linearSystem_x);

bindMatrixAccess<TMatrix, TVector>(c);

/// register the binding in the downcasting subsystem
PythonFactory::registerType<LinearSystem>([](sofa::core::objectmodel::Base* object)
{
return py::cast(dynamic_cast<LinearSystem*>(object));
});
}

}
Loading
Loading