rosflight_postprocess.cpp
Go to the documentation of this file.
1 #include <sys/stat.h>
2 #include <unistd.h>
3 #include <cstdio>
4 #include <fstream>
5 #include <iostream>
6 #include <string>
7 #include <vector>
8 
9 #pragma GCC diagnostic push
10 #pragma GCC diagnostic ignored "-Wold-style-cast"
11 #pragma GCC diagnostic push
12 #pragma GCC diagnostic ignored "-Wshadow"
13 #include <geometry_msgs/PoseStamped.h>
14 #include <geometry_msgs/TransformStamped.h>
15 #include <rosbag/bag.h>
16 #include <rosbag/view.h>
17 #include <rosflight_msgs/Command.h>
18 #include <sensor_msgs/Imu.h>
19 #include <yaml-cpp/yaml.h>
20 #include <boost/foreach.hpp>
21 #include <experimental/filesystem>
22 #pragma GCC diagnostic pop
23 
24 #include "mavlink/mavlink.h"
25 #include "rosflight.h"
28 #include "test_board.h"
29 
30 using namespace std;
31 namespace fs = std::experimental::filesystem;
32 
33 bool loadParameters(const string filename, rosflight_firmware::ROSflight &RF)
34 {
35  (void)RF;
36  if (!fs::exists(filename))
37  {
38  cout << "unable to find parameter file " << filename << endl;
39  return false;
40  }
41 
42  try
43  {
44  YAML::Node node = YAML::LoadFile(filename);
45  for (auto it = node.begin(); it != node.end(); it++)
46  {
47  if ((*it)["type"].as<int>() == 6)
48  RF.params_.set_param_by_name_int((*it)["name"].as<string>().c_str(), (*it)["value"].as<int>());
49  else if ((*it)["type"].as<int>() == 9)
50  RF.params_.set_param_by_name_float((*it)["name"].as<string>().c_str(), (*it)["value"].as<float>());
51  else
52  throw std::runtime_error("unrecognized parameter type");
53  }
54  int debug = 1;
55  (void)debug;
56  (void)node;
57  }
58  catch (...)
59  {
60  std::cout << "Failed to Read yaml file. Could you have a syntax error?" << filename << std::endl;
61  return false;
62  }
63  cout << "loaded parameters from " << filename << endl;
64  return true;
65 }
66 
68 {
69  cout << "USAGE: rosbag_parser [options]"
70  << "\n\n";
71  cout << "Options:\n";
72  cout << "\t -h, --help\tShow this help message and exit\n";
73  cout << "\t -f FILENAME\tBagfile to parse\n";
74  cout << "\t -p FILENAME\tParameter file to load\n";
75  cout << "\t -s START_TIME\tstart time of bag (seconds)\n";
76  cout << "\t -u DURATION\tduration to run bag (seconds)\n";
77  cout << "\t -v Show Verbose Output\n";
78  cout << endl;
79 }
80 
81 int main(int argc, char *argv[])
82 {
83  string bag_filename = "";
84  bool verbose = false;
85  double start_time = 0;
86  double duration = INFINITY;
87  string param_filename = "";
88  InputParser argparse(argc, argv);
89  if (argparse.cmdOptionExists("-h"))
90  displayHelp();
91  if (!argparse.getCmdOption("-f", bag_filename))
92  displayHelp();
93  if (!argparse.getCmdOption("-p", param_filename))
94  displayHelp();
95  argparse.getCmdOption("-s", start_time);
96  argparse.getCmdOption("-d", duration);
97  verbose = argparse.cmdOptionExists("-v");
98 
99  rosbag::Bag bag;
100  try
101  {
102  bag.open(bag_filename.c_str(), rosbag::bagmode::Read);
103  }
104  catch (rosbag::BagIOException e)
105  {
106  fprintf(stderr, "unable to load rosbag %s, %s", bag_filename.c_str(), e.what());
107  return -1;
108  }
109  rosbag::View view(bag);
110 
111  // Get list of topics and print to screen - https://answers.ros.org/question/39345/rosbag-info-in-c/
112  if (verbose)
113  {
114  vector<const rosbag::ConnectionInfo *> connections = view.getConnections();
115  vector<string> topics;
116  vector<string> types;
117  cout << "\nloaded bagfile: " << bag_filename << "\n===================================\n";
118  cout << "Topics\t\tTypes\n----------------------------\n\n" << endl;
119  for (const rosbag::ConnectionInfo *info : connections)
120  {
121  topics.push_back(info->topic);
122  types.push_back(info->datatype);
123  cout << info->topic << "\t\t" << info->datatype << endl;
124  }
125  }
126 
127  // Figure out the end time of the bag
128  double end_time = start_time + duration;
129  end_time = (end_time < view.getEndTime().toSec() - view.getBeginTime().toSec())
130  ? end_time
131  : view.getEndTime().toSec() - view.getBeginTime().toSec();
132  if (verbose)
133  cout << "Playing bag from: = " << start_time << "s to: " << end_time << "s" << endl;
134 
135  // Create the ROSflight object
137  rosflight_firmware::Mavlink mavlink(board);
138  rosflight_firmware::ROSflight RF(board, mavlink);
139  RF.init();
140 
141  if (!param_filename.empty())
142  {
143  if (!loadParameters(param_filename, RF))
144  return -1;
145  }
146 
147  // Get some time variables
148  ros::Time bag_start = view.getBeginTime() + ros::Duration(start_time);
149  ros::Time bag_end = view.getBeginTime() + ros::Duration(end_time);
150 
151  // Prepare the output file
152  fstream est_log, truth_log, imu_log, filtered_imu_log, cmd_log;
153  fs::create_directories("/tmp/rosflight_post_process/");
154  est_log.open("/tmp/rosflight_post_process/estimate.bin", std::ofstream::out | std::ofstream::trunc);
155  truth_log.open("/tmp/rosflight_post_process/truth.bin", std::ofstream::out | std::ofstream::trunc);
156  imu_log.open("/tmp/rosflight_post_process/imu.bin", std::ofstream::out | std::ofstream::trunc);
157  filtered_imu_log.open("/tmp/rosflight_post_process/imu_filt.bin", std::ofstream::out | std::ofstream::trunc);
158  cmd_log.open("/tmp/rosflight_post_process/cmd.bin", std::ofstream::out | std::ofstream::trunc);
159 
160  ProgressBar prog(view.size(), 80);
161  int i = 0;
162  bool time_initialized = false;
163  bool pose_initialized = false;
164  for (rosbag::MessageInstance const m : view)
165  {
166  // skip messages before start time
167  if (m.getTime() < bag_start)
168  continue;
169 
170  // End bag after duration has passed
171  if (m.getTime() > bag_end)
172  break;
173 
174  prog.print(++i);
175 
177 
178  // Cast datatype into proper format and call the appropriate callback
179  string datatype = m.getDataType();
180 
181  if (datatype.compare("sensor_msgs/Imu") == 0)
182  {
183  const sensor_msgs::ImuConstPtr imu(m.instantiate<sensor_msgs::Imu>());
184 
185  if (!time_initialized)
186  {
187  bag_start = imu->header.stamp;
188  board.set_time(0);
189  time_initialized = true;
190  }
191 
192  // Move the board time forward
193  float acc[3] = {(float)imu->linear_acceleration.x, (float)imu->linear_acceleration.y,
194  (float)imu->linear_acceleration.z};
195  float gyro[3] = {(float)imu->angular_velocity.x, (float)imu->angular_velocity.y, (float)imu->angular_velocity.z};
196  int64_t t_us = (imu->header.stamp - bag_start).toNSec() / 1000;
197 
198  board.set_imu(acc, gyro, t_us);
199  RF.run();
200  double est[8] = {(double)t_us / 1e6,
201  (double)RF.estimator_.state().attitude.w,
202  (double)RF.estimator_.state().attitude.x,
203  (double)RF.estimator_.state().attitude.y,
204  (double)RF.estimator_.state().attitude.z,
205  (double)RF.estimator_.bias().x,
206  (double)RF.estimator_.bias().y,
207  (double)RF.estimator_.bias().z};
208  est_log.write((char *)est, sizeof(est));
209 
210  double imud[7] = {(double)t_us / 1e6, (double)acc[0], (double)acc[1], (double)acc[2],
211  (double)gyro[0], (double)gyro[1], (double)gyro[2]};
212  imu_log.write((char *)imud, sizeof(imud));
213 
214  double imuf[7] = {(double)t_us / 1e6,
215  (double)RF.estimator_.accLPF().x,
216  (double)RF.estimator_.accLPF().y,
217  (double)RF.estimator_.accLPF().z,
218  (double)RF.estimator_.gyroLPF().x,
219  (double)RF.estimator_.gyroLPF().y,
220  (double)RF.estimator_.gyroLPF().z};
221 
222  filtered_imu_log.write((char *)imuf, sizeof(imuf));
223  }
224 
225  else if (datatype.compare("geometry_msgs/PoseStamped") == 0)
226  {
227  const geometry_msgs::PoseStampedConstPtr pose(m.instantiate<geometry_msgs::PoseStamped>());
228  double t = (pose->header.stamp - bag_start).toSec();
229  double truth[5] = {t, pose->pose.orientation.w, pose->pose.orientation.x, pose->pose.orientation.y,
230  pose->pose.orientation.z};
231  truth_log.write((char *)truth, sizeof(truth));
232  }
233 
234  else if (datatype.compare("geometry_msgs/TransformStamped") == 0)
235  {
236  const geometry_msgs::TransformStampedConstPtr trans(m.instantiate<geometry_msgs::TransformStamped>());
237  double t = (trans->header.stamp - bag_start).toSec();
238  double truth[5] = {t, trans->transform.rotation.w, trans->transform.rotation.x, trans->transform.rotation.y,
239  trans->transform.rotation.z};
240  truth_log.write((char *)truth, sizeof(truth));
241  }
242 
243  else if (datatype.compare("rosflight_msgs/Command") == 0)
244  {
245  const rosflight_msgs::CommandConstPtr cmd(m.instantiate<rosflight_msgs::Command>());
246  double t = (cmd->header.stamp - bag_start).toSec();
247  double cmdarr[5] = {t, cmd->x, cmd->y, cmd->z, cmd->F};
248  cmd_log.write((char *)cmdarr, sizeof(cmdarr));
249  }
250  }
251  prog.finished();
252  std::cout << std::endl;
253 }
254 #pragma GCC diagnostic pop
est
const turbomath::Vector & accLPF()
std::vector< const ConnectionInfo * > getConnections()
void open(std::string const &filename, uint32_t mode=bagmode::Read)
void set_imu(float *acc, float *gyro, uint64_t time_us)
cmd
void displayHelp()
const turbomath::Vector & bias()
bool loadParameters(const string filename, rosflight_firmware::ROSflight &RF)
uint32_t size()
const State & state() const
ros::Time getBeginTime()
bool cmdOptionExists(const std::string &option) const
Definition: input_parser.h:26
const turbomath::Vector & gyroLPF()
void set_time(uint64_t time_us)
imu
uint32_t out
int i
bool getCmdOption(const std::string &option, T &ret) const
Definition: input_parser.h:13
int main(int argc, char *argv[])
ros::Time getEndTime()
uint32_t start_time
bool set_param_by_name_int(const char name[PARAMS_NAME_LENGTH], int32_t value)
bool set_param_by_name_float(const char name[PARAMS_NAME_LENGTH], float value)
truth
int debug


rosflight_utils
Author(s):
autogenerated on Thu Apr 15 2021 05:10:06