CConnectionManager.cpp
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2016, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 
11 
12 using namespace mrpt::graphslam::detail;
13 using namespace std;
14 using namespace mrpt::utils;
15 using namespace mrpt::system;
16 using namespace mrpt::math;
17 using namespace multimaster_msgs_fkie;
18 
20  const multimaster_msgs_fkie::ROSMaster& master1,
21  const multimaster_msgs_fkie::ROSMaster& master2) {
22  return master1.uri == master2.uri;
23 }
25  const multimaster_msgs_fkie::ROSMaster& master1,
26  const multimaster_msgs_fkie::ROSMaster& master2) {
27  return !(master1 == master2);
28 }
29 
31  const mrpt_msgs::GraphSlamAgent& agent1,
32  const mrpt_msgs::GraphSlamAgent& agent2) {
33  return (
34  agent1.agent_ID == agent2.agent_ID &&
35  agent1.topic_namespace.data == agent2.topic_namespace.data);
36 }
38 
40  const mrpt_msgs::GraphSlamAgent& agent1,
41  const mrpt_msgs::GraphSlamAgent& agent2) {
42  return !(agent1 == agent2);
43 }
44 
45 bool operator<(
46  const mrpt_msgs::GraphSlamAgent& agent1,
47  const mrpt_msgs::GraphSlamAgent& agent2) {
48  return agent1.agent_ID < agent2.agent_ID;
49 }
51 
53  const multimaster_msgs_fkie::ROSMaster& master,
54  const mrpt_msgs::GraphSlamAgent& agent) {
55  return (master.name == agent.name.data);
56 }
57 
59  const multimaster_msgs_fkie::ROSMaster& master,
60  const mrpt_msgs::GraphSlamAgent& agent) {
61  return !(master == agent);
62 }
63 
65  const mrpt_msgs::GraphSlamAgent& agent,
66  const multimaster_msgs_fkie::ROSMaster& master) {
67  return (master == agent);
68 }
70  const mrpt_msgs::GraphSlamAgent& agent,
71  const multimaster_msgs_fkie::ROSMaster& master) {
72  return (master != agent);
73 }
74 
76 
78  mrpt::utils::COutputLogger* logger,
79  ros::NodeHandle* nh_in):
80  m_logger(logger),
81  m_nh(nh_in),
82  has_setup_comm(false)
83 {
84 
86  ASSERT_(m_nh);
87 
88  {
89  std::string own_ns_tmp = m_nh->getNamespace();
90  // ignore starting "/" characters
91  own_ns = std::string(
92  own_ns_tmp.begin() + own_ns_tmp.find_first_not_of(" /"),
93  own_ns_tmp.end());
94  }
95 
96  // keep this call below the topic names initializations
97  this->setupComm();
98 
99 }
100 
102 
103 const std::string& CConnectionManager::getTrimmedNs() const {
104  return own_ns;
105 }
106 
108  mrpt_msgs::GraphSlamAgents* agents_vec,
109  bool ignore_self/*= true */) {
110 
111 
112  ASSERTMSG_(agents_vec, "Invalid pointer to vector of GraphSlam Agents.");
113  this->updateNearbySlamAgents();
114  *agents_vec = m_nearby_slam_agents;
115 
116  if (ignore_self) {
117  // remove the GraphSlamAgent instance whose topic namespace coincedes with
118  // the namespace that the CConnectionManager instance is running under.
119  auto search = [this](const mrpt_msgs::GraphSlamAgent& agent) {
120  return (agent.topic_namespace.data == this->own_ns);
121  };
122  agents_it it = find_if(
123  agents_vec->list.begin(),
124  agents_vec->list.end(), search);
125 
126  // TODO - fix the following
127  // this agent should always exist
128  // TODO - well, sometimes it doesn't, investigate this
129  // UPDATE: Even when /master_discovery node is up the agents vector might
130  // be empty.
131  //ASSERT_(it != agents_vec->list.end());
132  if (it != agents_vec->list.end()) {
133  agents_vec->list.erase(it);
134  }
135  else {
136  }
137  }
138 }
139 
140 const mrpt_msgs::GraphSlamAgents&
142  return m_nearby_slam_agents;
143 }
144 
145 const mrpt_msgs::GraphSlamAgents&
147  this->updateNearbySlamAgents();
148  return this->getNearbySlamAgentsCached();
149 } // end of getNearbySlamAgents
150 
152  using ::operator==;
153  using namespace mrpt::utils;
154  using namespace mrpt::math;
156 
157  DiscoverMasters srv;
158 
159  // ask for the agents in the neighborhood
161  std::vector<ROSMaster>* masters = &(srv.response.masters);
162 
163  // convert RosMaster(s) to mrpt_msgs::GraphSlamAgent(s)
164  for (std::vector<ROSMaster>::const_iterator
165  masters_it = masters->begin();
166  masters_it != masters->end();
167  ++masters_it) {
168 
169  // 3 cases:
170  // In RosMasters AND In mrpt_msgs::GraphSlamAgents => update relevant fields
171  // In RosMasters AND NOT In mrpt_msgs::GraphSlamAgents => add it to mrpt_msgs::GraphSlamAgents
172  // NOT In RosMasters AND In mrpt_msgs::GraphSlamAgents => Do nothing.
173 
174  // have I already registered the current agent?
175  auto search = [masters_it](const mrpt_msgs::GraphSlamAgent& agent) {
176  return agent == *masters_it;
177  };
178  agents_it it = find_if(
179  m_nearby_slam_agents.list.begin(),
180  m_nearby_slam_agents.list.end(), search);
181 
182  if (it != m_nearby_slam_agents.list.end()) { // found, update relevant fields
183  // update timestamp
184  it->last_seen_time.data = ros::Time(masters_it->timestamp);
185  }
186  else { // not found, try to insert it.
187  mrpt_msgs::GraphSlamAgent new_agent;
188  bool is_agent = this->convert(*masters_it, &new_agent);
189  if (is_agent) {
190  m_nearby_slam_agents.list.push_back(new_agent);
191  };
192  }
193 
194  } // for all ROSMaster(s)
195 
196 } // end of updateNearbySlamAgents
197 
198 
200 
201  this->setupSubs();
202  this->setupPubs();
203  this->setupSrvs();
204 
205  has_setup_comm = true;
206 } // end of setupComm
207 
211  // call to the querier should be made after the
212  // multimaster_msgs_fkie::DiscoverMaster service is up and running
214  m_nh->serviceClient<multimaster_msgs_fkie::DiscoverMasters>(
215  "/master_discovery/list_masters");
216 
217  //ASSERT_(m_DiscoverMasters_client.isValid());
218 }
219 
221  const multimaster_msgs_fkie::ROSMaster& ros_master,
222  mrpt_msgs::GraphSlamAgent* slam_agent) {
223  ASSERT_(slam_agent);
224  bool agent_namespace_found = false;
225 
226  slam_agent->name.data = ros_master.name;
227  slam_agent->is_online.data = static_cast<bool>(ros_master.online);
228 
229  // ip_address, hostname, port
230  std::string ip_addr = CConnectionManager::extractHostnameOrIP(ros_master.monitoruri);
231  slam_agent->ip_addr.data = ip_addr;
232  std::string hostname = CConnectionManager::extractHostnameOrIP(
233  ros_master.uri, &slam_agent->port);
234  slam_agent->hostname.data = hostname;
235 
236  // agent_ID - last field of the IP address
237  vector<string> tokens;
238  mrpt::system::tokenize(ip_addr, ".", tokens);
239  slam_agent->agent_ID = atoi(tokens.rbegin()->c_str());
240 
241  // robot topic namespace
242  {
243  //stringstream ss("");
244  //ss << slam_agent->name.data << "_" << slam_agent->agent_ID;
245  //slam_agent->topic_namespace.data = ss.str().c_str();
246  slam_agent->topic_namespace.data = slam_agent->name.data;
247 
248  // assert that there exists a subtopic namespace named feedback under this.
250  bool got_topics = ros::master::getTopics(topics);
251  ASSERTMSG_(got_topics, "Unable to fetch topics. Exiting.");
252 
253  // get the namespaces under the current topic_namespace
254  const std::string& topic_ns = "/" + slam_agent->topic_namespace.data;
255  // TODO - What if this topic changes? from the configuration file
256  const std::string& feedback_ns =
257  "/" + slam_agent->topic_namespace.data + "/" + "feedback";
258 
259  auto search = [&feedback_ns](
260  const ros::master::TopicInfo& topic) {
261  return (strStarts(topic.name, feedback_ns));
262  };
263  ros::master::V_TopicInfo::const_iterator cit = find_if(
264  topics.begin(), topics.end(), search);
265  if (cit != topics.end()) {
266  agent_namespace_found = true;
267  }
268  }
269 
270  // timestamp
271  slam_agent->last_seen_time.data = ros::Time(ros_master.timestamp);
272  return agent_namespace_found;
273 
274 } // end of convert
275 
277  const mrpt_msgs::GraphSlamAgent& slam_agent,
278  multimaster_msgs_fkie::ROSMaster* ros_master) {
279  ASSERT_(ros_master);
280 
281  ros_master->name = slam_agent.name.data;
282  {
283  stringstream ss("");
284  ss << "http://" << slam_agent.ip_addr << ":" << slam_agent.port;
285  ros_master->uri = ss.str();
286  }
287  ros_master->online = slam_agent.is_online.data;
288  ros_master->discoverer_name = "/master_discovery";
289 
290  // TODO - timestamp
291 
292 }
293 
294 std::string CConnectionManager::extractHostnameOrIP(const std::string& str,
295  unsigned short* agent_port/*=NULL*/) {
296  // example for monitoruri: http://nickkouk-ubuntu:11311/
297  std::string s = std::string(str.begin()+7, str.end());
298 
299  vector<string> tokens;
300  mrpt::system::tokenize(s, ":", tokens);
301 
302  if (agent_port) {
303  *agent_port = static_cast<unsigned short>(atoi(tokens[1].c_str()));
304  }
305 
306  return tokens[0];
307 }
308 
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
const mrpt_msgs::GraphSlamAgents & getNearbySlamAgentsCached() const
Read-only method for accessing list of nearby agents. This doesn&#39;t update the internal list of GraphS...
void setupComm()
Wrapper method around the private setup* class methods.
const mrpt_msgs::GraphSlamAgents & getNearbySlamAgents()
Read-only method for accessing list of nearby agents.
bool call(MReq &req, MRes &res)
void updateNearbySlamAgents()
Update the internal list of nearby SLAM agents.
ROSCPP_DECL bool getTopics(V_TopicInfo &topics)
std::vector< TopicInfo > V_TopicInfo
mrpt_msgs::GraphSlamAgents::_list_type::iterator agents_it
std::string own_ns
Namespace under which we are running. Corresponds to the agent_ID_str with which the nodes are going ...
GLdouble s
ros::NodeHandle * m_nh
Pointer to the Ros NodeHanle instance.
mrpt_msgs::GraphSlamAgents m_nearby_slam_agents
List of slam agents in the current agent&#39;s neighborhood.
const std::string & getNamespace() const
bool operator<(const mrpt_msgs::GraphSlamAgent &agent1, const mrpt_msgs::GraphSlamAgent &agent2)
bool operator==(const multimaster_msgs_fkie::ROSMaster &master1, const multimaster_msgs_fkie::ROSMaster &master2)
ROSMaster instances are considered the same if the "uri" field is the same.
const std::string & getTrimmedNs() const
Get the agent ROS namespace.
bool BASE_IMPEXP strStarts(const std::string &str, const std::string &subStr)
CConnectionManager(mrpt::utils::COutputLogger *logger, ros::NodeHandle *nh_in)
Constructor.
#define ASSERT_(f)
mrpt::utils::COutputLogger * m_logger
Pointer to the logging instance.
string ss
static std::string extractHostnameOrIP(const std::string &str, unsigned short *agent_port=NULL)
Remove http:// prefix and port suffix from the string and return result.
ROSCPP_DECL bool search(const std::string &ns, const std::string &key, std::string &result)
#define ASSERTMSG_(f, __ERROR_MSG)
void BASE_IMPEXP tokenize(const std::string &inString, const std::string &inDelimiters, std::deque< std::string > &outTokens, bool skipBlankTokens=true) MRPT_NO_THROWS
static bool convert(const multimaster_msgs_fkie::ROSMaster &ros_master, mrpt_msgs::GraphSlamAgent *slam_agent)
ROSMaster ==> mrpt_msgs::GraphSlamAgent.
bool operator!=(const multimaster_msgs_fkie::ROSMaster &master1, const multimaster_msgs_fkie::ROSMaster &master2)


mrpt_graphslam_2d
Author(s): Nikos Koukis
autogenerated on Sat May 2 2020 03:44:17