Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <boost/date_time/gregorian/gregorian_types.hpp>
00038 #include <boost/date_time/posix_time/posix_time.hpp>
00039 #include <boost/date_time/posix_time/posix_time_types.hpp>
00040 #include <boost/thread/thread.hpp>
00041 #include <boost/uuid/uuid.hpp>
00042 #include <boost/uuid/uuid_generators.hpp>
00043 #include <iostream>
00044 #include <string>
00045 #include <tide/ebml_element.h>
00046 #include <tide/file_cluster.h>
00047 #include <tide/segment.h>
00048 #include <tide/simple_block.h>
00049 #include <tide/tide_impl.h>
00050 #include <tide/tracks.h>
00051 #include <tide/track_entry.h>
00052 #include <pcl/point_cloud.h>
00053 #include <pcl/point_types.h>
00054 #include <pcl/io/openni_grabber.h>
00055 #include <sensor_msgs/PointCloud2.h>
00056 #include <pcl/ros/conversions.h>
00057 #include <pcl/visualization/cloud_viewer.h>
00058 #include <pcl/console/parse.h>
00059 #include <pcl/common/time.h>
00060
00061 namespace bpt = boost::posix_time;
00062
00063
00064 class Recorder
00065 {
00066 public:
00067 Recorder(std::string const& filename, std::string const& title)
00068 : filename_(filename), title_(title),
00069 stream_(filename, std::ios::in|std::ios::out|std::ios::trunc),
00070 count_(0)
00071 {
00072 }
00073
00074 void Callback(pcl::PointCloud<pcl::PointXYZ>::ConstPtr const& cloud)
00075 {
00076
00077
00078
00079
00080 bpt::ptime blk_start(bpt::microsec_clock::local_time());
00081 bpt::time_duration blk_offset = blk_start - cltr_start_;
00082 tide::BlockElement::Ptr block(new tide::SimpleBlock(1,
00083 blk_offset.total_microseconds() / 10000));
00084
00085 sensor_msgs::PointCloud2 blob;
00086 pcl::toROSMsg(*cloud, blob);
00087 tide::Block::FramePtr frame_ptr(new tide::Block::Frame(blob.data.begin(),
00088 blob.data.end()));
00089 block->push_back(frame_ptr);
00090 cluster_->push_back(block);
00091
00092 if (++count_ == 30)
00093 {
00094 double now = pcl::getTime();
00095 std::cerr << "Average framerate: " <<
00096 static_cast<double>(count_) / (now - last_) << "Hz\n";
00097 count_ = 0;
00098 last_ = now;
00099 }
00100
00101
00102
00103
00104
00105 bpt::time_duration cluster_len(
00106 bpt::microsec_clock::local_time() - cltr_start_);
00107 if (cluster_len.total_seconds() >= 1)
00108 {
00109
00110 cluster_->finalise(stream_);
00111
00112 cltr_start_ = bpt::microsec_clock::local_time();
00113 bpt::time_duration cltr_offset = cltr_start_ - seg_start_;
00114 cluster_.reset(new tide::FileCluster(
00115 cltr_offset.total_microseconds() / 10000));
00116 cluster_->write(stream_);
00117 }
00118 }
00119
00120 int Run()
00121 {
00122
00123
00124 tide::EBMLElement ebml_el;
00125 ebml_el.write(stream_);
00126
00127
00128
00129
00130 tide::Segment segment;
00131 segment.write(stream_);
00132
00133
00134
00135 boost::uuids::random_generator gen;
00136 boost::uuids::uuid uuid = gen();
00137 std::vector<char> uuid_data(uuid.size());
00138 std::copy(uuid.begin(), uuid.end(), uuid_data.begin());
00139 segment.info.uid(uuid_data);
00140
00141 segment.info.filename(filename_);
00142
00143
00144
00145
00146 segment.info.timecode_scale(10000000);
00147
00148
00149
00150 bpt::ptime basis(boost::gregorian::date(2001, 1, 1));
00151 seg_start_ = boost::posix_time::microsec_clock::local_time();
00152 bpt::time_duration td = seg_start_ - basis;
00153 segment.info.date(td.total_microseconds() * 1000);
00154
00155 segment.info.title(title_);
00156
00157 segment.info.muxing_app("libtide-0.1");
00158 segment.info.writing_app("pcl_video");
00159
00160
00161 tide::Tracks tracks;
00162
00163
00164
00165 tide::TrackEntry::Ptr track(new tide::TrackEntry(1, 1, "pointcloud2"));
00166 track->name("3D video");
00167 track->codec_name("sensor_msgs::PointCloud2");
00168
00169
00170 segment.index.insert(std::make_pair(tracks.id(),
00171 segment.to_segment_offset(stream_.tellp())));
00172
00173 tracks.insert(track);
00174 tracks.write(stream_);
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 segment.index.insert(std::make_pair(tide::ids::Cluster,
00192 segment.to_segment_offset(stream_.tellp())));
00193
00194
00195
00196 pcl::Grabber* interface(new pcl::OpenNIGrabber());
00197 boost::function<void (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&)> f(
00198 boost::bind(&Recorder::Callback, this, _1));
00199 interface->registerCallback(f);
00200
00201 cltr_start_ = bpt::microsec_clock::local_time();
00202 bpt::time_duration cltr_offset = cltr_start_ - seg_start_;
00203 cluster_.reset(new tide::FileCluster(
00204 cltr_offset.total_microseconds() / 10000));
00205 cluster_->write(stream_);
00206 last_ = pcl::getTime();
00207 interface->start();
00208
00209 std::cout << "Recording frames. Press any key to stop.\n";
00210 getchar();
00211
00212 interface->stop();
00213
00214 if (cluster_)
00215 {
00216 cluster_->finalise(stream_);
00217 }
00218
00219
00220
00221 segment.finalise(stream_);
00222
00223 stream_.close();
00224
00225 return 0;
00226 }
00227
00228 private:
00229 std::string filename_;
00230 std::string title_;
00231 std::fstream stream_;
00232 tide::FileCluster::Ptr cluster_;
00233 bpt::ptime seg_start_;
00234 bpt::ptime cltr_start_;
00235 unsigned int count_;
00236 double last_;
00237 };
00238
00239
00240 class Player
00241 {
00242 public:
00243 Player(std::string const& filename)
00244 : filename_(filename), viewer_("PCL Video Player: " + filename)
00245 {
00246
00247
00248 }
00249
00250 int Run()
00251 {
00252
00253
00254 std::ifstream stream(filename_, std::ios::in);
00255 tide::ids::ReadResult id = tide::ids::read(stream);
00256 if (id.first != tide::ids::EBML)
00257 {
00258 std::cerr << "File does not begin with an EBML header.\n";
00259 return 1;
00260 }
00261 tide::EBMLElement ebml_el;
00262 ebml_el.read(stream);
00263 if (ebml_el.doc_type() != tide::TideDocType)
00264 {
00265 std::cerr << "Specified EBML file is not a Tide document.\n";
00266 return 1;
00267 }
00268 if (ebml_el.read_version() > tide::TideEBMLVersion)
00269 {
00270 std::cerr << "This Tide document requires read version " <<
00271 ebml_el.read_version() << ".\n";
00272 return 1;
00273 }
00274 if (ebml_el.doc_read_version() > tide::TideVersionMajor)
00275 {
00276 std::cerr << "This Tide document requires doc read version " <<
00277 ebml_el.read_version() << ".\n";
00278 return 1;
00279 }
00280 std::cerr << "Found EBML header\n";
00281
00282
00283
00284
00285
00286 id = tide::ids::read(stream);
00287 if (id.first != tide::ids::Segment)
00288 {
00289 std::cerr << "Segment element not found\n";
00290 return 1;
00291 }
00292 tide::Segment segment;
00293 segment.read(stream);
00294
00295
00296 bpt::ptime basis(boost::gregorian::date(2001, 1, 1));
00297 bpt::time_duration sd(bpt::microseconds(segment.info.date() / 1000));
00298 bpt::ptime seg_start(basis + sd);
00299
00300
00301
00302
00303
00304
00305
00306 std::streampos tracks_pos(segment.index.find(tide::ids::Tracks)->second);
00307 stream.seekg(segment.to_stream_offset(tracks_pos));
00308
00309
00310 id = tide::ids::read(stream);
00311 if (id.first != tide::ids::Tracks)
00312 {
00313 std::cerr << "Tracks element not at indicated position.\n";
00314 return 1;
00315 }
00316
00317 tide::Tracks tracks;
00318 tracks.read(stream);
00319
00320 if (tracks.empty())
00321 {
00322 std::cerr << "No tracks found.\n";
00323 return 1;
00324 }
00325
00326
00327 if (tracks[1]->codec_id() != "pointcloud2")
00328 {
00329 std::cerr << "Track #1 has wrong codec type " <<
00330 tracks[1]->codec_id() << '\n';
00331 return 1;
00332 }
00333
00334 bpt::ptime pb_start(bpt::microsec_clock::local_time());
00335
00336
00337
00338
00339
00340
00341
00342 for (tide::Segment::FileBlockIterator block(segment.blocks_begin_file(stream));
00343 block != segment.blocks_end_file(stream); ++block)
00344 {
00345 bpt::time_duration blk_offset(bpt::microseconds((
00346 (block.cluster()->timecode() + block->timecode()) *
00347 segment.info.timecode_scale() / 1000)));
00348 bpt::time_duration played_time(bpt::microsec_clock::local_time() -
00349 pb_start);
00350
00351 if (played_time > blk_offset)
00352 {
00353 std::cerr << "Skipping block at " << blk_offset <<
00354 " because current playback time is " << played_time << '\n';
00355 continue;
00356 }
00357
00358
00359
00360
00361
00362 tide::BlockElement::FramePtr frame_data(*block->begin());
00363
00364 sensor_msgs::PointCloud2 blob;
00365 blob.height = 480;
00366 blob.width = 640;
00367 sensor_msgs::PointField ptype;
00368 ptype.name = "x";
00369 ptype.offset = 0;
00370 ptype.datatype = 7;
00371 ptype.count = 1;
00372 blob.fields.push_back(ptype);
00373 ptype.name = "y";
00374 ptype.offset = 4;
00375 ptype.datatype = 7;
00376 ptype.count = 1;
00377 blob.fields.push_back(ptype);
00378 ptype.name = "z";
00379 ptype.offset = 8;
00380 ptype.datatype = 7;
00381 ptype.count = 1;
00382 blob.fields.push_back(ptype);
00383 blob.is_bigendian = false;
00384 blob.point_step = 16;
00385 blob.row_step = 10240;
00386 blob.is_dense = false;
00387 blob.data.assign(frame_data->begin(), frame_data->end());
00388 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
00389 pcl::fromROSMsg(blob, *cloud);
00390
00391
00392 played_time = bpt::microsec_clock::local_time() - pb_start;
00393 bpt::time_duration sleep_time(blk_offset - played_time);
00394 std::cerr << "Will sleep " << sleep_time << " until displaying block\n";
00395 boost::this_thread::sleep(sleep_time);
00396 viewer_.showCloud(cloud);
00397
00398
00399
00400
00401
00402
00403
00404 }
00405
00406 return 0;
00407 }
00408
00409 private:
00410 std::string filename_;
00411
00412 pcl::visualization::CloudViewer viewer_;
00413 };
00414
00415
00416 int main(int argc, char** argv)
00417 {
00418 std::string filename;
00419 if (pcl::console::parse_argument(argc, argv, "-f", filename) < 0)
00420 {
00421 std::cerr << "Usage: " << argv[0] << " -f filename [-p] [-t title]\n";
00422 return 1;
00423 }
00424 std::string title("PCL 3D video");
00425 pcl::console::parse_argument(argc, argv, "-t", title);
00426 if (pcl::console::find_switch(argc, argv, "-p"))
00427 {
00428 Player player(filename);
00429 return player.Run();
00430 }
00431 else
00432 {
00433 Recorder recorder(filename, title);
00434 return recorder.Run();
00435 }
00436 }
00437