Skip to content
Snippets Groups Projects
ros_queued_subscribe.cpp 7.89 KiB
Newer Older
//
// Copyright (c) 2017-2018 CNRS
// Authors: Joseph Mirabel
//
//

#include <boost/assign.hpp>
#include <boost/bind.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_bridge/ros_init.hh"
#include "ros_queued_subscribe.hh"

Olivier Stasse's avatar
Olivier Stasse committed
namespace dynamicgraph {
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(RosQueuedSubscribe, "RosQueuedSubscribe");

namespace command {
namespace rosQueuedSubscribe {
Clear::Clear(RosQueuedSubscribe& entity, const std::string& docstring)
    : Command(entity, std::vector<Value::Type>(), docstring) {}

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

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

ClearQueue::ClearQueue(RosQueuedSubscribe& entity, const std::string& docstring)
    : Command(entity, boost::assign::list_of(Value::STRING), docstring) {}

Value ClearQueue::doExecute() {
  RosQueuedSubscribe& entity = static_cast<RosQueuedSubscribe&>(owner());

  std::vector<Value> values = getParameterValues();
  const std::string& signal = values[0].value();
  entity.clearQueue(signal);

  return Value();
}

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

Value List::doExecute() {
  RosQueuedSubscribe& entity = static_cast<RosQueuedSubscribe&>(owner());
  return Value(entity.list());
}

Add::Add(RosQueuedSubscribe& entity, const std::string& docstring)
Guilhem Saurel's avatar
Guilhem Saurel committed
    : Command(entity, boost::assign::list_of(Value::STRING)(Value::STRING)(Value::STRING), docstring) {}
Olivier Stasse's avatar
Olivier Stasse committed

Value Add::doExecute() {
  RosQueuedSubscribe& entity = static_cast<RosQueuedSubscribe&>(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 == "double")
    entity.add<double>(type, signal, topic);
  else if (type == "unsigned")
    entity.add<unsigned int>(type, signal, topic);
  else if (type == "matrix")
Joseph Mirabel's avatar
Joseph Mirabel committed
    entity.add<Matrix>(type, signal, topic);
Olivier Stasse's avatar
Olivier Stasse committed
  else if (type == "vector")
Joseph Mirabel's avatar
Joseph Mirabel committed
    entity.add<Vector>(type, signal, topic);
Olivier Stasse's avatar
Olivier Stasse committed
  else if (type == "vector3")
    entity.add<specific::Vector3>(type, signal, topic);
  else if (type == "matrixHomo")
    entity.add<sot::MatrixHomogeneous>(type, signal, topic);
  else if (type == "twist")
    entity.add<specific::Twist>(type, signal, topic);
  else
    throw std::runtime_error("bad type");
  return Value();
}

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

Value Rm::doExecute() {
  RosQueuedSubscribe& entity = static_cast<RosQueuedSubscribe&>(owner());
  std::vector<Value> values = getParameterValues();
  const std::string& signal = values[0].value();
  entity.rm(signal);
  return Value();
}

QueueSize::QueueSize(RosQueuedSubscribe& entity, const std::string& docstring)
    : Command(entity, boost::assign::list_of(Value::STRING), docstring) {}

Value QueueSize::doExecute() {
  RosQueuedSubscribe& entity = static_cast<RosQueuedSubscribe&>(owner());

  std::vector<Value> values = getParameterValues();
  const std::string& signal = values[0].value();

  return Value((unsigned)entity.queueSize(signal));
}

ReadQueue::ReadQueue(RosQueuedSubscribe& entity, const std::string& docstring)
    : Command(entity, boost::assign::list_of(Value::INT), docstring) {}

Value ReadQueue::doExecute() {
  RosQueuedSubscribe& entity = static_cast<RosQueuedSubscribe&>(owner());

  std::vector<Value> values = getParameterValues();
  int read = values[0].value();
  entity.readQueue(read);

  return Value();
}
}  // namespace rosQueuedSubscribe
}  // end of namespace command.

const std::string RosQueuedSubscribe::docstring_(
    "Subscribe to a ROS topics and convert it into a dynamic-graph signals.\n"
    "\n"
    "  Use command \"add\" to subscribe to a new signal.\n");

RosQueuedSubscribe::RosQueuedSubscribe(const std::string& n)
Guilhem Saurel's avatar
Guilhem Saurel committed
    : dynamicgraph::Entity(n), nh_(rosInit(true)), bindedSignal_(), readQueue_(-1) {
Olivier Stasse's avatar
Olivier Stasse committed
  std::string docstring =
      "\n"
      "  Add a signal reading data from a ROS topic\n"
      "\n"
      "  Input:\n"
      "    - type: string among ['double', 'matrix', 'vector', 'vector3',\n"
      "                          'matrixHomo', 'twist'],\n"
      "    - signal: the signal name in dynamic-graph,\n"
      "    - topic:  the topic name in ROS.\n"
      "\n";
Olivier Stasse's avatar
Olivier Stasse committed
  addCommand("add", new command::rosQueuedSubscribe::Add(*this, docstring));
  docstring =
      "\n"
      "  Remove a signal reading data from a ROS topic\n"
      "\n"
      "  Input:\n"
Olivier Stasse's avatar
Olivier Stasse committed
      "    - name of the signal to remove (see method list for the list of "
      "signals).\n"
Olivier Stasse's avatar
Olivier Stasse committed
  addCommand("rm", new command::rosQueuedSubscribe::Rm(*this, docstring));
  docstring =
      "\n"
      "  Remove all signals reading data from a ROS topic\n"
      "\n"
      "  No input:\n"
      "\n";
Olivier Stasse's avatar
Olivier Stasse committed
  addCommand("clear", new command::rosQueuedSubscribe::Clear(*this, docstring));
  docstring =
      "\n"
      "  List signals reading data from a ROS topic\n"
      "\n"
      "  No input:\n"
      "\n";
Olivier Stasse's avatar
Olivier Stasse committed
  addCommand("list", new command::rosQueuedSubscribe::List(*this, docstring));
  docstring =
      "\n"
      "  Empty the queue of a given signal\n"
      "\n"
      "  Input is:\n"
      "    - name of the signal (see method list for the list of signals).\n"
      "\n";
Guilhem Saurel's avatar
Guilhem Saurel committed
  addCommand("clearQueue", new command::rosQueuedSubscribe::ClearQueue(*this, docstring));
Olivier Stasse's avatar
Olivier Stasse committed
  docstring =
      "\n"
      "  Return the queue size of a given signal\n"
      "\n"
      "  Input is:\n"
      "    - name of the signal (see method list for the list of signals).\n"
      "\n";
Guilhem Saurel's avatar
Guilhem Saurel committed
  addCommand("queueSize", new command::rosQueuedSubscribe::QueueSize(*this, docstring));
Olivier Stasse's avatar
Olivier Stasse committed
  docstring =
      "\n"
      "  Whether signals should read values from the queues, and when.\n"
      "\n"
      "  Input is:\n"
      "    - int (dynamic graph time at which the reading begin).\n"
      "\n";
Guilhem Saurel's avatar
Guilhem Saurel committed
  addCommand("readQueue", new command::rosQueuedSubscribe::ReadQueue(*this, docstring));
Olivier Stasse's avatar
Olivier Stasse committed
}
Olivier Stasse's avatar
Olivier Stasse committed
RosQueuedSubscribe::~RosQueuedSubscribe() {}
Guilhem Saurel's avatar
Guilhem Saurel committed
void RosQueuedSubscribe::display(std::ostream& os) const { os << CLASS_NAME << std::endl; }
Olivier Stasse's avatar
Olivier Stasse committed
void RosQueuedSubscribe::rm(const std::string& signal) {
  std::string signalTs = signal + "Timestamp";
Olivier Stasse's avatar
Olivier Stasse committed
  signalDeregistration(signal);
  bindedSignal_.erase(signal);
Olivier Stasse's avatar
Olivier Stasse committed
  if (bindedSignal_.find(signalTs) != bindedSignal_.end()) {
    signalDeregistration(signalTs);
    bindedSignal_.erase(signalTs);
Olivier Stasse's avatar
Olivier Stasse committed
}

std::string RosQueuedSubscribe::list() {
  std::string result("[");
Guilhem Saurel's avatar
Guilhem Saurel committed
  for (std::map<std::string, bindedSignal_t>::const_iterator it = bindedSignal_.begin(); it != bindedSignal_.end();
       it++) {
Olivier Stasse's avatar
Olivier Stasse committed
    result += "'" + it->first + "',";
Olivier Stasse's avatar
Olivier Stasse committed
  result += "]";
  return result;
}

void RosQueuedSubscribe::clear() {
  std::map<std::string, bindedSignal_t>::iterator it = bindedSignal_.begin();
  for (; it != bindedSignal_.end();) {
    rm(it->first);
    it = bindedSignal_.begin();
Olivier Stasse's avatar
Olivier Stasse committed
}
Olivier Stasse's avatar
Olivier Stasse committed
void RosQueuedSubscribe::clearQueue(const std::string& signal) {
  if (bindedSignal_.find(signal) != bindedSignal_.end()) {
    bindedSignal_[signal]->clear();
Olivier Stasse's avatar
Olivier Stasse committed
}
Olivier Stasse's avatar
Olivier Stasse committed
std::size_t RosQueuedSubscribe::queueSize(const std::string& signal) const {
Guilhem Saurel's avatar
Guilhem Saurel committed
  std::map<std::string, bindedSignal_t>::const_iterator _bs = bindedSignal_.find(signal);
Olivier Stasse's avatar
Olivier Stasse committed
  if (_bs != bindedSignal_.end()) {
    return _bs->second->size();
Olivier Stasse's avatar
Olivier Stasse committed
  return -1;
}

void RosQueuedSubscribe::readQueue(int beginReadingAt) {
  // Prints signal queues sizes
  /*for (std::map<std::string, bindedSignal_t>::const_iterator it =
         bindedSignal_.begin (); it != bindedSignal_.end (); it++) {
    std::cout << it->first << " : " << it->second->size() << '\n';
  }*/
  readQueue_ = beginReadingAt;
}

std::string RosQueuedSubscribe::getDocString() const { return docstring_; }
}  // end of namespace dynamicgraph.