Skip to content
Snippets Groups Projects
Forked from Stack Of Tasks / dynamic_graph_bridge
101 commits behind the upstream repository.
robot_model.cpp 4.62 KiB
#include "robot_model.hh"

#include <dynamic-graph/all-commands.h>
#include <dynamic-graph/factory.h>
#include <pinocchio/multibody/parser/urdf.hpp>
#include <pinocchio/multibody/model.hpp>

#include "dynamic_graph_bridge/ros_init.hh"

#include <ros/package.h>

namespace dynamicgraph {

RosRobotModel::RosRobotModel(const std::string& name)
    : Dynamic(name), jointsParameterName_("jrl_map"), ns_("sot_controller") {
  std::string docstring;

  docstring =
      "\n"
      "  Load the robot model from the parameter server.\n"
      "\n"
      "  This is the recommended method.\n"
      "\n";
  addCommand("loadFromParameterServer",
             command::makeCommandVoid0(*this, &RosRobotModel::loadFromParameterServer, docstring));

  docstring =
      "\n"
      "  Load the robot model from an URDF file.\n"
      "\n";
  addCommand("loadUrdf", command::makeCommandVoid1(*this, &RosRobotModel::loadUrdf, docstring));

  docstring =
      "\n"
      "  Set the controller namespace."
      "\n";
  addCommand("setNamespace", command::makeCommandVoid1(*this, &RosRobotModel::setNamespace, docstring));

  docstring =
      "\n"
      "  Get current configuration of the robot.\n"
      "\n";
  addCommand("curConf", new command::Getter<RosRobotModel, Vector>(*this, &RosRobotModel::curConf, docstring));

  docstring =
      "\n"
      "  Maps a link name in the URDF parser to actual robot link name.\n"
      "\n";
  addCommand("addJointMapping", command::makeCommandVoid2(*this, &RosRobotModel::addJointMapping, docstring));
}

RosRobotModel::~RosRobotModel() {}

void RosRobotModel::loadUrdf(const std::string& filename) {
  rosInit(false);
  m_model = se3::urdf::buildModel(filename);
  this->m_urdfPath = filename;
  if (m_data) delete m_data;
  m_data = new se3::Data(m_model);
  init = true;

  //  m_HDR = parser.parse(filename);
  ros::NodeHandle nh(ns_);

  XmlRpc::XmlRpcValue JointsNamesByRank_;
  JointsNamesByRank_.setSize(m_model.names.size());
  std::vector<std::string>::const_iterator it =
      m_model.names.begin() + 2;  // first joint is universe, second is freeflyer
  for (int i = 0; it != m_model.names.end(); ++it, ++i) JointsNamesByRank_[i] = (*it);
  nh.setParam(jointsParameterName_, JointsNamesByRank_);
}

void RosRobotModel::setNamespace(const std::string& ns) { ns_ = ns; }

void RosRobotModel::loadFromParameterServer() {
  rosInit(false);
  std::string robotDescription;
  ros::param::param<std::string>("/robot_description", robotDescription, "");
  if (robotDescription.empty()) throw std::runtime_error("No model available as ROS parameter. Fail.");
  ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDF(robotDescription);
  if (urdfTree)
    se3::urdf::parseTree(urdfTree->getRoot(), this->m_model, se3::SE3::Identity(), false);
  else {
    const std::string exception_message("robot_description not parsed correctly.");
    throw std::invalid_argument(exception_message);
  }

  this->m_urdfPath = "";
  if (m_data) delete m_data;
  m_data = new se3::Data(m_model);
  init = true;
  ros::NodeHandle nh(ns_);

  XmlRpc::XmlRpcValue JointsNamesByRank_;
  JointsNamesByRank_.setSize(m_model.names.size());
  // first joint is universe, second is freeflyer
  std::vector<std::string>::const_iterator it = m_model.names.begin() + 2;
  for (int i = 0; it != m_model.names.end(); ++it, ++i) JointsNamesByRank_[i] = (*it);
  nh.setParam(jointsParameterName_, JointsNamesByRank_);
}

Vector RosRobotModel::curConf() const {
  // The first 6 dofs are associated to the Freeflyer frame
  // Freeflyer reference frame should be the same as global
  // frame so that operational point positions correspond to
  // position in freeflyer frame.
  XmlRpc::XmlRpcValue ffpose;
  ros::NodeHandle nh(ns_);
  std::string param_name = "ffpose";
  if (nh.hasParam(param_name)) {
    nh.getParam(param_name, ffpose);
    ROS_ASSERT(ffpose.getType() == XmlRpc::XmlRpcValue::TypeArray);
    ROS_ASSERT(ffpose.size() == 6);
    for (int32_t i = 0; i < ffpose.size(); ++i) {
      ROS_ASSERT(ffpose[i].getType() == XmlRpc::XmlRpcValue::TypeDouble);
    }
  } else {
    ffpose.setSize(6);
    for (int32_t i = 0; i < ffpose.size(); ++i) ffpose[i] = 0.0;
  }

  if (!m_data)
    throw std::runtime_error("no robot loaded");
  else {
    // TODO: confirm accesscopy is for asynchronous commands
    Vector currConf = jointPositionSIN.accessCopy();
    for (int32_t i = 0; i < ffpose.size(); ++i) currConf(i) = static_cast<double>(ffpose[i]);

    return currConf;
  }
}

void RosRobotModel::addJointMapping(const std::string& link, const std::string& repName) {
  specialJoints_[link] = repName;
}

DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(RosRobotModel, "RosRobotModel");
}  // end of namespace dynamicgraph.