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 #include "rosrecord/constants.h"
00036
00037 #include <iomanip>
00038 #include <signal.h>
00039 #include <sys/statvfs.h>
00040
00041 #include <boost/filesystem.hpp>
00042 #include <boost/iostreams/filter/gzip.hpp>
00043 #include <boost/iostreams/filter/bzip2.hpp>
00044
00045 #include "ros/message.h"
00046
00047 #undef ROS_DEPRECATED
00048 #define ROS_DEPRECATED
00049 #define IGNORE_ROSRECORD_DEPRECATED
00050 #include "rosrecord/Recorder.h"
00051
00052 using std::string;
00053
00054 namespace ros {
00055 namespace record {
00056
00057 Recorder::Recorder() :
00058 logging_enabled_(true)
00059 {
00060 }
00061
00062 Recorder::~Recorder()
00063 {
00064 close();
00065 }
00066
00067 bool Recorder::open(string const& file_name, bool random_access)
00068 {
00069 try
00070 {
00071 bag_.open(file_name, rosbag::bagmode::Write);
00072
00073 check_disk_next_ = ros::WallTime::now() + ros::WallDuration().fromSec(20.0);
00074 warn_next_ = ros::WallTime();
00075 checkDisk();
00076
00077 return true;
00078 }
00079 catch (rosbag::BagException ex)
00080 {
00081 ROS_FATAL("rosrecord::Record: Failed to open file: %s", file_name.c_str());
00082 return false;
00083 }
00084 }
00085
00086 pos_t Recorder::getOffset() { return bag_.getSize(); }
00087
00088 void Recorder::close()
00089 {
00090 bag_.close();
00091 }
00092
00093 bool Recorder::checkDisk()
00094 {
00095 struct statvfs fiData;
00096
00097 string filename = bag_.getFileName();
00098
00099 if ((statvfs(filename.c_str(), &fiData)) < 0)
00100 {
00101 ROS_WARN("rosrecord::Record: Failed to check filesystem stats.");
00102 }
00103 else
00104 {
00105 unsigned long long free_space = 0;
00106
00107 free_space = (unsigned long long)(fiData.f_bsize) * (unsigned long long)(fiData.f_bavail);
00108
00109 if (free_space < 1073741824ull)
00110 {
00111 ROS_ERROR("rosrecord::Record: Less than 1GB of space free on disk with %s. Disabling logging.", filename.c_str());
00112 logging_enabled_ = false;
00113 return false;
00114 }
00115 else if (free_space < 5368709120ull)
00116 {
00117 ROS_WARN("rosrecord::Record: Less than 5GB of space free on disk with %s.", filename.c_str());
00118 }
00119 else
00120 {
00121 logging_enabled_ = true;
00122 }
00123 }
00124 return true;
00125 }
00126
00127 bool Recorder::record(string topic_name, ros::Message::ConstPtr msg, ros::Time time)
00128 {
00129 return record(topic_name, *msg, time);
00130 }
00131
00132 bool Recorder::record(string topic_name, const ros::Message& msg, ros::Time time)
00133 {
00134 if (!logging_enabled_)
00135 {
00136 ros::WallTime nowtime = ros::WallTime::now();
00137 if (nowtime > warn_next_)
00138 {
00139 warn_next_ = nowtime + ros::WallDuration().fromSec(5.0);
00140 ROS_WARN("Not logging message because logging disabled. Most likely cause is a full disk.");
00141 }
00142 return false;
00143 }
00144
00145 {
00146 boost::mutex::scoped_lock lock(check_disk_mutex_);
00147
00148 if (ros::WallTime::now() > check_disk_next_)
00149 {
00150 check_disk_next_ = check_disk_next_ + ros::WallDuration().fromSec(20.0);
00151
00152 if (!checkDisk())
00153 return false;
00154 }
00155 }
00156
00157 boost::shared_ptr<ros::M_string> hdr = msg.__connection_header;
00158 if (hdr == NULL)
00159 hdr = boost::shared_ptr<ros::M_string>(new ros::M_string);
00160 (*hdr)["type"] = std::string(ros::message_traits::datatype(msg));
00161 (*hdr)["md5sum"] = std::string(ros::message_traits::md5sum(msg));
00162 (*hdr)["message_definition"] = std::string(ros::message_traits::definition(msg));
00163 if (hdr->find("callerid") == hdr->end())
00164 (*hdr)["callerid"] = string("");
00165 if (hdr->find("latching") == hdr->end())
00166 (*hdr)["latching"] = string("0");
00167
00168 try
00169 {
00170 bag_.write(topic_name, time, msg, hdr);
00171 }
00172 catch (rosbag::BagException ex)
00173 {
00174 ROS_FATAL("rosrecord::Record: could not write to file. Check permissions and diskspace\n");
00175 return false;
00176 }
00177
00178 return true;
00179 }
00180
00181 }
00182 }