Skip to content
Snippets Groups Projects
ros_publish.cpp 7.02 KiB
Newer Older
#include <stdexcept>

#include <boost/assign.hpp>
#include <boost/bind.hpp>
Thomas Moulard's avatar
Thomas Moulard committed
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/function.hpp>
#include <boost/make_shared.hpp>

#include <ros/ros.h>
#include <std_msgs/Float64.h>
#include <std_msgs/UInt32.h>

#include <dynamic-graph/factory.h>
#include <dynamic-graph/command.h>
#include <dynamic-graph/linear-algebra.h>
#include "dynamic_graph_bridge/ros_init.hh"
  DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(RosPublish, "RosPublish");
  const double RosPublish::ROS_JOINT_STATE_PUBLISHER_RATE = 0.01;
  namespace command
  {
    {
      Clear::Clear
      (RosPublish& entity, const std::string& docstring)
	: Command
	  (entity,
	   std::vector<Value::Type> (),
	   docstring)
      {}

      Value Clear::doExecute ()
      {
	RosPublish& entity =
	  static_cast<RosPublish&> (owner ());

	entity.clear ();
	return Value ();
      }

      List::List
      (RosPublish& entity, const std::string& docstring)
	: Command
	  (entity,
	   std::vector<Value::Type> (),
	   docstring)
      {}

      Value List::doExecute ()
      {
	RosPublish& entity =
	  static_cast<RosPublish&> (owner ());
	return Value (entity.list ());
      (RosPublish& entity, const std::string& docstring)
	: Command
	  (entity,
	   boost::assign::list_of
	   (Value::STRING) (Value::STRING) (Value::STRING),
	   docstring)
      {}

      Value Add::doExecute ()
      {
	RosPublish& entity =
	  static_cast<RosPublish&> (owner ());
	std::vector<Value> values = getParameterValues ();

	const std::string& type = values[0].value ();
	const std::string& signal = values[1].value ();
	const std::string& topic = values[2].value ();

	if (type == "boolean")
	  entity.add<bool> (signal, topic);
        else if (type == "double")
	  entity.add<double> (signal, topic);
	else if (type == "unsigned")
	  entity.add<unsigned int> (signal, topic);
	else if (type == "int")
	  entity.add<int> (signal, topic);
	else if (type == "matrix")
	  entity.add<Matrix> (signal, topic);
	else if (type == "vector")
	  entity.add<Vector> (signal, topic);
	else if (type == "vector3")
	  entity.add<specific::Vector3> (signal, topic);
	else if (type == "vector3Stamped")
	  entity.add<std::pair<specific::Vector3, Vector> > (signal, topic);
	else if (type == "matrixHomo")
	  entity.add<sot::MatrixHomogeneous> (signal, topic);
	else if (type == "matrixHomoStamped")
	  entity.add<std::pair<sot::MatrixHomogeneous, Vector> >
	else if (type == "twist")
	  entity.add<specific::Twist> (signal, topic);
	else if (type == "twistStamped")
	  entity.add<std::pair<specific::Twist, Vector> > (signal, topic);
	else
	  throw std::runtime_error("bad type");
	return Value ();
      }

      Rm::Rm
      (RosPublish& entity, const std::string& docstring)
	: Command
	  (entity,
	   boost::assign::list_of (Value::STRING),
	   docstring)

      Value Rm::doExecute ()
      {
	RosPublish& entity =
	  static_cast<RosPublish&> (owner ());
	std::vector<Value> values = getParameterValues ();
	const std::string& signal = values[0].value ();
	entity.rm (signal);
	return Value ();
      }
    } // end of errorEstimator.
  } // end of namespace command.

  const std::string RosPublish::docstring_
  ("Publish dynamic-graph signals as ROS topics.\n"
   "  Use command \"add\" to publish a new ROS topic.\n");
  RosPublish::RosPublish (const std::string& n)
      // RosPublish do not use callback so do not create a useless spinner.
      nh_ (rosInit (false)),
Thomas Moulard's avatar
Thomas Moulard committed
      bindedSignal_ (),
      trigger_ (boost::bind (&RosPublish::trigger, this, _1, _2),
Thomas Moulard's avatar
Thomas Moulard committed
		sotNOSIGNAL,
		MAKE_SIGNAL_STRING(name, true, "int", "trigger")),
      rate_ (ROS_JOINT_STATE_PUBLISHER_RATE),
      nextPublication_ ()
      nextPublication_ = ros::Time::now ();
    } catch (const std::exception& exc) {
      throw std::runtime_error ("Failed to call ros::Time::now ():" +
				std::string (exc.what ()));
    }
Thomas Moulard's avatar
Thomas Moulard committed
    signalRegistration (trigger_);
    trigger_.setNeedUpdateFromAllChildren (true);

    std::string docstring =
      "\n"
      "  Add a signal writing data to a ROS topic\n"
      "\n"
      "  Input:\n"
      "    - type: string among ['double', 'matrix', 'vector', 'vector3',\n"
      "                          'vector3Stamped', 'matrixHomo', 'matrixHomoStamped',\n"
      "                          'twist', 'twistStamped'],\n"
      "    - signal: the signal name in dynamic-graph,\n"
      "    - topic:  the topic name in ROS.\n"
      "\n";
    addCommand ("add",
		(*this, docstring));
      "  Remove a signal writing data to a ROS topic\n"
      "\n"
      "  Input:\n"
      "    - name of the signal to remove (see method list for the list of signals).\n"
      "\n";
    addCommand ("rm",
		(*this, docstring));
      "  Remove all signals writing data to a ROS topic\n"
    addCommand ("clear",
		(*this, docstring));
      "  List signals writing data to a ROS topic\n"
    addCommand ("list",
		(*this, docstring));
  void RosPublish::display (std::ostream& os) const
  void RosPublish::rm (const std::string& signal)
    if(bindedSignal_.find(signal) == bindedSignal_.end())
      return;

    if(signal == "trigger")
    {
      std::cerr << "The trigger signal should not be removed. Aborting." << std::endl;
      return;
    }

    //lock the mutex to avoid deleting the signal during a call to trigger
    boost::mutex::scoped_lock lock (mutex_);

    signalDeregistration(signal);
    bindedSignal_.erase (signal);
  std::string RosPublish::list () const
    std::string result("[");
    for (std::map<std::string, bindedSignal_t>::const_iterator it =
	   bindedSignal_.begin (); it != bindedSignal_.end (); it++) {
      result += "'" + it->first + "',";
    }
    result += "]";
    return result;
 }
    std::map<std::string, bindedSignal_t>::iterator it = bindedSignal_.begin();
    for(; it!= bindedSignal_.end(); )
    {
      if (it->first != "trigger")
      {
        rm(it->first);
        it = bindedSignal_.begin();
      }
      else
      {
          ++it;
      }
    }
  int& RosPublish::trigger (int& dummy, int t)
Thomas Moulard's avatar
Thomas Moulard committed
  {
    typedef std::map<std::string, bindedSignal_t>::iterator iterator_t;

    if (ros::Time::now() <= nextPublication_)
    nextPublication_ = ros::Time::now() + rate_;
    boost::mutex::scoped_lock lock (mutex_);

Thomas Moulard's avatar
Thomas Moulard committed
    for (iterator_t it = bindedSignal_.begin ();
	 it != bindedSignal_.end (); ++it)
      {
	boost::get<1>(it->second) (t);
Thomas Moulard's avatar
Thomas Moulard committed
      }
    return dummy;
  }

  std::string RosPublish::getDocString () const
} // end of namespace dynamicgraph.