diff --git a/include/spline/exact_cubic.h b/include/spline/exact_cubic.h index 5e7b7a7ac25fe2023a1631f22ca0d4abcdfc97fe..10af708395b363c87e76aabf741faab6707e87da 100644 --- a/include/spline/exact_cubic.h +++ b/include/spline/exact_cubic.h @@ -36,7 +36,8 @@ namespace spline /// crossing each of the waypoint given in its initialization /// template<typename Time= double, typename Numeric=Time, std::size_t Dim=3, bool Safe=false -, typename Point= Eigen::Matrix<Numeric, Dim, 1>, typename T_Point =std::vector<Point,Eigen::aligned_allocator<Point> > > +, typename Point= Eigen::Matrix<Numeric, Dim, 1>, typename T_Point =std::vector<Point,Eigen::aligned_allocator<Point> > +, typename SplineBase=spline_curve<Time, Numeric, Dim, Safe, Point, T_Point> > struct exact_cubic : public curve_abc<Time, Numeric, Dim, Safe, Point> { typedef Point point_t; @@ -44,7 +45,7 @@ struct exact_cubic : public curve_abc<Time, Numeric, Dim, Safe, Point> typedef Eigen::Matrix<Numeric, Eigen::Dynamic, Eigen::Dynamic> MatrixX; typedef Time time_t; typedef Numeric num_t; - typedef spline_curve<time_t, Numeric, Dim, Safe, point_t, t_point_t> spline_t; + typedef SplineBase spline_t; typedef typename std::vector<spline_t> t_spline_t; typedef typename t_spline_t::iterator it_spline_t; typedef typename t_spline_t::const_iterator cit_spline_t; @@ -149,7 +150,7 @@ struct exact_cubic : public curve_abc<Time, Numeric, Dim, Safe, Point> } private: - exact_cubic& operator=(const exact_cubic&); + //exact_cubic& operator=(const exact_cubic&); /* Constructors - destructors */ /*Operations*/ @@ -193,7 +194,7 @@ struct exact_cubic : public curve_abc<Time, Numeric, Dim, Safe, Point> /*Attributes*/ public: - const t_spline_t subSplines_; + t_spline_t subSplines_; // const /*Attributes*/ }; } diff --git a/include/spline/helpers/effector_spline_rotation.h b/include/spline/helpers/effector_spline_rotation.h index a6f4422ba72afb161ea07658cd49d493f526302f..e9f7992639bdecbddcf4f74f478ae9c19163223f 100644 --- a/include/spline/helpers/effector_spline_rotation.h +++ b/include/spline/helpers/effector_spline_rotation.h @@ -21,6 +21,7 @@ #define _CLASS_EFFECTOR_SPLINE_ROTATION #include "spline/helpers/effector_spline.h" +#include "spline/curve_abc.h" #include <Eigen/Geometry> namespace spline @@ -32,19 +33,51 @@ typedef Eigen::Matrix<Numeric, 4, 1> quat_t; typedef Eigen::Ref<quat_t> quat_ref_t; typedef const Eigen::Ref<const quat_t> quat_ref_const_t; typedef Eigen::Matrix<Numeric, 7, 1> config_t; +typedef curve_abc<Time, Numeric, 4, false, quat_t> curve_abc_quat_t; +typedef std::pair<Numeric, quat_t > waypoint_quat_t; +typedef std::vector<waypoint_quat_t> t_waypoint_quat_t; typedef Eigen::Matrix<Numeric, 1, 1> point_one_dim_t; typedef spline_deriv_constraint <Numeric, Numeric, 1, false, point_one_dim_t> spline_deriv_constraint_one_dim; typedef std::pair<Numeric, point_one_dim_t > waypoint_one_dim_t; typedef std::vector<waypoint_one_dim_t> t_waypoint_one_dim_t; -class time_reparametrization_spline: public spline_deriv_constraint_one_dim +class rotation_spline: public curve_abc_quat_t { public: - time_reparametrization_spline() - : spline_deriv_constraint_one_dim(computeWayPoints()){} + rotation_spline (quat_ref_const_t quat_from=quat_t(0,0,0,1), quat_ref_const_t quat_to=quat_t(0,0,0,1), + const double min = 0., const double max = 1.) + : curve_abc_quat_t() + , quat_from_(quat_from.data()), quat_to_(quat_to.data()), min_(min), max_(max) + , time_reparam_(computeWayPoints()) + {} - ~time_reparametrization_spline(){} + ~rotation_spline() {} + + /* Copy Constructors / operator=*/ + rotation_spline& operator=(const rotation_spline& from) + { + quat_from_ = from.quat_from_; + quat_to_ = from.quat_to_; + min_ =from.min_; max_ = from.max_; + time_reparam_ = spline_deriv_constraint_one_dim(from.time_reparam_); + } + /* Copy Constructors / operator=*/ + + quat_t operator()(const Numeric t) const + { + if(t<=min()) return quat_from_.coeffs(); + if(t>=max()) return quat_to_.coeffs(); + //normalize u + Numeric u = (t - min()) /(max() - min()); + // reparametrize u + return quat_from_.slerp(time_reparam_(u)[0], quat_to_).coeffs(); + } + + virtual quat_t derivate(time_t /*t*/, std::size_t /*order*/) const + { + throw std::runtime_error("TODO quaternion spline does not implement derivate"); + } spline_deriv_constraint_one_dim computeWayPoints() const { @@ -54,8 +87,22 @@ class time_reparametrization_spline: public spline_deriv_constraint_one_dim waypoints.push_back(std::make_pair(1,point_one_dim_t::Ones())); return spline_deriv_constraint_one_dim(waypoints.begin(), waypoints.end()); } + + virtual time_t min() const{return min_;} + virtual time_t max() const{return max_;} + + public: + Eigen::Quaterniond quat_from_; //const + Eigen::Quaterniond quat_to_; //const + double min_; //const + double max_; //const + spline_deriv_constraint_one_dim time_reparam_; //const }; + +typedef exact_cubic<Time, Numeric, 4, false, quat_t, std::vector<quat_t,Eigen::aligned_allocator<quat_t> >, rotation_spline> exact_cubic_quat_t; + + /// \class effector_spline_rotation /// \brief Represents a trajectory for and end effector /// uses the method effector_spline to create a spline trajectory. @@ -93,7 +140,40 @@ class effector_spline_rotation , to_quat_(to_quat.data()), land_quat_(land_quat.data()) , time_lift_offset_(spline_->min()+lift_offset_duration) , time_land_offset_(spline_->max()-land_offset_duration) - , rotation_spline_() + , quat_spline_(simple_quat_spline()) + { + // NOTHING + } + + /// \brief Constructor. + /// Given a set of waypoints, and the normal vector of the start and + /// ending positions, automatically create the spline such that: + /// + init and end velocities / accelerations are 0. + /// + the effector lifts and lands exactly in the direction of the specified normals + /// \param wayPointsBegin : an iterator pointing to the first element of a waypoint container + /// \param wayPointsEnd : an iterator pointing to the end of a waypoint container + /// \param quatWayPointsBegin : en iterator pointing to the first element of a 4D vector (x, y, z, w) container of + /// quaternions indicating rotation at specific time steps. + /// \param quatWayPointsEnd : en iterator pointing to the end of a 4D vector (x, y, z, w) container of + /// quaternions indicating rotation at specific time steps. + /// \param lift_normal : normal to be followed by end effector at take-off + /// \param land_normal : normal to be followed by end effector at landing + /// \param lift_offset : length of the straight line along normal at take-off + /// \param land_offset : length of the straight line along normal at landing + /// \param lift_offset_duration : time travelled along straight line at take-off + /// \param land_offset_duration : time travelled along straight line at landing + /// + template<typename In, typename InQuat> + effector_spline_rotation(In wayPointsBegin, In wayPointsEnd, + InQuat quatWayPointsBegin, InQuat quatWayPointsEnd, + const Point& lift_normal=Eigen::Vector3d::UnitZ(), const Point& land_normal=Eigen::Vector3d::UnitZ(), + const Numeric lift_offset=0.02, const Numeric land_offset=0.02, + const Time lift_offset_duration=0.02, const Time land_offset_duration=0.02) + : spline_(effector_spline(wayPointsBegin, wayPointsEnd, lift_normal, land_normal, lift_offset, land_offset, lift_offset_duration, land_offset_duration)) + , to_quat_((quatWayPointsBegin->second).data()), land_quat_(((quatWayPointsEnd-1)->second).data()) + , time_lift_offset_(spline_->min()+lift_offset_duration) + , time_land_offset_(spline_->max()-land_offset_duration) + , quat_spline_(quat_spline(quatWayPointsBegin, quatWayPointsEnd)) { // NOTHING } @@ -122,19 +202,39 @@ class effector_spline_rotation return res; } - - /// \brief Interpolates between two quaternions - /// \param t : the time when to evaluate the spline - /// \param quat : quaternion updated as the interpolation result - /// - quat_t interpolate_quat(Numeric t) const + public: + quat_t interpolate_quat(const Numeric t) const { if(t<=time_lift_offset_) return to_quat_.coeffs(); if(t>=time_land_offset_) return land_quat_.coeffs(); - //normalize u - Numeric u = (t - time_lift_offset_) /(time_land_offset_ - time_lift_offset_); - // reparametrize u - return to_quat_.slerp(rotation_spline_(u)[0], land_quat_).coeffs(); + return quat_spline_(t); + } + + private: + exact_cubic_quat_t simple_quat_spline() const + { + std::vector<rotation_spline> splines; + splines.push_back(rotation_spline(to_quat_.coeffs(),land_quat_.coeffs(),time_lift_offset_, time_land_offset_)); + return exact_cubic_quat_t(splines); + } + + template <typename InQuat> + exact_cubic_quat_t quat_spline(InQuat quatWayPointsBegin, InQuat quatWayPointsEnd) const + { + if(std::distance(quatWayPointsBegin, quatWayPointsEnd) < 1) + return simple_quat_spline(); + exact_cubic_quat_t::t_spline_t splines; + InQuat it(quatWayPointsBegin); + Time init = time_lift_offset_; + Eigen::Quaterniond current_quat = to_quat_; + for(; it != quatWayPointsEnd; ++it) + { + splines.push_back(rotation_spline(current_quat.coeffs(), it->second, init, it->first)); + current_quat = it->second; + init = it->first; + } + splines.push_back(rotation_spline(current_quat.coeffs(), land_quat_.coeffs(), init, time_land_offset_)); + return exact_cubic_quat_t(splines); } /*Operations*/ @@ -146,7 +246,7 @@ class effector_spline_rotation const Eigen::Quaterniond land_quat_; const double time_lift_offset_; const double time_land_offset_; - const time_reparametrization_spline rotation_spline_; // should be static + const exact_cubic_quat_t quat_spline_; /*Attributes*/ }; diff --git a/include/spline/spline_deriv_constraint.h b/include/spline/spline_deriv_constraint.h index b8153381185c5117b3d7ee64df5c22abbb1c8770..07ebe01c8da94bf6f519497a7fbb6b7d4c6b9c5d 100644 --- a/include/spline/spline_deriv_constraint.h +++ b/include/spline/spline_deriv_constraint.h @@ -38,8 +38,9 @@ namespace spline /// template<typename Time= double, typename Numeric=Time, std::size_t Dim=3, bool Safe=false, typename Point= Eigen::Matrix<Numeric, Dim, 1>, - typename T_Point =std::vector<Point,Eigen::aligned_allocator<Point> > > -struct spline_deriv_constraint : public exact_cubic<Time, Numeric, Dim, Safe, Point, T_Point> + typename T_Point =std::vector<Point,Eigen::aligned_allocator<Point> >, + typename SplineBase=spline_curve<Time, Numeric, Dim, Safe, Point, T_Point> > +struct spline_deriv_constraint : public exact_cubic<Time, Numeric, Dim, Safe, Point, T_Point, SplineBase> { typedef Point point_t; typedef T_Point t_point_t; @@ -83,7 +84,6 @@ struct spline_deriv_constraint : public exact_cubic<Time, Numeric, Dim, Safe, Po spline_deriv_constraint(const spline_deriv_constraint& other) : exact_cubic_t(other.subSplines_) {} - private: template<typename In> void compute_one_spline(In wayPointsBegin, In wayPointsNext, spline_constraints& constraints, t_spline_t& subSplines) const @@ -146,7 +146,6 @@ struct spline_deriv_constraint : public exact_cubic<Time, Numeric, Dim, Safe, Po } private: - spline_deriv_constraint& operator=(const spline_deriv_constraint&); /* Constructors - destructors */ }; } diff --git a/src/tests/spline_test/Main.cpp b/src/tests/spline_test/Main.cpp index 84e6108b9a408f91c6ff59ed40ca7f6f6a778de5..2b9022b7000ada01dc20cfa4a50fc222c3513278 100644 --- a/src/tests/spline_test/Main.cpp +++ b/src/tests/spline_test/Main.cpp @@ -429,6 +429,13 @@ helpers::quat_t GetXRotQuat(const double theta) return helpers::quat_t(Eigen::Quaterniond(m).coeffs().data()); } +double GetXRotFromQuat(helpers::quat_ref_const_t q) +{ + Eigen::Quaterniond quat (q.data()); + Eigen::AngleAxisd m (quat); + return m.angle() / M_PI * 180.; +} + void EffectorSplineRotationNoRotationTest(bool& error) { // create arbitrary trajectory @@ -466,7 +473,7 @@ void EffectorSplineRotationRotationTest(bool& error) helpers::config_t q_to = q_init; q_to(2) +=0.02; helpers::config_t q_land = q_end ; q_land(2)+=0.02; helpers::quat_t q_mod = GetXRotQuat(M_PI_2);; - std::string errmsg("Error in EffectorSplineRotationNoRotationTest; while checking waypoints (expected / obtained)"); + std::string errmsg("Error in EffectorSplineRotationRotationTest; while checking waypoints (expected / obtained)"); ComparePoints(q_init, eff_traj(0), errmsg,error); ComparePoints(q_to , eff_traj(0.02), errmsg,error); ComparePoints(q_land, eff_traj(9.98), errmsg,error); @@ -474,9 +481,46 @@ void EffectorSplineRotationRotationTest(bool& error) ComparePoints(q_end , eff_traj(10), errmsg,error); } +void EffectorSplineRotationWayPointRotationTest(bool& error) +{ + // create arbitrary trajectory + spline::T_Waypoint waypoints; + for(double i = 0; i <= 10; i = i + 2) + { + waypoints.push_back(std::make_pair(i,point_t(i,i,i))); + } + helpers::quat_t init_quat = GetXRotQuat(0); + helpers::t_waypoint_quat_t quat_waypoints_; + + + helpers::quat_t q_pi_0 = GetXRotQuat(0); + helpers::quat_t q_pi_2 = GetXRotQuat(M_PI_2); + helpers::quat_t q_pi = GetXRotQuat(M_PI); + + quat_waypoints_.push_back(std::make_pair(0.4,q_pi_0)); + quat_waypoints_.push_back(std::make_pair(6,q_pi_2)); + quat_waypoints_.push_back(std::make_pair(8,q_pi)); + + + helpers::effector_spline_rotation eff_traj(waypoints.begin(),waypoints.end(), + quat_waypoints_.begin(), quat_waypoints_.end()); + helpers::config_t q_init = helpers::config_t::Zero(); q_init.tail<4>() = init_quat; + helpers::config_t q_end; q_end << 10.,10.,10.,0.,0.,0.,1.; q_end.tail<4>() = q_pi; + helpers::config_t q_mod; q_mod.head<3>() = point_t(6,6,6) ; q_mod.tail<4>() = q_pi_2; + helpers::config_t q_to = q_init; q_to(2) +=0.02; + helpers::config_t q_land = q_end ; q_land(2)+=0.02; + std::string errmsg("Error in EffectorSplineRotationWayPointRotationTest; while checking waypoints (expected / obtained)"); + ComparePoints(q_init, eff_traj(0), errmsg,error); + ComparePoints(q_to , eff_traj(0.02), errmsg,error); + ComparePoints(q_land, eff_traj(9.98), errmsg,error); + ComparePoints(q_mod , eff_traj(6), errmsg,error); + ComparePoints(q_end , eff_traj(10), errmsg,error); +} + void TestReparametrization(bool& error) { - helpers::time_reparametrization_spline sp; + helpers::rotation_spline s; + const helpers::spline_deriv_constraint_one_dim& sp = s.time_reparam_; if(sp.min() != 0) { std::cout << "in TestReparametrization; min value is not 0, got " << sp.min() << std::endl; @@ -521,6 +565,7 @@ int main(int /*argc*/, char** /*argv[]*/) EffectorSplineRotationNoRotationTest(error); EffectorSplineRotationRotationTest(error); TestReparametrization(error); + EffectorSplineRotationWayPointRotationTest(error); BezierCurveTest(error); if(error) {