Parasol Planning Library (PPL)
ValidationStrategy.h
Go to the documentation of this file.
1 #ifndef PMPL_VALIDATION_STRATEGY_H_
2 #define PMPL_VALIDATION_STRATEGY_H_
3 
4 #include "MPStrategyMethod.h"
5 #include "nonstd/io.h"
6 
7 
13 template <typename MPTraits>
14 class ValidationStrategy : public MPStrategyMethod<MPTraits> {
15 
16  public:
17 
20 
21  typedef typename MPTraits::CfgType CfgType;
22  typedef typename MPTraits::WeightType WeightType;
23  typedef typename MPTraits::RoadmapType RoadmapType;
24  typedef typename RoadmapType::VID VID;
25 
29 
31  struct GoldStandard {
32 
34  enum class Type {Roadmap,
36  CfgPath,
38  History};
39 
41  std::string label;
43  std::string filename;
44 
45  };
46 
50 
52 
54 
55  virtual ~ValidationStrategy() = default;
56 
60 
61  virtual void Initialize() override;
62  virtual void Run() override;
63  virtual void Finalize() override;
64 
66 
67  private:
68 
71 
73  void ValidateResult(const GoldStandard& _g);
74 
76  void ValidateRoadmap(const GoldStandard& _g, RoadmapType* const _output);
77 
79  void ValidatePath(const GoldStandard& _g,
80  const std::vector<CfgType>& _output);
81 
83  void ValidateHistory(const GoldStandard& _g);
84 
88 
89  std::string m_targetLabel;
90  std::vector<GoldStandard> m_goldStandards;
91 
93 
94 };
95 
96 /*----------------------------- Construction ---------------------------------*/
97 
98 template <typename MPTraits>
101  this->SetName("ValidationStrategy");
102 }
103 
104 
105 template <typename MPTraits>
108  this->SetName("ValidationStrategy");
109 
110  m_targetLabel = _node.Read("target", true, "",
111  "The label of the target strategy to validate.");
112 
113 
114  // Read gold standards from child nodes.
115  for(auto& child : _node) {
116  if(child.Name() != "GoldStandard")
117  throw ParseException(child.Where()) << "Only child nodes of type "
118  << "'GoldStandard' are permitted.";
119 
120  GoldStandard g;
121 
122  // Parse the output type.
123  std::string type = child.Read("type", true, "", "The output type.");
124  std::transform(type.begin(), type.end(), type.begin(), ::tolower);
125  if(type == "roadmap")
127  else if(type == "blockroadmap")
129  else if(type == "cfgpath")
131  else if(type == "fullcfgpath")
133  else if(type == "history")
135  else
136  throw ParseException(child.Where()) << "Unrecognized type '" << type
137  << "'.";
138 
139  // Get the object label.
140  switch(g.type) {
145  g.label = child.Read("robot", true, "", "The robot label.");
146  break;
148  g.label = child.Read("label", true, "", "The history label.");
149  break;
150  default:
151  throw RunTimeException(WHERE) << "Unrecognized type.";
152  }
153 
154  // Parse the filename.
155  g.filename = child.Read("filename", true, "", "The input file name.");
156 
157  m_goldStandards.push_back(g);
158  }
159 
160  if(m_goldStandards.empty())
161  throw ParseException(_node.Where()) << "At least one GoldStandard is "
162  << "required.";
163 }
164 
165 /*------------------------------ Interface -----------------------------------*/
166 
167 template <typename MPTraits>
168 void
170 Initialize() {
171  auto problem = this->GetMPProblem();
172 
173  // Validate each gold standard.
174  for(auto& g : m_goldStandards) {
175  // Fetch the robot if needed (throws if not found).
176  switch(g.type) {
177  case GoldStandard::Type::Roadmap:
178  case GoldStandard::Type::BlockRoadmap:
179  case GoldStandard::Type::CfgPath:
180  case GoldStandard::Type::FullCfgPath:
181  g.robot = problem->GetRobot(g.label);
182  break;
183  case GoldStandard::Type::History:
184  break;
185  default:
186  throw RunTimeException(WHERE) << "Unrecognized type.";
187  }
188 
189  // Check that file exists.
190  g.filename = problem->GetPath(g.filename);
191  if(!std::ifstream(g.filename).good())
192  throw ParseException(WHERE) << "Could not open file '"
193  << g.filename << "'.";
194  }
195 }
196 
197 
198 template <typename MPTraits>
199 void
201 Run() {
202  // Get the target, disable outputs, and run.
203  auto target = this->GetMPStrategy(m_targetLabel);
204  target->EnableOutputFiles(false);
205  (*target)();
206 }
207 
208 
209 template <typename MPTraits>
210 void
212 Finalize() {
213  // Verify each gold standard against the output.
214  for(const auto& g : m_goldStandards)
215  ValidateResult(g);
216 }
217 
218 /*-------------------------------- Helpers -----------------------------------*/
219 
220 template <typename MPTraits>
221 void
223 ValidateResult(const GoldStandard& _g) {
224  switch(_g.type) {
225  case GoldStandard::Type::Roadmap:
226  {
227  auto output = this->GetRoadmap(_g.robot);
228  ValidateRoadmap(_g, output);
229  break;
230  }
231  case GoldStandard::Type::BlockRoadmap:
232  {
233  auto output = this->GetBlockRoadmap(_g.robot);
234  ValidateRoadmap(_g, output);
235  break;
236  }
237  case GoldStandard::Type::CfgPath:
238  {
239  const std::vector<CfgType> output = this->GetPath(_g.robot)->Cfgs();
240  ValidatePath(_g, output);
241  break;
242  }
243  case GoldStandard::Type::FullCfgPath:
244  {
245  const std::vector<CfgType> output = this->GetPath(_g.robot)->FullCfgs(
246  this->GetMPLibrary());
247  ValidatePath(_g, output);
248  break;
249  }
250  case GoldStandard::Type::History:
251  {
252  ValidateHistory(_g);
253  break;
254  }
255  default:
256  throw RunTimeException(WHERE) << "Unrecognized type.";
257  }
258 }
259 
260 
261 template <typename MPTraits>
262 void
264 ValidateRoadmap(const GoldStandard& _g, RoadmapType* const _output) {
265  if(this->m_debug)
266  std::cout << "Validating "
267  << (_g.type == GoldStandard::Type::BlockRoadmap ? "blocked " : "")
268  << "roadmap file '" << _g.filename << "'"
269  << " for robot '" << _g.label << "'"
270  << std::endl;
271 
272  // Get the input roadmap.
273  RoadmapType input(_g.robot);
274  ::Read(&input, _g.filename);
275 
276  // Compare.
277  const bool ok = *_output == input;
278 
279  // Quit on pass.
280  if(this->m_debug)
281  std::cout << "\t" << (ok ? "Passed" : "Failed") << std::endl;
282  if(ok)
283  return;
284 
285  // Maps are not equal, write the output for inspection.
286  const std::string base = this->GetBaseFilename();
287 
288  if(_g.type == GoldStandard::Type::Roadmap)
289  _output->Write(base + ".map", this->GetEnvironment());
290  else
291  _output->Write(base + ".block.map", this->GetEnvironment());
292 }
293 
294 
295 template <typename MPTraits>
296 void
298 ValidatePath(const GoldStandard& _g, const std::vector<CfgType>& _output) {
299  if(this->m_debug)
300  std::cout << "Validating "
301  << (_g.type == GoldStandard::Type::FullCfgPath ? "full " : "")
302  << "cfg path file '" << _g.filename << "'"
303  << " for robot '" << _g.label << "'"
304  << std::endl;
305 
306  // Get the input path.
307  const std::vector<CfgType> input = ReadPath<CfgType>(_g.filename, _g.robot);
308 
309  // Compare.
310  const bool ok = _output == input;
311 
312  // Quit on pass.
313  if(this->m_debug)
314  std::cout << "\t" << (ok ? "Passed" : "Failed") << std::endl;
315  if(ok)
316  return;
317 
318  // Paths are not equal, write the output for inspection.
319  const std::string base = this->GetBaseFilename();
320  if(_g.type == GoldStandard::Type::CfgPath)
321  ::WritePath(base + ".rdmp.path", _output);
322  else
323  ::WritePath(base + ".path", _output);
324 }
325 
326 
327 template <typename MPTraits>
328 void
330 ValidateHistory(const GoldStandard& _g) {
331  if(this->m_debug)
332  std::cout << "Validating history file '" << _g.filename << "' for history "
333  << "stat '" << _g.label << "'"
334  << std::endl;
335 
336  // Get the output.
337  auto stats = this->GetStatClass();
338  const std::vector<double> output = stats->GetHistory(_g.label);
339 
340  // Read the input file.
341  double buffer;
342  std::vector<double> input;
343  input.reserve(output.size());
344  std::ifstream ifs(_g.filename);
345  while(ifs >> buffer)
346  input.push_back(buffer);
347 
348  // Compare.
349  constexpr double tolerance = std::numeric_limits<double>::epsilon() * 100;
350  bool ok = output.size() == input.size();
351  for(size_t i = 0; ok and i < output.size(); ++i)
352  ok &= nonstd::approx(output[i], input[i], tolerance);
353 
354  // Quit on pass.
355  if(this->m_debug)
356  std::cout << "\t" << (ok ? "Passed" : "Failed") << std::endl;
357  if(ok)
358  return;
359 
360  // Write history.
361  stats->WriteHistory(_g.label);
362 }
363 
364 /*----------------------------------------------------------------------------*/
365 
366 #endif
void Read(GenericStateGraph *_g, const std::string &_filename)
Definition: GenericStateGraph.h:1337
void WritePath(const std::string &_filename, const std::vector< CfgType > &_path)
Write a list of Cfgs from a path to file.
Definition: IOUtils.h:145
#define WHERE
Macro for retrieving info about file, function, and line number.
Definition: RuntimeUtils.h:32
Definition: MPStrategyMethod.h:33
Definition: Robot.h:31
Definition: ValidationStrategy.h:14
MPTraits::CfgType CfgType
Definition: ValidationStrategy.h:21
MPTraits::WeightType WeightType
Definition: ValidationStrategy.h:22
virtual void Finalize() override
Clean-up and output results.
Definition: ValidationStrategy.h:212
RoadmapType::VID VID
Definition: ValidationStrategy.h:24
virtual void Initialize() override
Definition: ValidationStrategy.h:170
virtual ~ValidationStrategy()=default
MPTraits::RoadmapType RoadmapType
Definition: ValidationStrategy.h:23
ValidationStrategy()
Definition: ValidationStrategy.h:100
virtual void Run() override
Call Iterate until EvaluateMap is true.
Definition: ValidationStrategy.h:201
Definition: XMLNode.h:27
std::string Where() const
Definition: XMLNode.cpp:243
T Read(const std::string &_name, const bool _req, const T &_default, const T &_min, const T &_max, const std::string &_desc)
Definition: XMLNode.h:274
Defines available methods in the Motion Planning Universe for Cfg under parallel compile.
Definition: ParallelCfgTraits.h:144
C CfgType
Definition: ParallelCfgTraits.h:145
W WeightType
Definition: ParallelCfgTraits.h:146
Definition: PMPLExceptions.h:38
Definition: PMPLExceptions.h:62
A gold standard input to validate against the target strategy.
Definition: ValidationStrategy.h:31
Type type
The type of output to check.
Definition: ValidationStrategy.h:40
Type
The types of gold standard files we can read.
Definition: ValidationStrategy.h:34
std::string filename
The input filename.
Definition: ValidationStrategy.h:43
Robot * robot
The robot represented in the output.
Definition: ValidationStrategy.h:42
std::string label
Label for the generated object.
Definition: ValidationStrategy.h:41