Skip to content
Snippets Groups Projects
handle.cc 6.77 KiB
///
/// Copyright (c) 2014 CNRS
/// Authors: Florent Lamiraux
///
///
// This file is part of hpp-manipulation.
// hpp-manipulation 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-manipulation 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-manipulation. If not, see
// <http://www.gnu.org/licenses/>.

#include <hpp/manipulation/handle.hh>

#include <boost/assign/list_of.hpp>

#include <pinocchio/multibody/joint/joint.hpp>

#include <hpp/util/debug.hh>

#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/joint.hh>
#include <hpp/pinocchio/gripper.hh>

#include <hpp/constraints/generic-transformation.hh>

#include <hpp/core/numerical-constraint.hh>
#include <hpp/core/explicit-numerical-constraint.hh>
#include <hpp/core/explicit-relative-transformation.hh>

namespace hpp {
  namespace manipulation {
    namespace {
      static const matrix3_t I3 = matrix3_t::Identity();

      struct ZeroDiffFunc : public constraints::DifferentiableFunction {
        ZeroDiffFunc (size_type sIn, size_type sInD,
            std::string name=std::string("Empty function"))
          : DifferentiableFunction (sIn, sInD, LiegroupSpace::empty (), name)
        {
          context ("Grasp complement");
        }

        inline void impl_compute (LiegroupElement&, vectorIn_t) const {}
        inline void impl_jacobian (matrixOut_t, vectorIn_t) const {}
      };
    }

    using core::ExplicitNumericalConstraint;
    using constraints::DifferentiableFunction;

    bool isHandleOnFreeflyer (const Handle& handle)
    {
      if (handle.joint()->jointModel().shortname() == se3::JointModelFreeFlyer::classname()
          && !handle.joint ()->parentJoint ()) {
	return true;
      }
      return false;
    }

    inline bool is6Dmask (const std::vector<bool>& mask)
    {
      for (std::size_t i = 0; i < 6; ++i) if (!mask[i]) return false;
      return true;
    }

    inline std::vector<bool> complementMask (const std::vector<bool>& mask)
    {
      std::vector<bool> m(6);
      for (std::size_t i = 0; i < 6; ++i) m[i] = !mask[i];
      return m;
    }

    inline std::string maskToStr (const std::vector<bool>& mask)
    {
      std::stringstream ss;
      ss << "(";
      for (std::size_t i = 0; i < 5; ++i) ss << mask[i] << ",";
      ss << mask[5] << ")";
      return ss.str();
    }

    void Handle::mask (const std::vector<bool>& mask)
    {
      assert(mask.size() == 6);
      std::size_t nRotFree = 3;
      for (std::size_t i = 3; i < 6; ++i)
        if (mask[i]) nRotFree--;
      switch (nRotFree) {
        case 1: // TODO we should check the axis are properly aligned.
          break;
        case 2: // This does not make sense.
          throw std::logic_error("It is not allowed to constrain only one rotation");
          break;
      } 
      mask_ = mask;
    }

    NumericalConstraintPtr_t Handle::createGrasp
    (const GripperPtr_t& gripper, std::string n) const
    {
      using core::ExplicitRelativeTransformation;
      // If handle is on a freeflying object, create an explicit constraint
      if (is6Dmask(mask_) && isHandleOnFreeflyer (*this)) {
        if (n.empty())
          n = "Explicit_relative_transform_" + name() + "_" + gripper->name();
	return ExplicitRelativeTransformation::create
	  (n, gripper->joint ()->robot (), gripper->joint (), joint (),
	   gripper->objectPositionInJoint (), localPosition())->createNumericalConstraint();
      }
      if (n.empty())
        n = "Grasp_" + maskToStr(mask_) + "_" + name() + "_" + gripper->name();
      return NumericalConstraintPtr_t
	(NumericalConstraint::create (RelativeTransformation::create
				      (n,
				       gripper->joint()->robot(),
				       gripper->joint (), joint (),
				       gripper->objectPositionInJoint (),
				       localPosition(), mask_)));
    }

    NumericalConstraintPtr_t Handle::createGraspComplement
    (const GripperPtr_t& gripper, std::string n) const
    {
      core::DevicePtr_t robot = gripper->joint()->robot();
      if (is6Dmask(mask_)) {
        if (n.empty())
          n = "GraspComp_(0,0,0,0,0,0)_" + name () + "_" + gripper->name ();
        return NumericalConstraint::create (
            boost::shared_ptr <ZeroDiffFunc> (new ZeroDiffFunc (
                robot->configSize(), robot->numberDof (), n))
            );
      } else {
        // TODO handle cases where rotations or translation are allowed.
        std::vector<bool> Cmask = complementMask(mask_);
        if (n.empty())
          n = "Transformation_" + maskToStr(Cmask) + "_" + name ()
            + "_" + gripper->name ();
        RelativeTransformationPtr_t function = RelativeTransformation::create
          (n,
           gripper->joint()->robot(),
           gripper->joint (), joint (),
           gripper->objectPositionInJoint (),
           localPosition(), Cmask);
        return NumericalConstraintPtr_t (NumericalConstraint::create
            (function,
             core::ComparisonTypes::create(function->outputSize(),
                                           core::ComparisonType::Equality)
             ));
      }
    }

    NumericalConstraintPtr_t Handle::createPreGrasp
    (const GripperPtr_t& gripper, const value_type& shift, std::string n) const
    {
      using boost::assign::list_of;
      Transform3f transform = gripper->objectPositionInJoint ()
        * Transform3f (I3, vector3_t (shift,0,0));
      if (n.empty())
        n = "Pregrasp_ " + maskToStr(mask_) + "_" + name ()
          + "_" + gripper->name ();
      return NumericalConstraintPtr_t
	(NumericalConstraint::create (RelativeTransformation::create
				      (n,
				       gripper->joint()->robot(),
				       gripper->joint (), joint (),
                                       transform, localPosition(), mask_)));
    }

    HandlePtr_t Handle::clone () const
    {
      HandlePtr_t other = Handle::create (name (), localPosition (), joint ());
      other->mask(mask_);
      other->clearance(clearance_);
      return other;
    }

    std::ostream& Handle::print (std::ostream& os) const
    {
      os << "name :" << name () << std::endl;
      os << "local position :" << localPosition () << std::endl;
      os << "joint :" << joint ()->name () << std::endl;
      os << "mask :" << maskToStr (mask()) << std::endl;
      return os;
    }

    std::ostream& operator<< (std::ostream& os, const Handle& handle)
    {
      return handle.print (os);
    }
  } // namespace manipulation
} // namespace hpp