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
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #ifndef __nifti_image_proc__PROCESSINGCONFIG_H__
00048 #define __nifti_image_proc__PROCESSINGCONFIG_H__
00049
00050 #include <dynamic_reconfigure/config_tools.h>
00051 #include <limits>
00052 #include <ros/node_handle.h>
00053 #include <dynamic_reconfigure/ConfigDescription.h>
00054 #include <dynamic_reconfigure/ParamDescription.h>
00055 #include <dynamic_reconfigure/Group.h>
00056 #include <dynamic_reconfigure/config_init_mutex.h>
00057 #include <boost/any.hpp>
00058
00059 namespace nifti_image_proc
00060 {
00061 class ProcessingConfigStatics;
00062
00063 class ProcessingConfig
00064 {
00065 public:
00066 class AbstractParamDescription : public dynamic_reconfigure::ParamDescription
00067 {
00068 public:
00069 AbstractParamDescription(std::string n, std::string t, uint32_t l,
00070 std::string d, std::string e)
00071 {
00072 name = n;
00073 type = t;
00074 level = l;
00075 description = d;
00076 edit_method = e;
00077 }
00078
00079 virtual void clamp(ProcessingConfig &config, const ProcessingConfig &max, const ProcessingConfig &min) const = 0;
00080 virtual void calcLevel(uint32_t &level, const ProcessingConfig &config1, const ProcessingConfig &config2) const = 0;
00081 virtual void fromServer(const ros::NodeHandle &nh, ProcessingConfig &config) const = 0;
00082 virtual void toServer(const ros::NodeHandle &nh, const ProcessingConfig &config) const = 0;
00083 virtual bool fromMessage(const dynamic_reconfigure::Config &msg, ProcessingConfig &config) const = 0;
00084 virtual void toMessage(dynamic_reconfigure::Config &msg, const ProcessingConfig &config) const = 0;
00085 virtual void getValue(const ProcessingConfig &config, boost::any &val) const = 0;
00086 };
00087
00088 typedef boost::shared_ptr<AbstractParamDescription> AbstractParamDescriptionPtr;
00089 typedef boost::shared_ptr<const AbstractParamDescription> AbstractParamDescriptionConstPtr;
00090
00091 template <class T>
00092 class ParamDescription : public AbstractParamDescription
00093 {
00094 public:
00095 ParamDescription(std::string name, std::string type, uint32_t level,
00096 std::string description, std::string edit_method, T ProcessingConfig::* f) :
00097 AbstractParamDescription(name, type, level, description, edit_method),
00098 field(f)
00099 {}
00100
00101 T (ProcessingConfig::* field);
00102
00103 virtual void clamp(ProcessingConfig &config, const ProcessingConfig &max, const ProcessingConfig &min) const
00104 {
00105 if (config.*field > max.*field)
00106 config.*field = max.*field;
00107
00108 if (config.*field < min.*field)
00109 config.*field = min.*field;
00110 }
00111
00112 virtual void calcLevel(uint32_t &comb_level, const ProcessingConfig &config1, const ProcessingConfig &config2) const
00113 {
00114 if (config1.*field != config2.*field)
00115 comb_level |= level;
00116 }
00117
00118 virtual void fromServer(const ros::NodeHandle &nh, ProcessingConfig &config) const
00119 {
00120 nh.getParam(name, config.*field);
00121 }
00122
00123 virtual void toServer(const ros::NodeHandle &nh, const ProcessingConfig &config) const
00124 {
00125 nh.setParam(name, config.*field);
00126 }
00127
00128 virtual bool fromMessage(const dynamic_reconfigure::Config &msg, ProcessingConfig &config) const
00129 {
00130 return dynamic_reconfigure::ConfigTools::getParameter(msg, name, config.*field);
00131 }
00132
00133 virtual void toMessage(dynamic_reconfigure::Config &msg, const ProcessingConfig &config) const
00134 {
00135 dynamic_reconfigure::ConfigTools::appendParameter(msg, name, config.*field);
00136 }
00137
00138 virtual void getValue(const ProcessingConfig &config, boost::any &val) const
00139 {
00140 val = config.*field;
00141 }
00142 };
00143
00144 class AbstractGroupDescription : public dynamic_reconfigure::Group
00145 {
00146 public:
00147 AbstractGroupDescription(std::string n, std::string t, int p, int i, bool s)
00148 {
00149 name = n;
00150 type = t;
00151 parent = p;
00152 state = s;
00153 id = i;
00154 }
00155
00156 std::vector<AbstractParamDescriptionConstPtr> abstract_parameters;
00157 bool state;
00158
00159 virtual void toMessage(dynamic_reconfigure::Config &msg, const boost::any &config) const = 0;
00160 virtual bool fromMessage(const dynamic_reconfigure::Config &msg, boost::any &config) const =0;
00161 virtual void updateParams(boost::any &cfg, ProcessingConfig &top) const= 0;
00162 virtual void setInitialState(boost::any &cfg) const = 0;
00163
00164
00165 void convertParams()
00166 {
00167 for(std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = abstract_parameters.begin(); i != abstract_parameters.end(); i++)
00168 {
00169 parameters.push_back(dynamic_reconfigure::ParamDescription(**i));
00170 }
00171 }
00172 };
00173
00174 typedef boost::shared_ptr<AbstractGroupDescription> AbstractGroupDescriptionPtr;
00175 typedef boost::shared_ptr<const AbstractGroupDescription> AbstractGroupDescriptionConstPtr;
00176
00177 template<class T, class PT>
00178 class GroupDescription : public AbstractGroupDescription
00179 {
00180 public:
00181 GroupDescription(std::string name, std::string type, int parent, int id, bool s, T PT::* f) : AbstractGroupDescription(name, type, parent, id, s), field(f)
00182 {
00183 }
00184
00185 GroupDescription(const GroupDescription<T, PT>& g): AbstractGroupDescription(g.name, g.type, g.parent, g.id, g.state), field(g.field), groups(g.groups)
00186 {
00187 parameters = g.parameters;
00188 abstract_parameters = g.abstract_parameters;
00189 }
00190
00191 virtual bool fromMessage(const dynamic_reconfigure::Config &msg, boost::any &cfg) const
00192 {
00193 PT* config = boost::any_cast<PT*>(cfg);
00194 if(!dynamic_reconfigure::ConfigTools::getGroupState(msg, name, (*config).*field))
00195 return false;
00196
00197 for(std::vector<AbstractGroupDescriptionConstPtr>::const_iterator i = groups.begin(); i != groups.end(); i++)
00198 {
00199 boost::any n = &((*config).*field);
00200 if(!(*i)->fromMessage(msg, n))
00201 return false;
00202 }
00203
00204 return true;
00205 }
00206
00207 virtual void setInitialState(boost::any &cfg) const
00208 {
00209 PT* config = boost::any_cast<PT*>(cfg);
00210 T* group = &((*config).*field);
00211 group->state = state;
00212
00213 for(std::vector<AbstractGroupDescriptionConstPtr>::const_iterator i = groups.begin(); i != groups.end(); i++)
00214 {
00215 boost::any n = boost::any(&((*config).*field));
00216 (*i)->setInitialState(n);
00217 }
00218
00219 }
00220
00221 virtual void updateParams(boost::any &cfg, ProcessingConfig &top) const
00222 {
00223 PT* config = boost::any_cast<PT*>(cfg);
00224
00225 T* f = &((*config).*field);
00226 f->setParams(top, abstract_parameters);
00227
00228 for(std::vector<AbstractGroupDescriptionConstPtr>::const_iterator i = groups.begin(); i != groups.end(); i++)
00229 {
00230 boost::any n = &((*config).*field);
00231 (*i)->updateParams(n, top);
00232 }
00233 }
00234
00235 virtual void toMessage(dynamic_reconfigure::Config &msg, const boost::any &cfg) const
00236 {
00237 const PT config = boost::any_cast<PT>(cfg);
00238 dynamic_reconfigure::ConfigTools::appendGroup<T>(msg, name, id, parent, config.*field);
00239
00240 for(std::vector<AbstractGroupDescriptionConstPtr>::const_iterator i = groups.begin(); i != groups.end(); i++)
00241 {
00242 (*i)->toMessage(msg, config.*field);
00243 }
00244 }
00245
00246 T (PT::* field);
00247 std::vector<ProcessingConfig::AbstractGroupDescriptionConstPtr> groups;
00248 };
00249
00250 class DEFAULT
00251 {
00252 public:
00253 DEFAULT()
00254 {
00255 state = true;
00256 name = "Default";
00257 }
00258
00259 void setParams(ProcessingConfig &config, const std::vector<AbstractParamDescriptionConstPtr> params)
00260 {
00261 for (std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = params.begin(); i != params.end(); i++)
00262 {
00263 boost::any val;
00264 (*i)->getValue(config, val);
00265
00266 if("min_intensity"==(*i)->name){min_intensity = boost::any_cast<int>(val);}
00267 if("max_intensity"==(*i)->name){max_intensity = boost::any_cast<int>(val);}
00268 if("gamma"==(*i)->name){gamma = boost::any_cast<double>(val);}
00269 if("percent_saturated"==(*i)->name){percent_saturated = boost::any_cast<double>(val);}
00270 }
00271 }
00272
00273 int min_intensity;
00274 int max_intensity;
00275 double gamma;
00276 double percent_saturated;
00277
00278 bool state;
00279 std::string name;
00280
00281
00282 }groups;
00283
00284
00285
00286
00287 int min_intensity;
00288
00289 int max_intensity;
00290
00291 double gamma;
00292
00293 double percent_saturated;
00294
00295
00296 bool __fromMessage__(dynamic_reconfigure::Config &msg)
00297 {
00298 const std::vector<AbstractParamDescriptionConstPtr> &__param_descriptions__ = __getParamDescriptions__();
00299 const std::vector<AbstractGroupDescriptionConstPtr> &__group_descriptions__ = __getGroupDescriptions__();
00300
00301 int count = 0;
00302 for (std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = __param_descriptions__.begin(); i != __param_descriptions__.end(); i++)
00303 if ((*i)->fromMessage(msg, *this))
00304 count++;
00305
00306 for (std::vector<AbstractGroupDescriptionConstPtr>::const_iterator i = __group_descriptions__.begin(); i != __group_descriptions__.end(); i ++)
00307 {
00308 if ((*i)->id == 0)
00309 {
00310 boost::any n = boost::any(this);
00311 (*i)->updateParams(n, *this);
00312 (*i)->fromMessage(msg, n);
00313 }
00314 }
00315
00316 if (count != dynamic_reconfigure::ConfigTools::size(msg))
00317 {
00318 ROS_ERROR("ProcessingConfig::__fromMessage__ called with an unexpected parameter.");
00319 ROS_ERROR("Booleans:");
00320 for (unsigned int i = 0; i < msg.bools.size(); i++)
00321 ROS_ERROR(" %s", msg.bools[i].name.c_str());
00322 ROS_ERROR("Integers:");
00323 for (unsigned int i = 0; i < msg.ints.size(); i++)
00324 ROS_ERROR(" %s", msg.ints[i].name.c_str());
00325 ROS_ERROR("Doubles:");
00326 for (unsigned int i = 0; i < msg.doubles.size(); i++)
00327 ROS_ERROR(" %s", msg.doubles[i].name.c_str());
00328 ROS_ERROR("Strings:");
00329 for (unsigned int i = 0; i < msg.strs.size(); i++)
00330 ROS_ERROR(" %s", msg.strs[i].name.c_str());
00331
00332
00333 return false;
00334 }
00335 return true;
00336 }
00337
00338
00339
00340 void __toMessage__(dynamic_reconfigure::Config &msg, const std::vector<AbstractParamDescriptionConstPtr> &__param_descriptions__, const std::vector<AbstractGroupDescriptionConstPtr> &__group_descriptions__) const
00341 {
00342 dynamic_reconfigure::ConfigTools::clear(msg);
00343 for (std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = __param_descriptions__.begin(); i != __param_descriptions__.end(); i++)
00344 (*i)->toMessage(msg, *this);
00345
00346 for (std::vector<AbstractGroupDescriptionConstPtr>::const_iterator i = __group_descriptions__.begin(); i != __group_descriptions__.end(); i++)
00347 {
00348 if((*i)->id == 0)
00349 {
00350 (*i)->toMessage(msg, *this);
00351 }
00352 }
00353 }
00354
00355 void __toMessage__(dynamic_reconfigure::Config &msg) const
00356 {
00357 const std::vector<AbstractParamDescriptionConstPtr> &__param_descriptions__ = __getParamDescriptions__();
00358 const std::vector<AbstractGroupDescriptionConstPtr> &__group_descriptions__ = __getGroupDescriptions__();
00359 __toMessage__(msg, __param_descriptions__, __group_descriptions__);
00360 }
00361
00362 void __toServer__(const ros::NodeHandle &nh) const
00363 {
00364 const std::vector<AbstractParamDescriptionConstPtr> &__param_descriptions__ = __getParamDescriptions__();
00365 for (std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = __param_descriptions__.begin(); i != __param_descriptions__.end(); i++)
00366 (*i)->toServer(nh, *this);
00367 }
00368
00369 void __fromServer__(const ros::NodeHandle &nh)
00370 {
00371 static bool setup=false;
00372
00373 const std::vector<AbstractParamDescriptionConstPtr> &__param_descriptions__ = __getParamDescriptions__();
00374 for (std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = __param_descriptions__.begin(); i != __param_descriptions__.end(); i++)
00375 (*i)->fromServer(nh, *this);
00376
00377 const std::vector<AbstractGroupDescriptionConstPtr> &__group_descriptions__ = __getGroupDescriptions__();
00378 for (std::vector<AbstractGroupDescriptionConstPtr>::const_iterator i = __group_descriptions__.begin(); i != __group_descriptions__.end(); i++){
00379 if (!setup && (*i)->id == 0) {
00380 setup = true;
00381 boost::any n = boost::any(this);
00382 (*i)->setInitialState(n);
00383 }
00384 }
00385 }
00386
00387 void __clamp__()
00388 {
00389 const std::vector<AbstractParamDescriptionConstPtr> &__param_descriptions__ = __getParamDescriptions__();
00390 const ProcessingConfig &__max__ = __getMax__();
00391 const ProcessingConfig &__min__ = __getMin__();
00392 for (std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = __param_descriptions__.begin(); i != __param_descriptions__.end(); i++)
00393 (*i)->clamp(*this, __max__, __min__);
00394 }
00395
00396 uint32_t __level__(const ProcessingConfig &config) const
00397 {
00398 const std::vector<AbstractParamDescriptionConstPtr> &__param_descriptions__ = __getParamDescriptions__();
00399 uint32_t level = 0;
00400 for (std::vector<AbstractParamDescriptionConstPtr>::const_iterator i = __param_descriptions__.begin(); i != __param_descriptions__.end(); i++)
00401 (*i)->calcLevel(level, config, *this);
00402 return level;
00403 }
00404
00405 static const dynamic_reconfigure::ConfigDescription &__getDescriptionMessage__();
00406 static const ProcessingConfig &__getDefault__();
00407 static const ProcessingConfig &__getMax__();
00408 static const ProcessingConfig &__getMin__();
00409 static const std::vector<AbstractParamDescriptionConstPtr> &__getParamDescriptions__();
00410 static const std::vector<AbstractGroupDescriptionConstPtr> &__getGroupDescriptions__();
00411
00412 private:
00413 static const ProcessingConfigStatics *__get_statics__();
00414 };
00415
00416 template <>
00417 inline void ProcessingConfig::ParamDescription<std::string>::clamp(ProcessingConfig &config, const ProcessingConfig &max, const ProcessingConfig &min) const
00418 {
00419 return;
00420 }
00421
00422 class ProcessingConfigStatics
00423 {
00424 friend class ProcessingConfig;
00425
00426 ProcessingConfigStatics()
00427 {
00428 ProcessingConfig::GroupDescription<ProcessingConfig::DEFAULT, ProcessingConfig> Default("Default", "", 0, 0, true, &ProcessingConfig::groups);
00429
00430 __min__.min_intensity = 0;
00431
00432 __max__.min_intensity = 255;
00433
00434 __default__.min_intensity = 0;
00435
00436 Default.abstract_parameters.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<int>("min_intensity", "int", 0, "Minimum intensity of a pixel", "", &ProcessingConfig::min_intensity)));
00437
00438 __param_descriptions__.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<int>("min_intensity", "int", 0, "Minimum intensity of a pixel", "", &ProcessingConfig::min_intensity)));
00439
00440 __min__.max_intensity = 0;
00441
00442 __max__.max_intensity = 255;
00443
00444 __default__.max_intensity = 255;
00445
00446 Default.abstract_parameters.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<int>("max_intensity", "int", 0, "Maximum intensity of a pixel", "", &ProcessingConfig::max_intensity)));
00447
00448 __param_descriptions__.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<int>("max_intensity", "int", 0, "Maximum intensity of a pixel", "", &ProcessingConfig::max_intensity)));
00449
00450 __min__.gamma = 0.25;
00451
00452 __max__.gamma = 4.0;
00453
00454 __default__.gamma = 1.0;
00455
00456 Default.abstract_parameters.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<double>("gamma", "double", 0, "Gamma correction", "", &ProcessingConfig::gamma)));
00457
00458 __param_descriptions__.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<double>("gamma", "double", 0, "Gamma correction", "", &ProcessingConfig::gamma)));
00459
00460 __min__.percent_saturated = 0.0;
00461
00462 __max__.percent_saturated = 100.0;
00463
00464 __default__.percent_saturated = 5.0;
00465
00466 Default.abstract_parameters.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<double>("percent_saturated", "double", 0, "Percent of saturated pixels", "", &ProcessingConfig::percent_saturated)));
00467
00468 __param_descriptions__.push_back(ProcessingConfig::AbstractParamDescriptionConstPtr(new ProcessingConfig::ParamDescription<double>("percent_saturated", "double", 0, "Percent of saturated pixels", "", &ProcessingConfig::percent_saturated)));
00469
00470 Default.convertParams();
00471
00472 __group_descriptions__.push_back(ProcessingConfig::AbstractGroupDescriptionConstPtr(new ProcessingConfig::GroupDescription<ProcessingConfig::DEFAULT, ProcessingConfig>(Default)));
00473
00474
00475 for (std::vector<ProcessingConfig::AbstractGroupDescriptionConstPtr>::const_iterator i = __group_descriptions__.begin(); i != __group_descriptions__.end(); i++)
00476 {
00477 __description_message__.groups.push_back(**i);
00478 }
00479 __max__.__toMessage__(__description_message__.max, __param_descriptions__, __group_descriptions__);
00480 __min__.__toMessage__(__description_message__.min, __param_descriptions__, __group_descriptions__);
00481 __default__.__toMessage__(__description_message__.dflt, __param_descriptions__, __group_descriptions__);
00482 }
00483 std::vector<ProcessingConfig::AbstractParamDescriptionConstPtr> __param_descriptions__;
00484 std::vector<ProcessingConfig::AbstractGroupDescriptionConstPtr> __group_descriptions__;
00485 ProcessingConfig __max__;
00486 ProcessingConfig __min__;
00487 ProcessingConfig __default__;
00488 dynamic_reconfigure::ConfigDescription __description_message__;
00489
00490 static const ProcessingConfigStatics *get_instance()
00491 {
00492
00493
00494
00495
00496 static ProcessingConfigStatics instance;
00497 return &instance;
00498 }
00499 };
00500
00501 inline const dynamic_reconfigure::ConfigDescription &ProcessingConfig::__getDescriptionMessage__()
00502 {
00503 return __get_statics__()->__description_message__;
00504 }
00505
00506 inline const ProcessingConfig &ProcessingConfig::__getDefault__()
00507 {
00508 return __get_statics__()->__default__;
00509 }
00510
00511 inline const ProcessingConfig &ProcessingConfig::__getMax__()
00512 {
00513 return __get_statics__()->__max__;
00514 }
00515
00516 inline const ProcessingConfig &ProcessingConfig::__getMin__()
00517 {
00518 return __get_statics__()->__min__;
00519 }
00520
00521 inline const std::vector<ProcessingConfig::AbstractParamDescriptionConstPtr> &ProcessingConfig::__getParamDescriptions__()
00522 {
00523 return __get_statics__()->__param_descriptions__;
00524 }
00525
00526 inline const std::vector<ProcessingConfig::AbstractGroupDescriptionConstPtr> &ProcessingConfig::__getGroupDescriptions__()
00527 {
00528 return __get_statics__()->__group_descriptions__;
00529 }
00530
00531 inline const ProcessingConfigStatics *ProcessingConfig::__get_statics__()
00532 {
00533 const static ProcessingConfigStatics *statics;
00534
00535 if (statics)
00536 return statics;
00537
00538 boost::mutex::scoped_lock lock(dynamic_reconfigure::__init_mutex__);
00539
00540 if (statics)
00541 return statics;
00542
00543 statics = ProcessingConfigStatics::get_instance();
00544
00545 return statics;
00546 }
00547
00548
00549 }
00550
00551 #endif // __PROCESSINGRECONFIGURATOR_H__