Choreonoid  1.8
GeneralSeqReader.h
Go to the documentation of this file.
1 
6 #ifndef CNOID_UTIL_GENERAL_SEQ_READER_H
7 #define CNOID_UTIL_GENERAL_SEQ_READER_H
8 
9 #include "ValueTree.h"
10 #include "AbstractSeq.h"
11 #include <functional>
12 #include <type_traits>
13 #include <ostream>
14 
15 namespace cnoid {
16 
18 {
19  static std::string mismatched_seq_type_message(const std::string& type, AbstractSeq* seq);
20  static std::string has_frame_time_unsupported_message(double formatVersion);
21  static std::string unkown_frame_rate_for_time_frame_seq_message();
22  static std::string frames_key_not_found_message();
23  static std::string no_frame_data_message();
24  static std::string invalid_num_parts_messaage();
25  static std::string invalid_frame_size_message();
26 
27  std::ostream& os_;
28  const Mapping* archive_;
29  AbstractSeq* seq_;
30  double formatVersion_;
31  bool hasFrameTime_;
32  int numParts_;
33 
34  std::function<bool(GeneralSeqReader& reader, const std::string& type)> customSeqTypeChecker;
35 
36 public:
37  GeneralSeqReader(std::ostream& os)
38  : os_(os)
39  {
40  archive_ = nullptr;
41  seq_ = nullptr;
42  formatVersion_ = 2.0;
43  hasFrameTime_ = false;
44  numParts_ = 0;
45  }
46 
47  std::ostream& os() { return os_; }
48  const Mapping* archive() { return archive_; }
49  AbstractSeq* seq() { return seq_; }
50  double formatVersion() const { return formatVersion_; }
51  bool hasFrameTime() const { return hasFrameTime_; }
52  int numParts() const { return numParts_; }
53 
54  bool checkSeqType(const std::string& type) const {
55  return (type == seq_->seqType());
56  };
57 
58  void setCustomSeqTypeChecker(std::function<bool(GeneralSeqReader& reader, const std::string& type)> func){
59  customSeqTypeChecker = func;
60  }
61 
62 private:
63  const Listing& getFrames(const Mapping* archive)
64  {
65  auto framesNode = archive->find("frames");
66  if(!framesNode->isValid()){
67  archive->throwException(frames_key_not_found_message());
68  }
69  const Listing& frames = *framesNode->toListing();
70  if(frames.empty()){
71  frames.throwException(no_frame_data_message());
72  }
73  return frames;
74  }
75 
76 public:
78  {
79  archive_ = archive;
80  seq_ = seq;
81 
82  formatVersion_ = archive->get("formatVersion", 1.0);
83 
84  auto& typeNode = (*archive)["type"];
85  auto type = typeNode.toString();
86  bool isTypeMatched;
87  if(customSeqTypeChecker){
88  isTypeMatched = customSeqTypeChecker(*this, type);
89  } else {
90  isTypeMatched = checkSeqType(type);
91  }
92  if(!isTypeMatched){
93  typeNode.throwException(mismatched_seq_type_message(type, seq));
94  }
95 
96  std::string content;
97  if(archive->read("content", content)){
98  seq->setSeqContentName(content);
99  } else if(formatVersion_ < 2.0 && archive->read("purpose", content)){
100  seq->setSeqContentName(content);
101  }
102 
103  hasFrameTime_ = false;
104  auto node_hasFrameTime = archive->find("hasFrameTime");
105  if(node_hasFrameTime->isValid()){
106  if(formatVersion_ < 2.0){
107  node_hasFrameTime->throwException(has_frame_time_unsupported_message(formatVersion_));
108  }
109  hasFrameTime_ = node_hasFrameTime->toBool();
110  }
111 
112  if(!hasFrameTime_){
113  seq->setFrameRate(archive->read<double>("frameRate"));
114  } else {
115  if(seq->getFrameRate() <= 0){
116  double r;
117  if(archive->read("frameRate", r)){
118  seq->setFrameRate(r);
119  } else {
120  os_ << unkown_frame_rate_for_time_frame_seq_message() << std::endl;
121  return false;
122  }
123  }
124  }
125 
126  if(dynamic_cast<AbstractMultiSeq*>(seq)){
127  auto& node = (*archive)["numParts"];
128  numParts_ = node.toInt();
129  if(numParts_ < 1){
130  node.throwException(invalid_num_parts_messaage());
131  }
132  }
133 
134  return true;
135  }
136 
137  template<
138  class SeqType,
139  typename std::enable_if<
140  std::is_base_of<AbstractSeq, SeqType>::value &&
141  !std::is_base_of<AbstractMultiSeq, SeqType>::value, std::nullptr_t>::type = nullptr
142  >
143  bool read(
144  const Mapping* archive, SeqType* seq,
145  std::function<void(const Listing& srcNode, int topIndex, typename SeqType::value_type& seqValue)> readValue)
146  {
147  return readHeaders(archive, seq) && readFrames(archive, seq, readValue);
148  }
149 
150  template<
151  class SeqType,
152  typename std::enable_if<
153  std::is_base_of<AbstractSeq, SeqType>::value &&
154  !std::is_base_of<AbstractMultiSeq, SeqType>::value, std::nullptr_t>::type = nullptr
155  >
157  const Mapping* archive, SeqType* seq,
158  std::function<void(const Listing& srcNode, int topIndex, typename SeqType::value_type& seqValue)> readValue)
159  {
160  const Listing& frames = getFrames(archive);
161  const int numFrames = frames.size();
162  seq->setNumFrames(hasFrameTime_ ? 0 : numFrames);
163 
164  for(int i=0; i < numFrames; ++i){
165  const Listing& srcValue = *frames[i].toListing();
166  if(!hasFrameTime_){
167  auto& seqValue = (*seq)[i];
168  readValue(srcValue, 0, seqValue);
169  } else {
170  double time = srcValue[0].toDouble();
171  int frameIndex = seq->frameOfTime(time);
172  if(frameIndex >= seq->numFrames()){
173  seq->setNumFrames(frameIndex + 1, true);
174  }
175  auto& seqValue = (*seq)[frameIndex];
176  readValue(srcValue, 1, seqValue);
177  }
178  }
179 
180  return true;
181  }
182 
183  template<
184  class SeqType,
185  typename std::enable_if<std::is_base_of<AbstractMultiSeq, SeqType>::value, std::nullptr_t>::type = nullptr
186  >
187  bool read(
188  const Mapping* archive, SeqType* seq,
189  std::function<void(const ValueNode& srcNode, typename SeqType::value_type& seqValue)> readValue)
190  {
191  return readHeaders(archive, seq) && readFrames(archive, seq, readValue);
192  }
193 
194  template<
195  class SeqType,
196  typename std::enable_if<std::is_base_of<AbstractMultiSeq, SeqType>::value, std::nullptr_t>::type = nullptr
197  >
199  const Mapping* archive, SeqType* seq,
200  std::function<void(const ValueNode& srcNode, typename SeqType::value_type& seqValue)> readValue)
201  {
202  int frameDataSize = numParts_;
203  if(hasFrameTime_){
204  frameDataSize += 1;
205  }
206 
207  const Listing& frames = getFrames(archive);
208  const int numFrames = frames.size();
209 
210  if(hasFrameTime_){
211  seq->setDimension(0, numParts_);
212  } else {
213  seq->setDimension(numFrames, numParts_);
214  }
215 
216  for(int i=0; i < numFrames; ++i){
217  const Listing& srcValues = *frames[i].toListing();
218  if(srcValues.size() != frameDataSize){
219  srcValues.throwException(invalid_frame_size_message());
220  }
221  if(!hasFrameTime_){
222  auto seqFrame = seq->frame(i);
223  for(int j=0; j < numParts_; ++j){
224  readValue(srcValues[j], seqFrame[j]);
225  }
226  } else {
227  double time = srcValues[0].toDouble();
228  int frameIndex = seq->frameOfTime(time);
229  if(frameIndex >= seq->numFrames()){
230  seq->setNumFrames(frameIndex + 1, true);
231  }
232  auto seqFrame = seq->frame(frameIndex);
233  for(int j=0; j < numParts_; ++j){
234  readValue(srcValues[j+1], seqFrame[j]);
235  }
236  }
237  }
238 
239  return true;
240  }
241 };
242 
243 }
244 
245 #endif
cnoid::GeneralSeqReader::GeneralSeqReader
GeneralSeqReader(std::ostream &os)
Definition: GeneralSeqReader.h:37
cnoid::Mapping::read
bool read(const std::string &key, std::string &out_value) const
Definition: ValueTree.cpp:809
cnoid::GeneralSeqReader::setCustomSeqTypeChecker
void setCustomSeqTypeChecker(std::function< bool(GeneralSeqReader &reader, const std::string &type)> func)
Definition: GeneralSeqReader.h:58
cnoid::AbstractSeq::seqType
const std::string & seqType() const
Definition: AbstractSeq.h:36
cnoid::Mapping
Definition: ValueTree.h:253
cnoid::Mapping::get
ValueNode & get(const std::string &key) const
Definition: ValueTree.cpp:666
cnoid::AbstractSeq::setNumFrames
virtual void setNumFrames(int n, bool clearNewElements=false)=0
cnoid::GeneralSeqReader::read
bool read(const Mapping *archive, SeqType *seq, std::function< void(const Listing &srcNode, int topIndex, typename SeqType::value_type &seqValue)> readValue)
Definition: GeneralSeqReader.h:143
cnoid::ValueNode::toString
const std::string & toString() const
Definition: ValueTree.h:244
cnoid::ValueNode::throwException
void throwException(const std::string &message) const
Definition: ValueTree.cpp:405
cnoid::GeneralSeqReader::readHeaders
bool readHeaders(const Mapping *archive, AbstractSeq *seq)
Definition: GeneralSeqReader.h:77
cnoid::AbstractSeq::getFrameRate
virtual double getFrameRate() const =0
cnoid::GeneralSeqReader::readFrames
bool readFrames(const Mapping *archive, SeqType *seq, std::function< void(const Listing &srcNode, int topIndex, typename SeqType::value_type &seqValue)> readValue)
Definition: GeneralSeqReader.h:156
cnoid::ValueNode
Definition: ValueTree.h:34
cnoid::AbstractMultiSeq
Definition: AbstractSeq.h:99
cnoid::GeneralSeqReader::seq
AbstractSeq * seq()
Definition: GeneralSeqReader.h:49
cnoid::GeneralSeqReader::archive
const Mapping * archive()
Definition: GeneralSeqReader.h:48
AbstractSeq.h
cnoid::GeneralSeqReader::os
std::ostream & os()
Definition: GeneralSeqReader.h:47
cnoid::GeneralSeqReader::hasFrameTime
bool hasFrameTime() const
Definition: GeneralSeqReader.h:51
ValueTree.h
cnoid::ValueNode::toListing
const Listing * toListing() const
Definition: ValueTree.cpp:387
cnoid::GeneralSeqReader::readFrames
bool readFrames(const Mapping *archive, SeqType *seq, std::function< void(const ValueNode &srcNode, typename SeqType::value_type &seqValue)> readValue)
Definition: GeneralSeqReader.h:198
cnoid::GeneralSeqReader::checkSeqType
bool checkSeqType(const std::string &type) const
Definition: GeneralSeqReader.h:54
cnoid::GeneralSeqReader::formatVersion
double formatVersion() const
Definition: GeneralSeqReader.h:50
cnoid::Listing::size
int size() const
Definition: ValueTree.h:502
cnoid::GeneralSeqReader::numParts
int numParts() const
Definition: GeneralSeqReader.h:52
cnoid::Listing
Definition: ValueTree.h:486
cnoid
Definition: AbstractSceneLoader.h:11
cnoid::GeneralSeqReader
Definition: GeneralSeqReader.h:17
cnoid::Mapping::find
ValueNode * find(const std::string &key) const
Definition: ValueTree.cpp:515
cnoid::ValueNode::toDouble
double toDouble() const
Definition: ValueTree.cpp:217
cnoid::AbstractSeq
Definition: AbstractSeq.h:21
cnoid::AbstractSeq::setSeqContentName
virtual void setSeqContentName(const std::string &name)
Definition: AbstractSeq.cpp:66
cnoid::AbstractSeq::setFrameRate
virtual void setFrameRate(double frameRate)=0
cnoid::GeneralSeqReader::read
bool read(const Mapping *archive, SeqType *seq, std::function< void(const ValueNode &srcNode, typename SeqType::value_type &seqValue)> readValue)
Definition: GeneralSeqReader.h:187