exploration.hpp
Go to the documentation of this file.
1 /*********************************************************************
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2020 Northwestern University
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *********************************************************************/
40 #include <ros/ros.h>
41 #include <ros/console.h>
42 #include <geometry_msgs/Twist.h>
43 #include <geometry_msgs/TransformStamped.h>
44 #include <nav_msgs/OccupancyGrid.h>
45 #include <nav_msgs/Odometry.h>
46 #include <sensor_msgs/LaserScan.h>
49 
52 
54 
55 namespace ergodic_exploration
56 {
57 constexpr char LOGNAME[] = "ergodic exploration";
58 
59 using arma::eye;
60 using arma::mat;
61 using arma::span;
62 using arma::vec;
63 
65 template <class ModelT>
67 {
68 public:
76  Exploration(ros::NodeHandle& nh, const ErgodicControl<ModelT>& ergodic_control,
77  const Collision& collision, const DynamicWindow& dwa);
78 
80  void init();
81 
87  void odomCallback(const nav_msgs::Odometry& msg);
88 
93  void mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg);
94 
105  void control(const Target& target, const std::string& map_frame_id,
106  const std::string& base_frame_id, double frequency, double val_dt,
107  double val_horizon);
108 
109 private:
110  ros::NodeHandle nh_; // NodeHandle
111 
113  Collision collision_; // collision detector
114  DynamicWindow dwa_; // dynamic window local planner
115 
116  bool map_received_; // occupancy grid received
117 
118  vec vb_; // current body twist [vx, vy, w]
119  GridMap grid_; // occupancy grid
120 
121  tf2_ros::Buffer tfBuffer_; // tf2 buffer
123 
124  ros::Subscriber map_sub_; // occupancy grid subscriber
125  ros::Subscriber odom_sub_; // odometry grid subscriber
126 
127  ros::Publisher cmd_pub_; // twist publisher
128  ros::Publisher opt_traj_pub_; // ergodic controller trajectory publisher
129  ros::Publisher dwa_path_pub_; // dynamic window trajectory publisher
130  ros::Publisher target_pub_; // target distribution publisher
131 };
132 
133 template <class ModelT>
135  const ErgodicControl<ModelT>& ergodic_control,
136  const Collision& collision, const DynamicWindow& dwa)
137  : nh_(nh)
138  , ergodic_control_(ergodic_control)
139  , collision_(collision)
140  , dwa_(dwa)
141  , map_received_(false)
142  , vb_(3, arma::fill::zeros)
143  , tfListener_(tfBuffer_)
144 {
145  init();
146 }
147 
148 template <class ModelT>
150 {
151  map_sub_ = nh_.subscribe("map", 1, &Exploration<ModelT>::mapCallback, this);
152  odom_sub_ = nh_.subscribe("odom", 1, &Exploration<ModelT>::odomCallback, this);
153 
154  cmd_pub_ = nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1);
155  opt_traj_pub_ = nh_.advertise<nav_msgs::Path>("trajectory", 1);
156  dwa_path_pub_ = nh_.advertise<nav_msgs::Path>("dwa_trajectory", 1);
157  target_pub_ = nh_.advertise<visualization_msgs::MarkerArray>("target", 1, true);
158 }
159 
160 template <class ModelT>
161 void Exploration<ModelT>::odomCallback(const nav_msgs::Odometry& msg)
162 {
163  vb_(0) = msg.twist.twist.linear.x;
164  vb_(1) = msg.twist.twist.linear.y;
165  vb_(2) = msg.twist.twist.angular.z;
166 }
167 
168 template <class ModelT>
169 void Exploration<ModelT>::mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg)
170 {
171  grid_.update(msg);
172  // grid_.print();
173  map_received_ = true;
174 }
175 
176 template <class ModelT>
177 void Exploration<ModelT>::control(const Target& target, const std::string& map_frame_id,
178  const std::string& base_frame_id, double frequency,
179  double val_dt, double val_horizon)
180 {
181  // Initialize the target distribution
182  ergodic_control_.setTarget(target);
183 
184  const visualization_msgs::MarkerArray marker_array = target.markers(map_frame_id);
185  target_pub_.publish(marker_array);
186 
187  const auto dwa_steps = dwa_.steps();
188  vec u(3, arma::fill::zeros);
189  vec pose(3, arma::fill::zeros);
190 
191  bool pose_known = false;
192  bool follow_dwa = false;
193 
194  ros::Rate rate(frequency);
195  unsigned int i = 0;
196 
197  while (nh_.ok())
198  {
199  try
200  {
201  const geometry_msgs::TransformStamped t_map_base =
202  tfBuffer_.lookupTransform(map_frame_id, base_frame_id, ros::Time(0));
203  pose(0) = t_map_base.transform.translation.x;
204  pose(1) = t_map_base.transform.translation.y;
205  pose(2) = getYaw(t_map_base.transform.rotation.x, t_map_base.transform.rotation.y,
206  t_map_base.transform.rotation.z, t_map_base.transform.rotation.w);
207 
208  // Add state to memory
209  ergodic_control_.addStateMemory(pose);
210 
211  pose_known = true;
212  }
213 
214  catch (tf2::TransformException& ex)
215  {
216  ROS_WARN_ONCE_NAMED(LOGNAME, "%s", ex.what());
217  // continue;
218  }
219 
220  // Contol loop
221  if (map_received_ && pose_known)
222  {
223  if (follow_dwa)
224  {
225  i++;
226  // May need to replan
227  follow_dwa = (i != dwa_steps) ? true : false;
228  }
229 
230  if (!follow_dwa)
231  {
232  u = ergodic_control_.control(grid_, pose);
233 
234  const nav_msgs::Path trajectory = ergodic_control_.path(map_frame_id);
235  opt_traj_pub_.publish(trajectory);
236  }
237 
238  if (!validate_control(collision_, grid_, pose, u, val_dt, val_horizon))
239  {
240  // ROS_INFO_STREAM_NAMED(LOGNAME, "Collision detected! Enabling DWA!");
241 
242  // Collision is a result from the previous dwa twist
243  if (follow_dwa)
244  {
245  // If dwa fails twist is set to zeros
246  u = std::get<vec>(dwa_.control(grid_, pose, vb_, u));
247 
248  // Whether or not dwa is successful the
249  // ergodic controller will replan next iteration
250  follow_dwa = false;
251  }
252 
253  // Collision is a result from the ergodic controller
254  else
255  {
256  // Reference trajectory for dwa
257  const mat opt_traj = ergodic_control_.optTraj();
258 
259  // If dwa fails twist is set to zeros
260  const tuple<bool, vec> dwa_state =
261  dwa_.control(grid_, pose, vb_, opt_traj, ergodic_control_.timeStep());
262 
263  u = std::get<vec>(dwa_state);
264 
265  // if dwa found at a solution and the robot will follow it
266  // else ergodic controller will replan next iteration
267  follow_dwa = std::get<bool>(dwa_state);
268 
269  if (follow_dwa)
270  {
271  i = 0;
272 
273  // Visualize dwa predicted trajectory
274  const nav_msgs::Path dwa_traj =
275  constTwistPath(map_frame_id, pose, u, dwa_.timeStep(), dwa_.horizon());
276  dwa_path_pub_.publish(dwa_traj);
277  }
278  }
279  } // end validate control
280 
281  geometry_msgs::Twist twist_msg;
282  twist_msg.linear.x = u(0);
283  twist_msg.linear.y = u(1);
284  twist_msg.angular.z = u(2);
285 
286  cmd_pub_.publish(twist_msg);
287  // u.print();
288 
289  } // end control loop
290 
291  rate.sleep();
292  } // end while loop
293 }
294 } // namespace ergodic_exploration
ergodic_exploration::validate_control
bool validate_control(const Collision &collision, const GridMap &grid, const vec &x0, const vec &u, double dt, double horizon)
Determine if control will cause a collision.
Definition: numerics.hpp:312
ergodic_exploration::Exploration::nh_
ros::NodeHandle nh_
Definition: exploration.hpp:110
ergodic_exploration::Exploration
Exploration template.
Definition: exploration.hpp:66
ros::Publisher
ergodic_exploration::Exploration::cmd_pub_
ros::Publisher cmd_pub_
Definition: exploration.hpp:127
ergodic_exploration::Exploration::vb_
vec vb_
Definition: exploration.hpp:118
ros.h
ergodic_exploration::Target::markers
visualization_msgs::MarkerArray markers(const std::string &frame) const
Visualize target distribution.
Definition: target.cpp:91
ergodic_exploration::constTwistPath
nav_msgs::Path constTwistPath(const std::string &map_frame_id, const vec &x0, const vec &u, double dt, double horizon)
Visualize path from following a constant twist.
Definition: numerics.hpp:340
ROS_WARN_ONCE_NAMED
#define ROS_WARN_ONCE_NAMED(name,...)
ergodic_exploration::Exploration::map_received_
bool map_received_
Definition: exploration.hpp:116
ergodic_exploration::Exploration::dwa_
DynamicWindow dwa_
Definition: exploration.hpp:114
ergodic_exploration::DynamicWindow
Dynamic window approach.
Definition: dynamic_window.hpp:52
ergodic_exploration::getYaw
double getYaw(double qx, double qy, double qz, double qw)
Get yaw from quaternion.
Definition: numerics.hpp:118
ergodic_exploration::LOGNAME
constexpr char LOGNAME[]
Definition: exploration.hpp:57
tf2_ros::TransformListener
console.h
ergodic_exploration::Exploration::tfListener_
tf2_ros::TransformListener tfListener_
Definition: exploration.hpp:122
ergodic_exploration
Definition: basis.hpp:43
ergodic_exploration::GridMap
Constructs an 2D grid.
Definition: grid.hpp:79
ergodic_exploration::Target
Target distribution.
Definition: target.hpp:110
ergodic_exploration::Exploration::ergodic_control_
ErgodicControl< ModelT > ergodic_control_
Definition: exploration.hpp:112
Quaternion.h
dynamic_window.hpp
Dynamic window control.
ergodic_exploration::Exploration::mapCallback
void mapCallback(const nav_msgs::OccupancyGrid::ConstPtr &msg)
Occupancy grid callback.
Definition: exploration.hpp:169
ergodic_exploration::Exploration::dwa_path_pub_
ros::Publisher dwa_path_pub_
Definition: exploration.hpp:129
omni.hpp
Kinematic omni directional models control wheel velocities or body twist.
tf2_ros::Buffer
ergodic_exploration::Exploration::Exploration
Exploration(ros::NodeHandle &nh, const ErgodicControl< ModelT > &ergodic_control, const Collision &collision, const DynamicWindow &dwa)
Constructor.
Definition: exploration.hpp:134
ros::Rate::sleep
bool sleep()
ergodic_exploration::Exploration::grid_
GridMap grid_
Definition: exploration.hpp:119
ergodic_exploration::Exploration::control
void control(const Target &target, const std::string &map_frame_id, const std::string &base_frame_id, double frequency, double val_dt, double val_horizon)
Executes the exploration stack.
Definition: exploration.hpp:177
transform_listener.h
ergodic_exploration::Exploration::tfBuffer_
tf2_ros::Buffer tfBuffer_
Definition: exploration.hpp:121
ergodic_control.hpp
Ergodic control strategy for exploration.
ergodic_exploration::Exploration::collision_
Collision collision_
Definition: exploration.hpp:113
ros::Time
ros::Rate
ergodic_exploration::ErgodicControl
Receding horizon ergodic trajectory optimization.
Definition: ergodic_control.hpp:73
ergodic_exploration::Exploration::target_pub_
ros::Publisher target_pub_
Definition: exploration.hpp:130
ergodic_exploration::Exploration::odomCallback
void odomCallback(const nav_msgs::Odometry &msg)
Odometry callback.
Definition: exploration.hpp:161
tf2::TransformException
ergodic_exploration::Exploration::init
void init()
Initialize subscribers and publishers.
Definition: exploration.hpp:149
ergodic_exploration::Exploration::odom_sub_
ros::Subscriber odom_sub_
Definition: exploration.hpp:125
ergodic_exploration::Exploration::opt_traj_pub_
ros::Publisher opt_traj_pub_
Definition: exploration.hpp:128
ros::NodeHandle
ros::Subscriber
ergodic_exploration::Exploration::map_sub_
ros::Subscriber map_sub_
Definition: exploration.hpp:124
ergodic_exploration::Collision
2D collision detection
Definition: collision.hpp:85


ergodic_exploration
Author(s): bostoncleek
autogenerated on Wed Mar 2 2022 00:17:13