Commit 4fd70d49 authored by Justin Carpentier's avatar Justin Carpentier
Browse files

Merge pull request #23 from fvalenza/master

Refactoring index, and fixing python "se3ToXYZQuat"
parents 8faae27f 34455eec
......@@ -2,6 +2,7 @@ language: cpp
sudo: required
compiler:
- gcc
- clang
env:
global:
- secure: "SnIBG/xLIHX3CSvUbqqsX8xTVqIqQ7fFS6HWO6KZQVBsT6yugTwYHbyhNiU531JejYJ/I3ZrDhXfYH3qFZiYxnH1sifvwV+fnTtMXpPN7qPZwIymkjcmm6gJF51e0C7VOfUbvKFv0ngwj+ul21rgZSMuoEvxPK0WxtE3/ZSfn9c="
......@@ -14,10 +15,10 @@ branches:
only:
- master
- debian
- topic/travis
- devel
matrix:
allow_failures:
- compiler: clang
- compiler:
script: ./.travis/run ../travis_custom/custom_build
after_success: ./travis/run after_success
after_failure: ./.travis/run after_failure
......
#
# Copyright 2014 CNRS
# Copyright (c) 2015 CNRS
#
# This file is part of Pinocchio
# hpp-core 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
# 3 of the License, or (at your option) any later version.
# hpp-core 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 Lesser Public License for more details. You should have
# received a copy of the GNU Lesser General Public License along with
# hpp-core If not, see
# <http://www.gnu.org/licenses/>.
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
......
Copyright (c) 2015, Stack Of Tasks development team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Copyright (c) 2015 CNRS
#
# This file is part of Pinocchio
# Pinocchio 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
# 3 of the License, or (at your option) any later version.
# Pinocchio 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 Lesser Public License for more details. You should have
# received a copy of the GNU Lesser General Public License along with
# Pinocchio If not, see
# <http://www.gnu.org/licenses/>.
MACRO(ADD_GROUP GROUP_NAME FILENAMES)
FOREACH(filename ${${FILENAMES}})
GET_FILENAME_COMPONENT(filenamePath ${filename} PATH)
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_center_of_mass_hpp__
#define __se3_center_of_mass_hpp__
......@@ -55,8 +72,8 @@ namespace se3
using namespace Eigen;
using namespace se3;
const std::size_t & i = jmodel.id();
const std::size_t & parent = model.parents[i];
const Model::Index & i = (Model::Index) jmodel.id();
const Model::Index & parent = model.parents[i];
jmodel.calc(jdata.derived(),q);
......@@ -80,13 +97,13 @@ namespace se3
data.mass[0] = 0;
data.com[0].setZero ();
for( int i=1;i<model.nbody;++i )
for( Model::Index i=1;i<(Model::Index)(model.nbody);++i )
{
data.com[i] = model.inertias[i].mass()*model.inertias[i].lever();
data.mass[i] = model.inertias[i].mass();
}
for( int i=model.nbody-1;i>0;--i )
for( Model::Index i=(Model::Index)(model.nbody-1);i>0;--i )
{
CenterOfMassForwardStep
::run(model.joints[i],data.joints[i],
......@@ -125,7 +142,7 @@ namespace se3
using namespace Eigen;
using namespace se3;
const Model::Index & i = jmodel.id();
const Model::Index & i = (Model::Index) jmodel.id();
const Model::Index & parent = model.parents[i];
jmodel.calc(jdata.derived(),q);
......@@ -160,7 +177,7 @@ namespace se3
using namespace Eigen;
using namespace se3;
const Model::Index & i = jmodel.id();
const Model::Index & i = (Model::Index) jmodel.id();
const Model::Index & parent = model.parents[i];
data.com[parent] += data.com[i];
......@@ -192,13 +209,13 @@ namespace se3
{
data.com[0].setZero ();
data.mass[0] = 0;
for( int i=1;i<model.nbody;++i )
for( Model::Index i=1;i<(Model::Index)model.nbody;++i )
{
JacobianCenterOfMassForwardStep
::run(model.joints[i],data.joints[i],
JacobianCenterOfMassForwardStep::ArgsType(model,data,q));
}
for( int i=model.nbody-1;i>0;--i )
for( Model::Index i= (Model::Index) (model.nbody-1);i>0;--i )
{
JacobianCenterOfMassBackwardStep
::run(model.joints[i],data.joints[i],
......
clear U L M parent tree
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
parent = [ 0 1 2 3 2 5 2 7 8 9 8 11 ];
%parent = [ 0 1 2 3 2 5 2 7 8 9 10 8 12 13 ];
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_cholesky_hpp__
#define __se3_cholesky_hpp__
......@@ -59,7 +76,7 @@ namespace se3
for(int j=model.nv-1;j>=0;--j )
{
const int NVT = data.nvSubtree_fromRow[j]-1;
const int NVT = data.nvSubtree_fromRow[(Model::Index)j]-1;
Eigen::VectorXd::SegmentReturnType DUt = data.tmp.head(NVT);
if(NVT)
DUt = U.row(j).segment(j+1,NVT).transpose()
......@@ -67,7 +84,7 @@ namespace se3
D[j] = M(j,j) - U.row(j).segment(j+1,NVT) * DUt;
for( int _i=data.parents_fromRow[j];_i>=0;_i=data.parents_fromRow[_i] )
for( int _i=data.parents_fromRow[(Model::Index)j];_i>=0;_i=data.parents_fromRow[(Model::Index)_i] )
U(_i,j) = (M(_i,j) - U.row(_i).segment(j+1,NVT).dot(DUt)) / D[j];
}
......@@ -88,7 +105,7 @@ namespace se3
const std::vector<int> & nvt = data.nvSubtree_fromRow;
for( int k=0;k<model.nv-1;++k ) // You can stop one step before nv
v[k] += U.row(k).segment(k+1,nvt[k]-1) * v.segment(k+1,nvt[k]-1);
v[k] += U.row(k).segment(k+1,nvt[(Model::Index)k]-1) * v.segment(k+1,nvt[(Model::Index)k]-1);
return v.derived();
}
......@@ -106,7 +123,7 @@ namespace se3
const Eigen::MatrixXd & U = data.U;
const std::vector<int> & nvt = data.nvSubtree_fromRow;
for( int i=model.nv-2;i>=0;--i ) // You can start from nv-2 (no child in nv-1)
v.segment(i+1,nvt[i]-1) += U.row(i).segment(i+1,nvt[i]-1).transpose()*v[i];
v.segment(i+1,nvt[(Model::Index)i]-1) += U.row(i).segment(i+1,nvt[(Model::Index)i]-1).transpose()*v[i];
return v.derived();
}
......@@ -129,7 +146,7 @@ namespace se3
const std::vector<int> & nvt = data.nvSubtree_fromRow;
for( int k=model.nv-2;k>=0;--k ) // You can start from nv-2 (no child in nv-1)
v[k] -= U.row(k).segment(k+1,nvt[k]-1) * v.segment(k+1,nvt[k]-1);
v[k] -= U.row(k).segment(k+1,nvt[(Model::Index)k]-1) * v.segment(k+1,nvt[(Model::Index)k]-1);
return v.derived();
}
......@@ -148,7 +165,7 @@ namespace se3
const Eigen::MatrixXd & U = data.U;
const std::vector<int> & nvt = data.nvSubtree_fromRow;
for( int i=0;i<model.nv-1;++i ) // You can stop one step before nv.
v.segment(i+1,nvt[i]-1) -= U.row(i).segment(i+1,nvt[i]-1).transpose()*v[i];
v.segment(i+1,nvt[(Model::Index)i]-1) -= U.row(i).segment(i+1,nvt[(Model::Index)i]-1).transpose()*v[i];
return v.derived();
}
......@@ -170,8 +187,8 @@ namespace se3
for( int k=model.nv-1;k>=0;--k )
{
res[k] = M.row(k).segment(k,nvt[k]) * v.segment(k,nvt[k]);
res.segment(k+1,nvt[k]-1) += M.row(k).segment(k+1,nvt[k]-1).transpose()*v[k];
res[k] = M.row(k).segment(k,nvt[(Model::Index)k]) * v.segment(k,nvt[(Model::Index)k]);
res.segment(k+1,nvt[(Model::Index)k]-1) += M.row(k).segment(k+1,nvt[(Model::Index)k]-1).transpose()*v[k];
}
return res;
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_crba_hpp__
#define __se3_crba_hpp__
......@@ -37,7 +54,7 @@ namespace se3
using namespace Eigen;
using namespace se3;
const typename JointModel::Index & i = jmodel.id();
const Model::Index & i = (Model::Index) jmodel.id();
jmodel.calc(jdata.derived(),q);
data.liMi[i] = model.jointPlacements[i]*jdata.M();
......@@ -66,7 +83,7 @@ namespace se3
* Yli += liXi Yi
* F[1:6,SUBTREE] = liXi F[1:6,SUBTREE]
*/
const Model::Index & i = jmodel.id();
const Model::Index & i = (Model::Index) jmodel.id();
/* F[1:6,i] = Y*S */
data.Fcrb[i].block<6,JointModel::NV>(0,jmodel.idx_v()) = data.Ycrb[i] * jdata.S();
......@@ -100,13 +117,13 @@ namespace se3
crba(const Model & model, Data& data,
const Eigen::VectorXd & q)
{
for( int i=1;i<model.nbody;++i )
for( Model::Index i=1;i<(Model::Index)(model.nbody);++i )
{
CrbaForwardStep::run(model.joints[i],data.joints[i],
CrbaForwardStep::ArgsType(model,data,q));
}
for( int i=model.nbody-1;i>0;--i )
for( Model::Index i=(Model::Index)(model.nbody-1);i>0;--i )
{
CrbaBackwardStep::run(model.joints[i],data.joints[i],
CrbaBackwardStep::ArgsType(model,data));
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_jacobian_hpp__
#define __se3_jacobian_hpp__
......@@ -36,7 +53,7 @@ namespace se3
using namespace Eigen;
using namespace se3;
const Model::Index & i = jmodel.id();
const Model::Index & i = (Model::Index) jmodel.id();
const Model::Index & parent = model.parents[i];
jmodel.calc(jdata.derived(),q);
......@@ -55,7 +72,7 @@ namespace se3
computeJacobians(const Model & model, Data& data,
const Eigen::VectorXd & q)
{
for( int i=1;i<model.nbody;++i )
for( Model::Index i=1; i< (Model::Index) model.nbody;++i )
{
JacobiansForwardStep::run(model.joints[i],data.joints[i],
JacobiansForwardStep::ArgsType(model,data,q));
......@@ -76,7 +93,7 @@ namespace se3
const SE3 & oMjoint = data.oMi[jointId];
int colRef = nv(model.joints[jointId])+idx_v(model.joints[jointId])-1;
for(int j=colRef;j>=0;j=data.parents_fromRow[j])
for(int j=colRef;j>=0;j=data.parents_fromRow[(Model::Index)j])
{
if(! localFrame ) J.col(j) = data.J.col(j);
else J.col(j) = oMjoint.actInv(Motion(data.J.col(j))).toVector();
......@@ -103,7 +120,7 @@ namespace se3
using namespace Eigen;
using namespace se3;
const Model::Index & i = jmodel.id();
const Model::Index & i = (Model::Index) jmodel.id();
const Model::Index & parent = model.parents[i];
jmodel.calc(jdata.derived(),q);
......@@ -123,7 +140,7 @@ namespace se3
const Model::Index & idx )
{
data.iMf[idx] = SE3::Identity();
for( int i=idx;i>0;i=model.parents[i] )
for( Model::Index i=idx;i>0;i=model.parents[i] )
{
JacobianForwardStep::run(model.joints[i],data.joints[i],
JacobianForwardStep::ArgsType(model,data,q));
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_kinematics_hpp__
#define __se3_kinematics_hpp__
......@@ -24,7 +41,7 @@ namespace se3
{
typedef boost::fusion::vector<const se3::Model &,
se3::Data &,
const int &,
const Model::Index,
const Eigen::VectorXd &
> ArgsType;
......@@ -35,7 +52,7 @@ namespace se3
se3::JointDataBase<typename JointModel::JointData> & jdata,
const se3::Model & model,
se3::Data & data,
const int & i,
const Model::Index i,
const Eigen::VectorXd & q)
{
using namespace se3;
......@@ -58,7 +75,7 @@ namespace se3
Data & data,
const Eigen::VectorXd & q)
{
for (size_t i=1; i < (size_t) model.nbody; ++i)
for (Model::Index i=1; i < (Model::Index) model.nbody; ++i)
{
GeometryStep::run(model.joints[i],
data.joints[i],
......@@ -71,7 +88,7 @@ namespace se3
{
typedef boost::fusion::vector< const se3::Model&,
se3::Data&,
const int&,
const Model::Index,
const Eigen::VectorXd &,
const Eigen::VectorXd &
> ArgsType;
......@@ -83,7 +100,7 @@ namespace se3
se3::JointDataBase<typename JointModel::JointData> & jdata,
const se3::Model& model,
se3::Data& data,
const int &i,
const Model::Index i,
const Eigen::VectorXd & q,
const Eigen::VectorXd & v)
{
......@@ -114,7 +131,7 @@ namespace se3
{
data.v[0] = Motion::Zero();
for( int i=1;i<model.nbody;++i )
for( Model::Index i=1; i<(Model::Index) model.nbody; ++i )
{
KinematicsStep::run(model.joints[i],data.joints[i],
KinematicsStep::ArgsType(model,data,i,q,v));
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_non_linear_effects_hpp__
#define __se3_non_linear_effects_hpp__
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_rnea_hpp__
#define __se3_rnea_hpp__
......@@ -44,16 +61,16 @@ namespace se3
jmodel.calc(jdata.derived(),q,v);
const Model::Index & parent = model.parents[i];
data.liMi[i] = model.jointPlacements[i]*jdata.M();
const Model::Index & parent = model.parents[(Model::Index)i];
data.liMi[(Model::Index)i] = model.jointPlacements[(Model::Index)i]*jdata.M();
data.v[i] = jdata.v();
if(parent>0) data.v[i] += data.liMi[i].actInv(data.v[parent]);
data.v[(Model::Index)i] = jdata.v();
if(parent>0) data.v[(Model::Index)i] += data.liMi[(Model::Index)i].actInv(data.v[parent]);
data.a[i] = jdata.S()*jmodel.jointMotion(a) + jdata.c() + (data.v[i] ^ jdata.v()) ;
data.a[i] += data.liMi[i].actInv(data.a[parent]);
data.a[(Model::Index)i] = jdata.S()*jmodel.jointMotion(a) + jdata.c() + (data.v[(Model::Index)i] ^ jdata.v()) ;
data.a[(Model::Index)i] += data.liMi[(Model::Index)i].actInv(data.a[parent]);
data.f[i] = model.inertias[i]*data.a[i] + model.inertias[i].vxiv(data.v[i]); // -f_ext
data.f[(Model::Index)i] = model.inertias[(Model::Index)i]*data.a[(Model::Index)i] + model.inertias[(Model::Index)i].vxiv(data.v[(Model::Index)i]); // -f_ext
return 0;
}
......@@ -74,9 +91,9 @@ namespace se3
Data& data,
int i)
{
const Model::Index & parent = model.parents[i];
jmodel.jointForce(data.tau) = jdata.S().transpose()*data.f[i];
if(parent>0) data.f[parent] += data.liMi[i].act(data.f[i]);
const Model::Index & parent = model.parents[(Model::Index)i];
jmodel.jointForce(data.tau) = jdata.S().transpose()*data.f[(Model::Index)i];
if(parent>0) data.f[(Model::Index)parent] += data.liMi[(Model::Index)i].act(data.f[(Model::Index)i]);
}
};
......@@ -91,13 +108,13 @@ namespace se3
for( int i=1;i<model.nbody;++i )
{
RneaForwardStep::run(model.joints[i],data.joints[i],
RneaForwardStep::run(model.joints[(Model::Index)i],data.joints[(Model::Index)i],
RneaForwardStep::ArgsType(model,data,i,q,v,a));
}
for( int i=model.nbody-1;i>0;--i )
{
RneaBackwardStep::run(model.joints[i],data.joints[i],
RneaBackwardStep::run(model.joints[(Model::Index)i],data.joints[(Model::Index)i],
RneaBackwardStep::ArgsType(model,data,i));
}
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.
#ifndef __se3_assert_hpp__
#define __se3_assert_hpp__
......
//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio 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
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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 Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with