1 #include <gazebo/plugins/CameraPlugin.hh> 3 #include <gazebo/physics/physics.hh> 21 std::deque<double> samples;
32 AverageStat(
size_t numSamples,
double validStDev) :
34 maxSamples(numSamples),
44 double update(
double sample)
46 samples.push_back(sample);
47 if (samples.size() > maxSamples)
51 average = std::accumulate(samples.begin(), samples.end(), 0.0) / samples.size();
52 double stdevSquared = std::accumulate(samples.begin(), samples.end(), 0.0,
53 [&](
double sum,
double xi) {
54 return sum + (xi - average) * (xi - average);
56 stdev = std::sqrt(stdevSquared);
65 double getAverage()
const 75 double getStDev()
const 85 bool isAdequate()
const 87 return (samples.size() >= maxSamples) && (stdev < maxStDev);
137 void Load(gazebo::sensors::SensorPtr parent, sdf::ElementPtr sdf)
override 141 ROS_FATAL_NAMED(
"throttling_camera",
"ROS node for Gazebo has not been initialized, unable to load plugin");
144 ROS_DEBUG_NAMED(
"throttling_camera",
"Initializing ROS throttling (stable-rate) camera");
146 CameraPlugin::Load(parent, sdf);
148 world = gazebo::physics::get_world(parent->WorldName());
149 #if GAZEBO_MAJOR_VERSION >= 8 150 presetManager = world->PresetMgr();
152 presetManager = world->GetPresetManager();
156 if (presetManager->CurrentProfile() !=
"default_physics")
158 gzwarn <<
"Current physics profile is not default_physics, but actually is " << presetManager->CurrentProfile() <<
"\n";
159 if (!presetManager->CurrentProfile(
"default_physics"))
161 gzerr <<
"Could not set current profile to default_physics!\n";
165 double minUpdateRate = parent->UpdateRate();
166 if (sdf->HasElement(
"minUpdateRate"))
168 minUpdateRate = sdf->Get<
double>(
"minUpdateRate");
170 maxUpdateInterval = 1.0 / minUpdateRate;
172 size_t windowSize = 10;
173 if (sdf->HasElement(
"windowSize"))
175 windowSize = sdf->Get<
size_t>(
"windowSize");
178 double maxStDev = 0.02;
179 if (sdf->HasElement(
"maxStDev"))
181 maxStDev = sdf->Get<
double>(
"maxStDev");
184 timeSamples.reset(
new AverageStat(windowSize, maxStDev));
188 parentSensor_ = camPtr;
210 void OnNewFrame(
const unsigned char *image,
unsigned int width,
unsigned int height,
unsigned int depth,
211 const std::string &format)
override {
214 auto sensorUpdateTime = camPtr->LastMeasurementTime();
216 if (!camPtr->IsActive())
218 camPtr->SetActive(
true);
219 last_update_time_ = sensorUpdateTime;
220 timeSamples->reset();
224 boost::mutex::scoped_lock lock(*image_connect_count_lock_);
225 if (*image_connect_count_ > 0)
227 if (sensorUpdateTime < last_update_time_)
229 ROS_WARN_NAMED(
"throttling_camera",
"Negative sensor update time difference (world reset?)");
230 last_update_time_ = sensorUpdateTime;
231 timeSamples->reset();
234 auto timeDelta = sensorUpdateTime - last_update_time_;
235 timeSamples->update(timeDelta.Double());
238 if (timeSamples->isAdequate() && timeSamples->getAverage() > maxUpdateInterval)
241 << timeSamples->getAverage() <<
" (stdev: " << timeSamples->getStDev() <<
")" 242 <<
", but desired update period is " << update_period_
243 <<
", throttling simulation down");
244 boost::any currentRealTimeUpadteRateParam;
245 if (!presetManager->GetCurrentProfileParam(
"real_time_update_rate", currentRealTimeUpadteRateParam))
247 gzerr <<
"Failed to get real time update rate parameter!\n";
249 auto currentRate = boost::any_cast<
double>(currentRealTimeUpadteRateParam);
252 double slowdownFactor = update_period_ / timeSamples->getAverage();
253 auto nextRate = currentRate * slowdownFactor;
254 if (!presetManager->SetCurrentProfileParam(
"real_time_update_rate", nextRate))
256 gzerr <<
"Failed to set real time update rate parameter!\n";
258 if (slowdownFactor < 0.5)
261 "the simulation with a lower PX4_SIM_SPEED_FACTOR value (slowed down from " 262 << currentRate <<
" to " << nextRate <<
" updates per second)");
265 timeSamples->reset();
267 PutCameraData(image, sensorUpdateTime);
268 PublishCameraInfo(sensorUpdateTime);
270 last_update_time_ = sensorUpdateTime;
void OnNewFrame(const unsigned char *image, unsigned int width, unsigned int height, unsigned int depth, const std::string &format) override
#define ROS_WARN_NAMED(name,...)
ROSCPP_DECL bool isInitialized()
void Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf, const std::string &_camera_name_suffix="")
#define ROS_INFO_STREAM_NAMED(name, args)
std::unique_ptr< AverageStat > timeSamples
gazebo::sensors::SensorPtr camPtr
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
GZ_REGISTER_SENSOR_PLUGIN(throttling_camera::ThrottlingCamera)
gazebo::physics::WorldPtr world
#define ROS_DEBUG_NAMED(name,...)
gazebo::physics::PresetManagerPtr presetManager
void Load(gazebo::sensors::SensorPtr parent, sdf::ElementPtr sdf) override
#define ROS_FATAL_NAMED(name,...)
#define ROS_WARN_STREAM_NAMED(name, args)