Node.cc
Go to the documentation of this file.
1 #include "Node.h"
2 
3 #include <iostream>
4 
5 Node::Node (ORB_SLAM2::System::eSensor sensor, ros::NodeHandle &node_handle, image_transport::ImageTransport &image_transport) : image_transport_(image_transport) {
7  node_handle_ = node_handle;
9  sensor_ = sensor;
10 }
11 
12 
14  // Stop all threads
16 
17  // Save camera trajectory
18  orb_slam_->SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");
19 
20  delete orb_slam_;
21 }
22 
23 void Node::Init () {
24  //static parameters
25  node_handle_.param(name_of_node_+ "/publish_pointcloud", publish_pointcloud_param_, true);
26  node_handle_.param(name_of_node_+ "/publish_pose", publish_pose_param_, true);
27  node_handle_.param(name_of_node_+ "/publish_tf", publish_tf_param_, true);
28  node_handle_.param<std::string>(name_of_node_+ "/pointcloud_frame_id", map_frame_id_param_, "map");
29  node_handle_.param<std::string>(name_of_node_+ "/camera_frame_id", camera_frame_id_param_, "camera_link");
30  node_handle_.param<std::string>(name_of_node_+ "/target_frame_id", target_frame_id_param_, "base_link");
31  node_handle_.param<std::string>(name_of_node_ + "/map_file", map_file_name_param_, "map.bin");
32  node_handle_.param<std::string>(name_of_node_ + "/voc_file", voc_file_name_param_, "file_not_set");
33  node_handle_.param(name_of_node_ + "/load_map", load_map_param_, false);
34 
35  // Create a parameters object to pass to the Tracking system
36  ORB_SLAM2::ORBParameters parameters;
37  LoadOrbParameters (parameters);
38 
39  orb_slam_ = new ORB_SLAM2::System (voc_file_name_param_, sensor_, parameters, map_file_name_param_, load_map_param_);
40 
41  service_server_ = node_handle_.advertiseService(name_of_node_+"/save_map", &Node::SaveMapSrv, this);
42 
43  //Setup dynamic reconfigure
44  dynamic_reconfigure::Server<orb_slam2_ros::dynamic_reconfigureConfig>::CallbackType dynamic_param_callback;
45  dynamic_param_callback = boost::bind(&Node::ParamsChangedCallback, this, _1, _2);
46  dynamic_param_server_.setCallback(dynamic_param_callback);
47 
48  // Initialization transformation listener
49  tfBuffer.reset(new tf2_ros::Buffer);
51 
52  rendered_image_publisher_ = image_transport_.advertise (name_of_node_+"/debug_image", 1);
54  map_points_publisher_ = node_handle_.advertise<sensor_msgs::PointCloud2> (name_of_node_+"/map_points", 1);
55  }
56 
57  // Enable publishing camera's pose as PoseStamped message
58  if (publish_pose_param_) {
59  pose_publisher_ = node_handle_.advertise<geometry_msgs::PoseStamped> (name_of_node_+"/pose", 1);
60  }
61 
62  status_gba_publisher_ = node_handle_.advertise<std_msgs::Bool> (name_of_node_+"/gba_running", 1);
63 }
64 
65 
66 void Node::Update () {
67  cv::Mat position = orb_slam_->GetCurrentPosition();
68 
69  if (!position.empty()) {
70  if (publish_tf_param_){
72  }
73 
74  if (publish_pose_param_) {
76  }
77  }
78 
80 
83  }
84 
86 
87 }
88 
89 
90 void Node::PublishMapPoints (std::vector<ORB_SLAM2::MapPoint*> map_points) {
91  sensor_msgs::PointCloud2 cloud = MapPointsToPointCloud (map_points);
93 }
94 
95 tf2::Transform Node::TransformToTarget (tf2::Transform tf_in, std::string frame_in, std::string frame_target) {
96  // Transform tf_in from frame_in to frame_target
97  tf2::Transform tf_map2orig = tf_in;
98  tf2::Transform tf_orig2target;
99  tf2::Transform tf_map2target;
100 
101  tf2::Stamped<tf2::Transform> transformStamped_temp;
102  try {
103  // Get the transform from camera to target
104  geometry_msgs::TransformStamped tf_msg = tfBuffer->lookupTransform(frame_in, frame_target, ros::Time(0));
105  // Convert to tf2
106  tf2::fromMsg(tf_msg, transformStamped_temp);
107  tf_orig2target.setBasis(transformStamped_temp.getBasis());
108  tf_orig2target.setOrigin(transformStamped_temp.getOrigin());
109 
110  } catch (tf2::TransformException &ex) {
111  ROS_WARN("%s",ex.what());
112  //ros::Duration(1.0).sleep();
113  tf_orig2target.setIdentity();
114  }
115 
116  /*
117  // Print debug info
118  double roll, pitch, yaw;
119  // Print debug map2orig
120  tf2::Matrix3x3(tf_map2orig.getRotation()).getRPY(roll, pitch, yaw);
121  ROS_INFO("Static transform Map to Orig [%s -> %s]",
122  map_frame_id_param_.c_str(), frame_in.c_str());
123  ROS_INFO(" * Translation: {%.3f,%.3f,%.3f}",
124  tf_map2orig.getOrigin().x(), tf_map2orig.getOrigin().y(), tf_map2orig.getOrigin().z());
125  ROS_INFO(" * Rotation: {%.3f,%.3f,%.3f}",
126  RAD2DEG(roll), RAD2DEG(pitch), RAD2DEG(yaw));
127  // Print debug tf_orig2target
128  tf2::Matrix3x3(tf_orig2target.getRotation()).getRPY(roll, pitch, yaw);
129  ROS_INFO("Static transform Orig to Target [%s -> %s]",
130  frame_in.c_str(), frame_target.c_str());
131  ROS_INFO(" * Translation: {%.3f,%.3f,%.3f}",
132  tf_orig2target.getOrigin().x(), tf_orig2target.getOrigin().y(), tf_orig2target.getOrigin().z());
133  ROS_INFO(" * Rotation: {%.3f,%.3f,%.3f}",
134  RAD2DEG(roll), RAD2DEG(pitch), RAD2DEG(yaw));
135  // Print debug map2target
136  tf2::Matrix3x3(tf_map2target.getRotation()).getRPY(roll, pitch, yaw);
137  ROS_INFO("Static transform Map to Target [%s -> %s]",
138  map_frame_id_param_.c_str(), frame_target.c_str());
139  ROS_INFO(" * Translation: {%.3f,%.3f,%.3f}",
140  tf_map2target.getOrigin().x(), tf_map2target.getOrigin().y(), tf_map2target.getOrigin().z());
141  ROS_INFO(" * Rotation: {%.3f,%.3f,%.3f}",
142  RAD2DEG(roll), RAD2DEG(pitch), RAD2DEG(yaw));
143  */
144 
145  // Transform from map to target
146  tf_map2target = tf_map2orig * tf_orig2target;
147  return tf_map2target;
148 }
149 
150 void Node::PublishPositionAsTransform (cv::Mat position) {
151  // Get transform from map to camera frame
152  tf2::Transform tf_transform = TransformFromMat(position);
153 
154  // Make transform from camera frame to target frame
156 
157  // Make message
158  tf2::Stamped<tf2::Transform> tf_map2target_stamped;
159  tf_map2target_stamped = tf2::Stamped<tf2::Transform>(tf_map2target, current_frame_time_, map_frame_id_param_);
160  geometry_msgs::TransformStamped msg = tf2::toMsg(tf_map2target_stamped);
161  msg.child_frame_id = target_frame_id_param_;
162  // Broadcast tf
163  static tf2_ros::TransformBroadcaster tf_broadcaster;
164  tf_broadcaster.sendTransform(msg);
165 }
166 
167 void Node::PublishPositionAsPoseStamped (cv::Mat position) {
168  tf2::Transform tf_position = TransformFromMat(position);
169 
170  // Make transform from camera frame to target frame
172 
173  // Make message
174  tf2::Stamped<tf2::Transform> tf_position_target_stamped;
175  tf_position_target_stamped = tf2::Stamped<tf2::Transform>(tf_position_target, current_frame_time_, map_frame_id_param_);
176  geometry_msgs::PoseStamped pose_msg;
177  tf2::toMsg(tf_position_target_stamped, pose_msg);
178  pose_publisher_.publish(pose_msg);
179 }
180 
181 void Node::PublishGBAStatus (bool gba_status) {
182  std_msgs::Bool gba_status_msg;
183  gba_status_msg.data = gba_status;
184  status_gba_publisher_.publish(gba_status_msg);
185 }
186 
187 void Node::PublishRenderedImage (cv::Mat image) {
188  std_msgs::Header header;
189  header.stamp = current_frame_time_;
190  header.frame_id = map_frame_id_param_;
191  const sensor_msgs::ImagePtr rendered_image_msg = cv_bridge::CvImage(header, "bgr8", image).toImageMsg();
192  rendered_image_publisher_.publish(rendered_image_msg);
193 }
194 
195 
196 tf2::Transform Node::TransformFromMat (cv::Mat position_mat) {
197  cv::Mat rotation(3,3,CV_32F);
198  cv::Mat translation(3,1,CV_32F);
199 
200  rotation = position_mat.rowRange(0,3).colRange(0,3);
201  translation = position_mat.rowRange(0,3).col(3);
202 
203 
204  tf2::Matrix3x3 tf_camera_rotation (rotation.at<float> (0,0), rotation.at<float> (0,1), rotation.at<float> (0,2),
205  rotation.at<float> (1,0), rotation.at<float> (1,1), rotation.at<float> (1,2),
206  rotation.at<float> (2,0), rotation.at<float> (2,1), rotation.at<float> (2,2)
207  );
208 
209  tf2::Vector3 tf_camera_translation (translation.at<float> (0), translation.at<float> (1), translation.at<float> (2));
210 
211  //Coordinate transformation matrix from orb coordinate system to ros coordinate system
212  const tf2::Matrix3x3 tf_orb_to_ros (0, 0, 1,
213  -1, 0, 0,
214  0,-1, 0);
215 
216  //Transform from orb coordinate system to ros coordinate system on camera coordinates
217  tf_camera_rotation = tf_orb_to_ros*tf_camera_rotation;
218  tf_camera_translation = tf_orb_to_ros*tf_camera_translation;
219 
220  //Inverse matrix
221  tf_camera_rotation = tf_camera_rotation.transpose();
222  tf_camera_translation = -(tf_camera_rotation*tf_camera_translation);
223 
224  //Transform from orb coordinate system to ros coordinate system on map coordinates
225  tf_camera_rotation = tf_orb_to_ros*tf_camera_rotation;
226  tf_camera_translation = tf_orb_to_ros*tf_camera_translation;
227 
228  return tf2::Transform (tf_camera_rotation, tf_camera_translation);
229 }
230 
231 
232 sensor_msgs::PointCloud2 Node::MapPointsToPointCloud (std::vector<ORB_SLAM2::MapPoint*> map_points) {
233  if (map_points.size() == 0) {
234  std::cout << "Map point vector is empty!" << std::endl;
235  }
236 
237  sensor_msgs::PointCloud2 cloud;
238 
239  const int num_channels = 3; // x y z
240 
241  cloud.header.stamp = current_frame_time_;
242  cloud.header.frame_id = map_frame_id_param_;
243  cloud.height = 1;
244  cloud.width = map_points.size();
245  cloud.is_bigendian = false;
246  cloud.is_dense = true;
247  cloud.point_step = num_channels * sizeof(float);
248  cloud.row_step = cloud.point_step * cloud.width;
249  cloud.fields.resize(num_channels);
250 
251  std::string channel_id[] = { "x", "y", "z"};
252  for (int i = 0; i<num_channels; i++) {
253  cloud.fields[i].name = channel_id[i];
254  cloud.fields[i].offset = i * sizeof(float);
255  cloud.fields[i].count = 1;
256  cloud.fields[i].datatype = sensor_msgs::PointField::FLOAT32;
257  }
258 
259  cloud.data.resize(cloud.row_step * cloud.height);
260 
261  unsigned char *cloud_data_ptr = &(cloud.data[0]);
262 
263  float data_array[num_channels];
264  for (unsigned int i=0; i<cloud.width; i++) {
265  if (map_points.at(i)->nObs >= min_observations_per_point_) {
266  data_array[0] = map_points.at(i)->GetWorldPos().at<float> (2); //x. Do the transformation by just reading at the position of z instead of x
267  data_array[1] = -1.0* map_points.at(i)->GetWorldPos().at<float> (0); //y. Do the transformation by just reading at the position of x instead of y
268  data_array[2] = -1.0* map_points.at(i)->GetWorldPos().at<float> (1); //z. Do the transformation by just reading at the position of y instead of z
269  //TODO dont hack the transformation but have a central conversion function for MapPointsToPointCloud and TransformFromMat
270 
271  memcpy(cloud_data_ptr+(i*cloud.point_step), data_array, num_channels*sizeof(float));
272  }
273  }
274 
275  return cloud;
276 }
277 
278 
279 void Node::ParamsChangedCallback(orb_slam2_ros::dynamic_reconfigureConfig &config, uint32_t level) {
280  orb_slam_->EnableLocalizationOnly (config.localize_only);
281  min_observations_per_point_ = config.min_observations_for_ros_map;
282 
283  if (config.reset_map) {
284  orb_slam_->Reset();
285  config.reset_map = false;
286  }
287 
288  orb_slam_->SetMinimumKeyFrames (config.min_num_kf_in_map);
289 }
290 
291 
292 bool Node::SaveMapSrv (orb_slam2_ros::SaveMap::Request &req, orb_slam2_ros::SaveMap::Response &res) {
293  res.success = orb_slam_->SaveMap(req.name);
294 
295  if (res.success) {
296  ROS_INFO_STREAM ("Map was saved as " << req.name);
297  } else {
298  ROS_ERROR ("Map could not be saved.");
299  }
300 
301  return res.success;
302 }
303 
304 
306  //ORB SLAM configuration parameters
307  node_handle_.param(name_of_node_ + "/camera_fps", parameters.maxFrames, 30);
308  node_handle_.param(name_of_node_ + "/camera_rgb_encoding", parameters.RGB, true);
309  node_handle_.param(name_of_node_ + "/ORBextractor/nFeatures", parameters.nFeatures, 1200);
310  node_handle_.param(name_of_node_ + "/ORBextractor/scaleFactor", parameters.scaleFactor, static_cast<float>(1.2));
311  node_handle_.param(name_of_node_ + "/ORBextractor/nLevels", parameters.nLevels, 8);
312  node_handle_.param(name_of_node_ + "/ORBextractor/iniThFAST", parameters.iniThFAST, 20);
313  node_handle_.param(name_of_node_ + "/ORBextractor/minThFAST", parameters.minThFAST, 7);
314 
315  bool load_calibration_from_cam = false;
316  node_handle_.param(name_of_node_ + "/load_calibration_from_cam", load_calibration_from_cam, false);
317 
319  node_handle_.param(name_of_node_ + "/ThDepth", parameters.thDepth, static_cast<float>(35.0));
320  node_handle_.param(name_of_node_ + "/depth_map_factor", parameters.depthMapFactor, static_cast<float>(1.0));
321  }
322 
323  if (load_calibration_from_cam) {
324  ROS_INFO_STREAM ("Listening for camera info on topic " << node_handle_.resolveName(camera_info_topic_));
325  sensor_msgs::CameraInfo::ConstPtr camera_info = ros::topic::waitForMessage<sensor_msgs::CameraInfo>(camera_info_topic_, ros::Duration(1000.0));
326  if(camera_info == nullptr){
327  ROS_WARN("Did not receive camera info before timeout, defaulting to launch file params.");
328  } else {
329  parameters.fx = camera_info->K[0];
330  parameters.fy = camera_info->K[4];
331  parameters.cx = camera_info->K[2];
332  parameters.cy = camera_info->K[5];
333 
334  parameters.baseline = camera_info->P[3];
335 
336  parameters.k1 = camera_info->D[0];
337  parameters.k2 = camera_info->D[1];
338  parameters.p1 = camera_info->D[2];
339  parameters.p2 = camera_info->D[3];
340  parameters.k3 = camera_info->D[4];
341  return;
342  }
343  }
344 
345  bool got_cam_calibration = true;
347  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_baseline", parameters.baseline);
348  }
349 
350  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_fx", parameters.fx);
351  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_fy", parameters.fy);
352  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_cx", parameters.cx);
353  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_cy", parameters.cy);
354  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_k1", parameters.k1);
355  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_k2", parameters.k2);
356  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_p1", parameters.p1);
357  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_p2", parameters.p2);
358  got_cam_calibration &= node_handle_.getParam(name_of_node_ + "/camera_k3", parameters.k3);
359 
360  if (!got_cam_calibration) {
361  ROS_ERROR ("Failed to get camera calibration parameters from the launch file.");
362  throw std::runtime_error("No cam calibration");
363  }
364 }
std::string camera_info_topic_
Definition: Node.h:66
image_transport::Publisher rendered_image_publisher_
Definition: Node.h:88
ros::Publisher status_gba_publisher_
Definition: Node.h:91
std::string name_of_node_
Definition: Node.h:95
void publish(const boost::shared_ptr< M > &message) const
std::string map_frame_id_param_
Definition: Node.h:101
void ParamsChangedCallback(orb_slam2_ros::dynamic_reconfigureConfig &config, uint32_t level)
Definition: Node.cc:279
ros::Publisher map_points_publisher_
Definition: Node.h:89
bool SaveMap(const string &filename)
Definition: System.cc:573
std::string resolveName(const std::string &name, bool remap=true) const
bool isRunningGBA()
Definition: System.cc:292
dynamic_reconfigure::Server< orb_slam2_ros::dynamic_reconfigureConfig > dynamic_param_server_
Definition: Node.h:86
ros::NodeHandle node_handle_
Definition: Node.h:96
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
ORB_SLAM2::System * orb_slam_
Definition: Node.h:63
ros::ServiceServer service_server_
Definition: Node.h:93
ROSCPP_DECL const std::string & getName()
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void EnableLocalizationOnly(bool localize_only)
Definition: System.cc:558
void Shutdown()
Definition: System.cc:303
void PublishGBAStatus(bool gba_status)
Definition: Node.cc:181
#define ROS_WARN(...)
void setIdentity()
void PublishPositionAsPoseStamped(cv::Mat position)
Definition: Node.cc:167
Matrix3x3 transpose() const
TF2SIMD_FORCE_INLINE void setBasis(const Matrix3x3 &basis)
void LoadOrbParameters(ORB_SLAM2::ORBParameters &parameters)
Definition: Node.cc:305
void PublishMapPoints(std::vector< ORB_SLAM2::MapPoint * > map_points)
Definition: Node.cc:90
std::string camera_frame_id_param_
Definition: Node.h:102
std::string map_file_name_param_
Definition: Node.h:104
void publish(const sensor_msgs::Image &message) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ros::Time current_frame_time_
Definition: Node.h:64
void fromMsg(const A &, B &b)
void Init()
Definition: Node.cc:23
void PublishPositionAsTransform(cv::Mat position)
Definition: Node.cc:150
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
TF2SIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
bool SaveMapSrv(orb_slam2_ros::SaveMap::Request &req, orb_slam2_ros::SaveMap::Response &res)
Definition: Node.cc:292
void sendTransform(const geometry_msgs::TransformStamped &transform)
cv::Mat GetCurrentPosition()
Definition: System.cc:471
std::string voc_file_name_param_
Definition: Node.h:105
sensor_msgs::PointCloud2 MapPointsToPointCloud(std::vector< ORB_SLAM2::MapPoint * > map_points)
Definition: Node.cc:232
Node(ORB_SLAM2::System::eSensor sensor, ros::NodeHandle &node_handle, image_transport::ImageTransport &image_transport)
Definition: Node.cc:5
B toMsg(const A &a)
tf2::Transform TransformToTarget(tf2::Transform tf_in, std::string frame_in, std::string frame_target)
Definition: Node.cc:95
void PublishRenderedImage(cv::Mat image)
Definition: Node.cc:187
~Node()
Definition: Node.cc:13
#define ROS_INFO_STREAM(args)
std::string target_frame_id_param_
Definition: Node.h:103
tf2::Transform TransformFromMat(cv::Mat position_mat)
Definition: Node.cc:196
bool publish_pointcloud_param_
Definition: Node.h:107
bool getParam(const std::string &key, std::string &s) const
bool load_map_param_
Definition: Node.h:106
int min_observations_per_point_
Definition: Node.h:110
std::vector< MapPoint * > GetAllMapPoints()
Definition: System.cc:497
bool publish_tf_param_
Definition: Node.h:108
void SaveKeyFrameTrajectoryTUM(const string &filename)
Definition: System.cc:376
ros::Publisher pose_publisher_
Definition: Node.h:90
cv::Mat DrawCurrentFrame()
Definition: System.cc:493
void SetMinimumKeyFrames(int min_num_kf)
Definition: System.cc:467
void Update()
Definition: Node.cc:66
#define ROS_ERROR(...)
boost::shared_ptr< tf2_ros::TransformListener > tfListener
Definition: Node.h:80
boost::shared_ptr< tf2_ros::Buffer > tfBuffer
Definition: Node.h:79
sensor_msgs::ImagePtr toImageMsg() const
image_transport::ImageTransport image_transport_
Definition: Node.h:97
ORB_SLAM2::System::eSensor sensor_
Definition: Node.h:99
bool publish_pose_param_
Definition: Node.h:109


orb_slam2_ros
Author(s):
autogenerated on Wed Apr 21 2021 02:53:05