NASA Astrobee Robot Software  0.19.1
Flight software for the Astrobee robots operating inside the International Space Station.
localization_pipeline.h
Go to the documentation of this file.
1 /* Copyright (c) 2017, United States Government, as represented by the
2  * Administrator of the National Aeronautics and Space Administration.
3  *
4  * All rights reserved.
5  *
6  * The Astrobee platform is licensed under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with the
8  * License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations
16  * under the License.
17  */
18 
19 #ifndef LOCALIZATION_MANAGER_LOCALIZATION_PIPELINE_H_
20 #define LOCALIZATION_MANAGER_LOCALIZATION_PIPELINE_H_
21 
22 // ROS
23 #include <ros/ros.h>
24 
25 // Message types
26 #include <ff_msgs/CameraRegistration.h>
27 #include <ff_msgs/VisualLandmarks.h>
28 #include <ff_msgs/DepthLandmarks.h>
29 #include <ff_msgs/SetBool.h>
30 #include <ff_msgs/EkfState.h>
31 
32 // C++ includes
33 #include <functional>
34 #include <string>
35 #include <map>
36 
38 
39 enum PipelineError : uint8_t {
40  ERROR_REGISTRATION_TIMEOUT = 0, // Registration timeout
41  ERROR_VISUAL_TIMEOUT = 1, // Visual feature timeout
42  ERROR_DEPTH_TIMEOUT = 2, // Depth timeout
43  ERROR_FILTER_TIMEOUT = 3, // Filter timeout
44  ERROR_FILTER_BIAS = 4 // Filter is sampling the bias
45 };
46 
47 typedef std::function<void(PipelineError)> PipelineCallbackType;
48 
49 struct Pipeline {
50  enum Components : uint8_t {
51  COMPONENT_FILTER = (1<<0), // Filter needed
52  COMPONENT_OPTICAL_FLOW = (1<<1), // Optical flow needed
53  COMPONENT_ENABLE = (1<<2), // Needs optical flow
54  COMPONENT_SET_INPUT = (1<<3), // Needs EKF input to be set
55  COMPONENT_REGISTRATIONS = (1<<4), // Needs registration pulses
56  COMPONENT_VISUAL_FEATURES = (1<<5), // Needs viusal features
57  COMPONENT_DEPTH_FEATURES = (1<<6) // Needs depth features
58  };
59 
60  // Constructor
61  Pipeline(uint8_t mode, std::string const& name)
62  : mode_(mode), components_(0), name_(name) {}
63 
64  // If the pipeline requires
65  Pipeline& NeedsFilter(uint32_t max_conf, bool optical_flow, double timeout) {
66  components_ |= COMPONENT_FILTER;
67  max_filter_ = max_conf;
68  if (optical_flow)
69  components_ |= COMPONENT_OPTICAL_FLOW;
70  timeout_filter_ = timeout;
71  return *this;
72  }
73 
74  // Needs to be enabled/disabled
75  Pipeline& NeedsEnable(std::string const& topic, double timeout) {
76  components_ |= COMPONENT_ENABLE;
77  topic_enable_ = topic;
78  timeout_enable_ = timeout;
79  return *this;
80  }
81 
82  // Needs measurements to be streamed
83  Pipeline& NeedsRegistrations(std::string const& topic, double timeout) {
84  components_ |= COMPONENT_REGISTRATIONS;
85  topic_reg_ = topic;
86  timeout_reg_ = timeout;
87  return *this;
88  }
89 
90  // Needs features
92  std::string const& topic, double timeout, uint32_t min_features) {
93  components_ |= COMPONENT_VISUAL_FEATURES;
94  topic_visual_ = topic;
95  timeout_visual_ = timeout;
96  min_visual_ = min_features;
97  return *this;
98  }
99 
100  // Needs features
102  std::string const& topic, double timeout, uint32_t min_features) {
103  components_ |= COMPONENT_DEPTH_FEATURES;
104  topic_depth_ = topic;
105  timeout_depth_ = timeout;
106  min_depth_ = min_features;
107  return *this;
108  }
109 
110  // Get the name of the pipeline
111  std::string const& GetTopic() {
112  return topic_enable_;
113  }
114 
115  // Get the name of the pipeline
116  std::string const& GetName() {
117  return name_;
118  }
119 
120  // Get the name of the pipeline
121  uint8_t GetMode() {
122  return mode_;
123  }
124 
125  // Get whether the pipeline needs optical flow
127  return (components_ & COMPONENT_OPTICAL_FLOW);
128  }
129 
130  // Get whether the pipeline needs optical flow
131  bool RequiresFilter() {
132  return (components_ & COMPONENT_FILTER);
133  }
134 
135  // Initialize the pipeline
136  bool Initialize(ros::NodeHandle *nh,
137  PipelineCallbackType cb_error,
138  std::function<void(void)> cb_connected,
139  std::function<void(void)> cb_timeout) {
140  // Copy the callback and node handle
141  callback_ = cb_error;
142  nh_ = nh;
143  // If we need to enable
144  if (components_ & COMPONENT_ENABLE) {
145  service_.SetConnectedTimeout(timeout_enable_);
146  service_.SetConnectedCallback(cb_connected);
147  service_.SetTimeoutCallback(cb_timeout);
148  service_.Create(nh, topic_enable_);
149  }
150  // Disable by default
151  return true;
152  }
153 
154  // Check if the pipeline is initialized / connected to its services
155  bool IsConnected() {
156  if ((components_ & COMPONENT_ENABLE) && !service_.IsConnected())
157  return false;
158  return true;
159  }
160 
161  // Enable or disable this pipeline
162  bool Toggle(bool enable) {
163  // If we are enabling this pipeline
164  if (enable) {
165  if (components_ & COMPONENT_REGISTRATIONS) {
166  sub_reg_ = nh_->subscribe(topic_reg_, 1,
168  timer_reg_ = nh_->createTimer(ros::Duration(timeout_reg_),
170  }
171  if (components_ & COMPONENT_VISUAL_FEATURES) {
172  sub_visual_ = nh_->subscribe(topic_visual_, 1,
173  &Pipeline::VisualCallback, this);
174  timer_visual_ = nh_->createTimer(ros::Duration(timeout_visual_),
175  &Pipeline::VisualTimeoutCallback, this, false, false);
176  }
177  if (components_ & COMPONENT_DEPTH_FEATURES) {
178  sub_depth_ = nh_->subscribe(topic_depth_, 1,
179  &Pipeline::DepthCallback, this);
180  timer_depth_ = nh_->createTimer(ros::Duration(timeout_depth_),
182  }
183  } else {
184  // Make sure we don't keep monitoring the filter when the pipeline
185  // is shutdown.
186  Use(false);
187  // Stop monitoring the raw pipeline stream.
188  if (components_ & COMPONENT_VISUAL_FEATURES) {
189  sub_visual_.shutdown();
190  timer_visual_.stop();
191  }
192  if (components_ & COMPONENT_DEPTH_FEATURES) {
193  sub_depth_.shutdown();
194  timer_depth_.stop();
195  }
196  if (components_ & COMPONENT_REGISTRATIONS) {
197  sub_reg_.shutdown();
198  timer_reg_.stop();
199  }
200  }
201  // Enable or disable the pipeline if neededs
202  if (components_ & COMPONENT_ENABLE) {
203  ff_msgs::SetBool msg;
204  msg.request.enable = enable;
205  if (!service_.Call(msg))
206  return false;
207  }
208  return true;
209  }
210 
211  // Start actually using the pipeline
212  bool Use(bool enable) {
213  // If we are enabling this pipeline
214  if (enable) {
215  if (components_ & COMPONENT_FILTER) {
216  sub_filter_ = nh_->subscribe(TOPIC_GNC_EKF, 1,
217  &Pipeline::FilterCallback, this);
218  timer_filter_ = nh_->createTimer(ros::Duration(timeout_filter_),
219  &Pipeline::FilterTimeoutCallback, this, false, false);
220  }
221  } else {
222  if (components_ & COMPONENT_FILTER) {
223  sub_filter_.shutdown();
224  timer_filter_.stop();
225  }
226  }
227  return true;
228  }
229 
230  protected:
231  // Called back when registration pulses arrive for processing
232  void RegistrationCallback(ff_msgs::CameraRegistration::ConstPtr const& msg) {
233  timer_reg_.stop();
234  timer_reg_.start();
235  }
236 
237  // Called when registration pulses don't arrive
238  void RegistrationTimeoutCallback(ros::TimerEvent const& event) {
239  callback_(ERROR_REGISTRATION_TIMEOUT);
240  }
241 
242  // Called back when visual features arrive for processing
243  void VisualCallback(ff_msgs::VisualLandmarks::ConstPtr const& msg) {
244  if (msg->landmarks.size() < min_visual_)
245  return;
246  timer_visual_.stop();
247  timer_visual_.start();
248  }
249 
250  // Called when visual features don't arrive
251  void VisualTimeoutCallback(ros::TimerEvent const& event) {
252  callback_(ERROR_VISUAL_TIMEOUT);
253  }
254 
255  // Called back when depth features arrive for processing
256  void DepthCallback(ff_msgs::DepthLandmarks::ConstPtr const& msg) {
257  if (msg->landmarks.size() < min_depth_)
258  return;
259  timer_depth_.stop();
260  timer_depth_.start();
261  }
262 
263  // Called when depth features don't arrive
264  void DepthTimeoutCallback(ros::TimerEvent const& event) {
265  callback_(ERROR_DEPTH_TIMEOUT);
266  }
267 
268  // Called when filter estimates arrive
269  void FilterCallback(ff_msgs::EkfState::ConstPtr const& msg) {
270  if (msg->estimating_bias)
271  callback_(ERROR_FILTER_BIAS);
272  else if (msg->confidence > max_filter_)
273  return;
274  timer_filter_.stop();
275  timer_filter_.start();
276  }
277 
278  // Called when filter estimates don't arrive
279  void FilterTimeoutCallback(ros::TimerEvent const& event) {
280  callback_(ERROR_FILTER_TIMEOUT);
281  }
282 
283  private:
284  uint8_t mode_, components_;
285  std::string name_, topic_enable_, topic_reg_, topic_visual_, topic_depth_;
286  double timeout_reg_, timeout_visual_, timeout_depth_, timeout_enable_, timeout_filter_;
287  ros::Subscriber sub_visual_, sub_depth_, sub_reg_, sub_filter_;
288  uint32_t min_visual_, min_depth_, max_filter_;
290  ros::NodeHandle *nh_;
291  ros::Timer timer_visual_, timer_filter_, timer_depth_, timer_reg_;
292  PipelineCallbackType callback_;
293 };
294 
295 
296 // Shorthand for id:pipeline relation
297 typedef std::map<std::string, Pipeline> PipelineMap;
298 
299 } // namespace localization_manager
300 
301 #endif // LOCALIZATION_MANAGER_LOCALIZATION_PIPELINE_H_
mode
uint8_t mode
Definition: signal_lights.h:74
localization_manager::Pipeline::NeedsVisualFeatures
Pipeline & NeedsVisualFeatures(std::string const &topic, double timeout, uint32_t min_features)
Definition: localization_pipeline.h:91
localization_manager::ERROR_FILTER_TIMEOUT
@ ERROR_FILTER_TIMEOUT
Definition: localization_pipeline.h:43
localization_manager::Pipeline::Components
Components
Definition: localization_pipeline.h:50
localization_manager::Pipeline::Toggle
bool Toggle(bool enable)
Definition: localization_pipeline.h:162
localization_manager
Definition: localization_pipeline.h:37
localization_manager::Pipeline::FilterTimeoutCallback
void FilterTimeoutCallback(ros::TimerEvent const &event)
Definition: localization_pipeline.h:279
ff_util::FreeFlyerServiceClient::SetConnectedCallback
void SetConnectedCallback(ConnectedCallbackType cb_connected)
Definition: ff_service.h:56
localization_manager::Pipeline::NeedsDepthFeatures
Pipeline & NeedsDepthFeatures(std::string const &topic, double timeout, uint32_t min_features)
Definition: localization_pipeline.h:101
localization_manager::ERROR_REGISTRATION_TIMEOUT
@ ERROR_REGISTRATION_TIMEOUT
Definition: localization_pipeline.h:40
localization_manager::PipelineMap
std::map< std::string, Pipeline > PipelineMap
Definition: localization_pipeline.h:297
localization_manager::Pipeline::GetMode
uint8_t GetMode()
Definition: localization_pipeline.h:121
localization_manager::Pipeline::COMPONENT_ENABLE
@ COMPONENT_ENABLE
Definition: localization_pipeline.h:53
ff_util::FreeFlyerServiceClient< ff_msgs::SetBool >
localization_manager::Pipeline::RegistrationTimeoutCallback
void RegistrationTimeoutCallback(ros::TimerEvent const &event)
Definition: localization_pipeline.h:238
localization_manager::Pipeline::NeedsFilter
Pipeline & NeedsFilter(uint32_t max_conf, bool optical_flow, double timeout)
Definition: localization_pipeline.h:65
localization_manager::Pipeline::COMPONENT_REGISTRATIONS
@ COMPONENT_REGISTRATIONS
Definition: localization_pipeline.h:55
localization_manager::Pipeline::COMPONENT_DEPTH_FEATURES
@ COMPONENT_DEPTH_FEATURES
Definition: localization_pipeline.h:57
localization_manager::Pipeline::Use
bool Use(bool enable)
Definition: localization_pipeline.h:212
ff_util::FreeFlyerServiceClient::IsConnected
bool IsConnected()
Definition: ff_service.h:86
localization_manager::Pipeline
Definition: localization_pipeline.h:49
localization_manager::Pipeline::COMPONENT_VISUAL_FEATURES
@ COMPONENT_VISUAL_FEATURES
Definition: localization_pipeline.h:56
localization_manager::ERROR_VISUAL_TIMEOUT
@ ERROR_VISUAL_TIMEOUT
Definition: localization_pipeline.h:41
name
std::string name
Definition: eps_simulator.cc:48
localization_manager::Pipeline::Pipeline
Pipeline(uint8_t mode, std::string const &name)
Definition: localization_pipeline.h:61
localization_manager::PipelineCallbackType
std::function< void(PipelineError)> PipelineCallbackType
Definition: localization_pipeline.h:47
localization_manager::Pipeline::COMPONENT_FILTER
@ COMPONENT_FILTER
Definition: localization_pipeline.h:51
localization_manager::Pipeline::COMPONENT_SET_INPUT
@ COMPONENT_SET_INPUT
Definition: localization_pipeline.h:54
localization_manager::PipelineError
PipelineError
Definition: localization_pipeline.h:39
localization_manager::Pipeline::NeedsEnable
Pipeline & NeedsEnable(std::string const &topic, double timeout)
Definition: localization_pipeline.h:75
localization_manager::Pipeline::IsConnected
bool IsConnected()
Definition: localization_pipeline.h:155
localization_manager::Pipeline::NeedsRegistrations
Pipeline & NeedsRegistrations(std::string const &topic, double timeout)
Definition: localization_pipeline.h:83
ff_util::FreeFlyerServiceClient::SetConnectedTimeout
void SetConnectedTimeout(double to_connected)
Definition: ff_service.h:59
localization_manager::Pipeline::Initialize
bool Initialize(ros::NodeHandle *nh, PipelineCallbackType cb_error, std::function< void(void)> cb_connected, std::function< void(void)> cb_timeout)
Definition: localization_pipeline.h:136
localization_manager::Pipeline::GetTopic
std::string const & GetTopic()
Definition: localization_pipeline.h:111
localization_manager::ERROR_DEPTH_TIMEOUT
@ ERROR_DEPTH_TIMEOUT
Definition: localization_pipeline.h:42
localization_manager::ERROR_FILTER_BIAS
@ ERROR_FILTER_BIAS
Definition: localization_pipeline.h:44
localization_manager::Pipeline::RegistrationCallback
void RegistrationCallback(ff_msgs::CameraRegistration::ConstPtr const &msg)
Definition: localization_pipeline.h:232
localization_manager::Pipeline::RequiresFilter
bool RequiresFilter()
Definition: localization_pipeline.h:131
localization_manager::Pipeline::DepthTimeoutCallback
void DepthTimeoutCallback(ros::TimerEvent const &event)
Definition: localization_pipeline.h:264
localization_manager::Pipeline::FilterCallback
void FilterCallback(ff_msgs::EkfState::ConstPtr const &msg)
Definition: localization_pipeline.h:269
localization_manager::Pipeline::VisualTimeoutCallback
void VisualTimeoutCallback(ros::TimerEvent const &event)
Definition: localization_pipeline.h:251
localization_manager::Pipeline::DepthCallback
void DepthCallback(ff_msgs::DepthLandmarks::ConstPtr const &msg)
Definition: localization_pipeline.h:256
localization_manager::Pipeline::VisualCallback
void VisualCallback(ff_msgs::VisualLandmarks::ConstPtr const &msg)
Definition: localization_pipeline.h:243
localization_manager::Pipeline::COMPONENT_OPTICAL_FLOW
@ COMPONENT_OPTICAL_FLOW
Definition: localization_pipeline.h:52
localization_manager::Pipeline::RequiresOpticalFlow
bool RequiresOpticalFlow()
Definition: localization_pipeline.h:126
ff_util::FreeFlyerServiceClient::Call
bool Call(ServiceSpec &service)
Definition: ff_service.h:94
localization_manager::Pipeline::GetName
std::string const & GetName()
Definition: localization_pipeline.h:116
TOPIC_GNC_EKF
#define TOPIC_GNC_EKF
Definition: ff_names.h:135
ff_util::FreeFlyerServiceClient::Create
bool Create(ros::NodeHandle *nh, std::string const &topic)
Definition: ff_service.h:72
ff_util::FreeFlyerServiceClient::SetTimeoutCallback
void SetTimeoutCallback(TimeoutCallbackType cb_timeout)
Definition: ff_service.h:55