laser_tilt_controller_filter.h
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * Software License Agreement (BSD License)
4 *
5 * Copyright (c) 2009, Willow Garage, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * * Neither the name of Willow Garage, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * Author: Eitan Marder-Eppstein
36 *********************************************************************/
37 
38 #include <XmlRpc.h>
39 #include <sensor_msgs/LaserScan.h>
40 #include <filters/filter_base.h>
41 #include <pr2_msgs/LaserScannerSignal.h>
42 #include <boost/thread/mutex.hpp>
43 
45 
50  class LaserTiltControllerFilter : public filters::FilterBase<sensor_msgs::LaserScan>
51  {
52  public:
54 
56  XmlRpc::XmlRpcValue filter_sections;
57 
58  if(!filters::FilterBase<sensor_msgs::LaserScan>::getParam("filter_sections", filter_sections)){
59  //its ok to have an empty filter sections list... but we'll just return
60  return true;
61  }
62 
63  if(!(filter_sections.getType() == XmlRpc::XmlRpcValue::TypeArray)){
64  ROS_ERROR("The filter_sections must be a list of integers");
65  return false;
66  }
67 
68  //loop through the XmlRpc list
69  for(int i = 0; i < filter_sections.size(); ++i){
70  XmlRpc::XmlRpcValue section = filter_sections[i];
71 
72  //check to make sure that integer values are being used
73  if(!(section.getType() == XmlRpc::XmlRpcValue::TypeInt)){
74  ROS_ERROR("The tilt_profile_times must be a list of integers");
75  return false;
76  }
77 
78  double section_int = int(section);
79 
80  //push the time back onto our vector
81  filter_signals_.push_back(section_int);
82  }
83 
84  return true;
85  }
86 
88  XmlRpc::XmlRpcValue tilt_profile_times;
89  if(!filters::FilterBase<sensor_msgs::LaserScan>::getParam("tilt_profile_times", tilt_profile_times)){
90  ROS_ERROR("No tilt_profile_times were given");
91  return false;
92  }
93 
94  if(!(tilt_profile_times.getType() == XmlRpc::XmlRpcValue::TypeArray)){
95  ROS_ERROR("The tilt_profile_times must be a list of doubles");
96  return false;
97  }
98 
99  if(tilt_profile_times.size() < 2){
100  ROS_ERROR("The tilt_profile_times list must contain at least two values... a start and an end");
101  return false;
102  }
103 
104  //loop through the XmlRpc list
105  for(int i = 0; i < tilt_profile_times.size(); ++i){
106  XmlRpc::XmlRpcValue time_xml = tilt_profile_times[i];
107 
108  //check to make sure that integer/double values are being used
109  if(!(time_xml.getType() == XmlRpc::XmlRpcValue::TypeInt || time_xml.getType() == XmlRpc::XmlRpcValue::TypeDouble)){
110  ROS_ERROR("The tilt_profile_times must be a list of doubles");
111  return false;
112  }
113 
114  double time_dbl = time_xml.getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(time_xml) : (double)(time_xml);
115 
116  //push the time back onto our vector
117  tilt_profile_times_.push_back(time_dbl);
118  }
119 
120  return true;
121  }
122 
123  bool configure(){
124  ROS_DEBUG("Filtering initialized");
125  bool success = loadTiltProfileTiming() && loadFilterSignals();
126 
127  ros::NodeHandle n;
128  signal_sub_ = n.subscribe("laser_tilt_controller/laser_scanner_signal", 1, &LaserTiltControllerFilter::signalCb, this);
129  return success;
130  }
131 
132  void signalCb(const pr2_msgs::LaserScannerSignal::ConstPtr& signal){
133  boost::mutex::scoped_lock lock(mutex_);
134  //we'll sync the timer to the signal for the beginning of the profile to make sure we don't drift
135  if(signal->signal == 0){
136  timer_zero_ = signal->header.stamp;
137  signal_received_ = true;
138  }
139  }
140 
141  bool update(const sensor_msgs::LaserScan& scan_in, sensor_msgs::LaserScan& scan_out){
142  ROS_DEBUG("Signal filter running, current timer %.4f, signal_received: %d", timer_zero_.toSec(), signal_received_);
143  //make sure that we've received at least one scanner signal before throwing out scans
144  if(!signal_received_){
145  scan_out = scan_in;
146  return true;
147  }
148 
149  boost::mutex::scoped_lock lock(mutex_);
150  double time_diff = (scan_in.header.stamp - timer_zero_).toSec() + tilt_profile_times_.front();
151 
152  //make sure to put the time within the period of the profile
153  ROS_DEBUG("time_diff: %.4f, periold: %.4f", time_diff, tilt_profile_times_.back());
154  double period_time = fmod(time_diff, tilt_profile_times_.back());
155 
156  int profile_section = 0;
157  //get the period in which the scan falls
158  for(unsigned int i = 0; i < tilt_profile_times_.size() - 1; ++i){
159  ROS_DEBUG("Checking period_time: %.4f against tilt_profile time: %.4f and next %.4f",
160  period_time, tilt_profile_times_[i], tilt_profile_times_[i+1]);
161  if(period_time >= tilt_profile_times_[i] && period_time < tilt_profile_times_[i + 1]){
162  profile_section = i;
163  }
164  }
165 
166  ROS_DEBUG("Profile section: %d, time: %.4f", profile_section, scan_in.header.stamp.toSec());
167 
168  //check if our current tilt signal is one that should be filtered
169  for(unsigned int i = 0; i < filter_signals_.size(); ++i){
170  if(filter_signals_[i] == profile_section){
171  sensor_msgs::LaserScan empty_scan;
172  empty_scan.header = scan_in.header;
173  scan_out = empty_scan;
174  ROS_DEBUG("Filtering out scan");
175  return true;
176  }
177  }
178 
179  //if we made it here, then the tilt signal does not need to be
180  //filtered, so we'll just send the scan on
181  scan_out = scan_in;
182  return true;
183  }
184 
186 
187  private:
188  std::vector<int> filter_signals_;
189  std::vector<double> tilt_profile_times_;
191  boost::mutex mutex_;
194  };
195 
196 };
void signalCb(const pr2_msgs::LaserScannerSignal::ConstPtr &signal)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int size() const
bool update(const sensor_msgs::LaserScan &scan_in, sensor_msgs::LaserScan &scan_out)
Type const & getType() const
A filter that invalidates scans for certain periods of a tilt profile.
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


laser_tilt_controller_filter
Author(s): Eitan Marder-Eppstein
autogenerated on Mon Jun 10 2019 14:28:40