ed
model_loader.cpp
Go to the documentation of this file.
2 
3 #include "ed/types.h"
4 
5 #include "ed/update_request.h"
6 #include "ed/entity.h"
8 
9 #include <tue/filesystem/path.h>
10 
11 #include "shape_loader_private.h"
12 
13 #include <tue/config/reader.h>
14 #include <tue/config/writer.h>
16 
17 #include <geolib/CompositeShape.h>
18 
19 #include <sdf/parser.hh>
20 
21 #include <sstream>
22 
23 namespace ed
24 {
25 
26 namespace models
27 {
28 
30 {
32  readPose(r, pose);
33  pose = pose_offset * pose;
34  if (!r.readGroup("geometry"))
35  return false;
36 
37  std::map<std::string, geo::ShapePtr> dummy_shape_cache;
38  geo::ShapePtr sub_shape = loadShape("", r, dummy_shape_cache, error);
39  if (sub_shape)
40  {
41  if (!composite) // if pointer is empty, create new instance.
42  composite.reset(new geo::CompositeShape);
43  composite->addShape(*sub_shape, pose);
44  }
45  r.endGroup();
46  return true;
47 }
48 
49 // ----------------------------------------------------------------------------------------------------
50 
52 {
53  const char * edmpath = ::getenv("ED_MODEL_PATH");
54  if (edmpath)
55  {
56  std::vector<std::string> paths_vector = ed::models::split(edmpath, ':');
57  for (std::vector<std::string>::const_iterator it = paths_vector.begin(); it != paths_vector.end(); ++it)
59  }
60  const char * mpath = ::getenv("GAZEBO_MODEL_PATH");
61  if (mpath)
62  {
63  std::vector<std::string> paths_vector = ed::models::split(mpath, ':');
64  for (std::vector<std::string>::const_iterator it = paths_vector.begin(); it != paths_vector.end(); ++it)
66  }
67  const char * fpath = ::getenv("GAZEBO_RESOURCE_PATH");
68  if (fpath)
69  {
70  std::vector<std::string> paths_vector = ed::models::split(fpath, ':');
71  for (std::vector<std::string>::const_iterator it = paths_vector.begin(); it != paths_vector.end(); ++it)
73  }
74 }
75 
76 // ----------------------------------------------------------------------------------------------------
77 
79 {
80 }
81 
82 // ----------------------------------------------------------------------------------------------------
83 
91 {
93  {
94  tue::filesystem::Path model_path(*it + "/" + type);
95  if (model_path.exists())
96  return model_path.string();
97  }
98 
99  return "";
100 }
101 
102 // ----------------------------------------------------------------------------------------------------
103 
105 {
106  ModelOrFile uri_type;
107  std::string parsed_uri = parseURI(uri, uri_type);
108  if (parsed_uri.empty())
109  return "";
110 
111  if (uri_type == MODEL)
112  {
114  {
115  tue::filesystem::Path model_dir(*it + "/" + parsed_uri);
116  if (model_dir.exists())
117  {
118  tue::filesystem::Path config_path(model_dir.string() + "/model.config");
119  if (config_path.exists())
120  {
121  tue::filesystem::Path model_path = sdf::getModelFilePath(model_dir.string());
122  if (model_path.exists())
123  return model_path.string();
124  }
125  }
126  }
127  }
128  if (uri_type == FILE)
129  {
131  {
132  tue::filesystem::Path file_path(*it + "/" + parsed_uri);
133  if (file_path.exists())
134  return file_path.string();
135  }
136  }
137 
138  return "";
139 }
140 
141 // ----------------------------------------------------------------------------------------------------
142 
144 {
146  if (it != model_cache_.end())
147  return it->second;
148 
151  return ModelData(data, types);
152 }
153 
154 // ----------------------------------------------------------------------------------------------------
155 
157  std::stringstream& error, const bool allow_sdf)
158 {
159  if (allow_sdf)
160  {
162  data_sdf = loadSDFData("model://" + type, error);
163  if (!data_sdf.empty())
164  return data_sdf;
165  }
166  ModelData cache_data = readModelCache(type);
167  if (!cache_data.first.empty())
168  {
169  types = cache_data.second;
170  return cache_data.first;
171  }
172 
174 
175  std::string model_path = getModelPath(type);
176  if (model_path.empty())
177  {
178  error << "[ed::models::loadModelData] Model '" << type << "' could not be found." << std::endl;
179  return data;
180  }
181 
182  tue::filesystem::Path model_cfg_path(model_path + "/model.yaml");
183  if (!model_cfg_path.exists())
184  {
185  error << "[ed::models::loadModelData] ERROR loading configuration for model '" << type << "'; '" << model_cfg_path.string() << "' file does not exist." << std::endl;
186  return data;
187  }
188 
189  tue::Configuration model_cfg;
190  if (!model_cfg.loadFromYAMLFile(model_cfg_path.string()))
191  {
192  error << "[ed::models::loadModelData] ERROR loading configuration for model '" << type << "'; '" << model_cfg_path.string() << "' failed to parse yaml file." << std::endl;
193  return data;
194  }
195 
196  std::string super_type;
197  if (model_cfg.value("type", super_type, tue::config::OPTIONAL))
198  {
199  tue::config::DataConstPointer super_data = loadModelData(super_type, types, error);
200  tue::config::DataPointer combined_data;
201  combined_data.add(super_data);
202  combined_data.add(model_cfg.data());
203 
204  types.push_back(super_type);
205 
206  data = combined_data;
207  }
208  else
209  {
210  data = model_cfg.data();
211  }
212 
213  // If model loads a shape, set model path in shape data
214  tue::config::ReaderWriter rw(data);
215  rw.setValue("__model_path__", model_path);
216 
217  // Store data in cache
218  model_cache_[type] = ModelData(data, types);
219 
220  return data;
221 }
222 
223 // ----------------------------------------------------------------------------------------------------
224 
226 {
228  ModelOrFile uri_type;
229  std::string parsed_uri = parseURI(uri, uri_type);
230  if (parsed_uri.empty())
231  {
232  error << "[ed::models::loadSDFData] Incorrect URI: '" << uri << "'." << std::endl;
233  return data;
234  }
235  ModelData cache_data = readModelCache(parsed_uri + "_sdf");
236  if (!cache_data.first.empty())
237  {
238  return cache_data.first;
239  }
240 
241  tue::filesystem::Path model_cfg_path = getSDFPath(uri);
242  if (!model_cfg_path.exists())
243  {
244  error << "[ed::models::loadSDFData] Model '" << uri << "' could not be found." << std::endl;
245  return data;
246  }
247 
248  tue::Configuration model_cfg(data);
249  if (!model_cfg.loadFromSDFFile(model_cfg_path.string()))
250  {
251  error << "[ed::models::loadSDFData] ERROR loading configuration for model '" << uri << "'; '" << model_cfg_path << "' failed to parse SDF file." << std::endl;
252  error << model_cfg.error() << std::endl;
253  return data;
254  }
255 
256  // Store data in cache
257  model_cache_[parsed_uri+"_sdf"] = ModelData(data, std::vector<std::string>());
258 
259  return data;
260 }
261 
262 // ----------------------------------------------------------------------------------------------------
263 
264 bool ModelLoader::exists(const std::string& type) const
265 {
266  ModelData cache_data = readModelCache(type + "_sdf");
267  if(!cache_data.first.empty())
268  return true;
269 
270  cache_data = readModelCache(type);
271  if(!cache_data.first.empty())
272  return true;
273 
274 
275  std::string sdf_path = getSDFPath(type);
276  if (!sdf_path.empty())
277  return true;
278 
279  std::string model_path = getModelPath(type);
280  return !model_path.empty();
281 }
282 
283 // ----------------------------------------------------------------------------------------------------
284 
286  const bool allow_sdf)
287 {
290  bool sdf = true;
291  if (allow_sdf)
292  data = loadSDFData("model://" + type, error);
293  if(data.empty())
294  {
295  sdf = false;
296  data = loadModelData(type, types, error);
297  if (data.empty())
298  return false;
299  }
300 
301  // First try to get data before trying to create models.
302  if (sdf)
303  {
304  if (!createSDF(data, "", geo::Pose3D::identity(), id, boost::shared_ptr<const geo::Pose3D>(), req, error))
305  return false;
306  }
307  else
308  {
309  if (!create(data, id, "", req, error))
310  return false;
311  }
312 
313  types.push_back(type);
314  for(std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it)
315  req.addType(id, *it);
316 
317  return true;
318 }
319 
320 // ----------------------------------------------------------------------------------------------------
321 
323 {
324  return create(data, "_root", "", req, error, "");
325 }
326 
327 // ----------------------------------------------------------------------------------------------------
328 
329 bool ModelLoader::create(const tue::config::DataConstPointer& data, const UUID& id_opt, const UUID& parent_id,
330  UpdateRequest& req, std::stringstream& error, const std::string& model_path,
331  const geo::Pose3D& pose_offset)
332 {
333  tue::config::Reader r(data);
334 
335  if (r.hasGroup("sdf"))
336  return createSDF(r.data(), parent_id, pose_offset, id_opt, boost::shared_ptr<const geo::Pose3D>(), req, error);
337 
338 
339  // Get Id
340  UUID id;
341  std::string id_str;
342  if (r.value("id", id_str, tue::config::OPTIONAL))
343  {
344  if (parent_id.str().empty() || parent_id.str()[0] == '_')
345  id = id_str;
346  else
347  id = parent_id.str() + "/" + id_str;
348  }
349  else if (!id_opt.str().empty())
350  {
351  id = id_opt;
352  }
353  else
354  {
355  id = ed::Entity::generateID();
356  }
357 
358  // Get type. If it exists, first construct an entity based on the given type.
359  std::string type;
360  if (r.value("type", type, tue::config::OPTIONAL))
361  {
363  tue::config::DataConstPointer super_data = loadModelData(type, types, error);
364 
365  if (super_data.empty())
366  return false;
367 
368  tue::config::DataPointer data_combined;
369  data_combined.add(super_data);
370  data_combined.add(data);
371 
372  r = tue::config::Reader(data_combined);
373 
374  types.push_back(type);
375  for(std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it)
376  req.addType(id, *it);
377  }
378 
379  // Set type
380  req.setType(id, type);
381 
382  // Get pose
384  if (!ed::models::readPose(r, pose))
385  error << "[ed::models::create] No pose, while reading model: '" << id << "'" << std::endl;
386 
387  pose = pose_offset * pose;
388 
389  req.setPose(id, pose);
390 
391  // Check the composition
392  if (r.readArray("composition"))
393  {
394  while (r.nextArrayItem())
395  {
396  if (!create(r.data(), "", id, req, error, "", pose))
397  return false;
398  }
399 
400  r.endArray();
401  }
402 
403 
404  std::string shape_model_path = model_path;
405  r.value("__model_path__", shape_model_path);
406  // Set shape
407  if (r.readGroup("shape"))
408  {
409  geo::ShapePtr shape = loadShape(shape_model_path, r, shape_cache_, error);
410  if (shape)
411  {
412  req.setVisual(id, shape);
413  req.setCollision(id, shape);
414  }
415  else
416  return false;
417 
418  r.endGroup();
419  }
420 
421  // Set volumes
422  if (r.readArray("areas") || r.readArray("volumes"))
423  {
424  while (r.nextArrayItem())
425  {
426  std::string volume_name;
427  if (!(r.value("name", volume_name) && r.readArray("shape")))
428  continue;
429 
431  while (r.nextArrayItem())
432  {
433  geo::ShapePtr sub_shape = loadShape(shape_model_path, r, shape_cache_, error);
434  if (sub_shape)
435  {
436  if(!shape)
437  shape.reset(new geo::CompositeShape);
438  shape->addShape(*sub_shape, geo::Pose3D::identity());
439  }
440  }
441  r.endArray();
442 
443  if (shape)
444  req.addVolume(id, volume_name, shape);
445  }
446  r.endArray();
447  }
448 
449  if (r.readArray("flags"))
450  {
451  while (r.nextArrayItem())
452  {
453  std::string flag;
454  if (r.value("flag", flag))
455  req.setFlag(id, flag);
456  }
457  r.endArray();
458  }
459 
460  // Add additional data
461  req.addData(id, r.data());
462 
463  return true;
464 }
465 
466 bool ModelLoader::createSDF(const tue::config::DataConstPointer& data, const UUID& parent_id, const geo::Pose3D& parent_pose, const UUID& id_override,
467  const boost::shared_ptr<const geo::Pose3D> pose_override, UpdateRequest& req, std::stringstream& error)
468 {
469  tue::config::Reader r(data);
470 
471  r.readGroup("sdf"); // Just read the sdf element
472 
473  bool sdf_world = r.readGroup("world");
474  bool sdf_model = false;
475  if (!sdf_world)
476  {
477  sdf_model = r.readArray("model");
478  r.nextArrayItem();
479  }
480 
481  if (!sdf_world && !sdf_model)
482  {
483  error << "[ed::models::createSDF] Not a valid SDF model, because no 'world' or 'model' available: " << std::endl << data << std::endl;
484  return false;
485  }
486 
487  if (r.nextArrayItem())
488  {
489  error << "[ed::models::createSDF] A model sdf file should only contain one model." << std::endl;
490  return false;
491  }
492 
493  //ID
494  UUID id;
495  std::string id_str;
496  if (!id_override.str().empty())
497  id = id_override.str();
498  else if (r.value("name", id_str) && !id_str.empty())
499  id = id_str;
500  else
501  id = ed::Entity::generateID();
502 
503  // prefix with parent_id
504  if (!parent_id.str().empty() && parent_id.str()[0] != '_')
505  id = parent_id.str() + "/" + id.str();
506 
507  // pose
509  readPose(r, pose);
510  if (pose_override)
511  pose = *pose_override;
512  pose = parent_pose * pose;
513  req.setPose(id, pose);
514 
515  // set type if defined, no recursive type is done.
516  std::string type;
517  if (r.value("type", type))
518  req.setType(id, type);
519 
520  // composed models
521  if (r.readArray("model"))
522  {
523  while (r.nextArrayItem())
524  {
526  rw.writeArray("model");
527  rw.addArrayItem();
528  rw.data().add(r.data());
529  rw.endArray();
530  if (!createSDF(rw.data(), id, pose, "", boost::shared_ptr<const geo::Pose3D>(), req, error))
531  return false;
532  }
533  r.endArray(); // end array model
534  }
535  if (r.readArray("include"))
536  {
537  while (r.nextArrayItem())
538  {
539  std::string child_id;
540  geo::Pose3D child_pose;
541  std::string uri;
542  ed::shared_ptr<const geo::Pose3D> child_posePtr;
543 
544  r.value("name", child_id);
545  if (readPose(r, child_pose))
546  child_posePtr = ed::make_shared<const geo::Pose3D>(child_pose);
547  if (!r.value("uri", uri))
548  {
549  error << "No uri found for include in model: '" << id << "'." << std::endl << r.data() << std::endl;
550  return false;
551  }
552 
555  if (!createSDF(child_data, id, pose, child_id, child_posePtr, req, error))
556  return false;
557  }
558  r.endArray(); // end array include
559  }
560 
561 
562  // visual, collision & volumes
563  geo::CompositeShapePtr visual_composite, collision_composite;
564  std::map<std::string, geo::ShapePtr> dummy_shape_cache;
565  if (r.readArray("link"))
566  {
567  while (r.nextArrayItem())
568  {
569  geo::Pose3D link_pose = geo::Pose3D::identity();
570  readPose(r, link_pose);
571  if (r.readArray("visual"))
572  {
573  while(r.nextArrayItem())
574  {
575  readSDFGeometry(r, visual_composite, error, link_pose);
576  }
577  r.endArray();
578  }
579  if (r.readArray("collision"))
580  {
581  while(r.nextArrayItem())
582  {
583  readSDFGeometry(r, collision_composite, error, link_pose);
584  }
585  r.endArray();
586  }
587  geo::CompositeShapePtr volume_composite;
588  std::string volume_name;
589  if (r.value("name", volume_name))
590  {
591  if (r.readArray("virtual_volume"))
592  {
593  while(r.nextArrayItem())
594  {
595  readSDFGeometry(r, volume_composite, error, link_pose);
596  }
597  r.endArray();
598  }
599  if (volume_composite)
600  req.addVolume(id, volume_name, volume_composite);
601  }
602  }
603  r.endArray(); // end array link
604  }
605  if (visual_composite)
606  req.setVisual(id, visual_composite);
607  if (collision_composite)
608  req.setCollision(id, collision_composite);
609 
610  if(sdf_world)
611  r.endGroup(); // end group world
612  else // sdf_model
613  r.endArray(); // end array model
614 
615  return true;
616 }
617 
618 } // end namespace models
619 
620 } // end namespace ed
621 
ed::models::parseURI
std::string parseURI(const std::string &uri, ModelOrFile &uri_type)
Definition: shape_loader.cpp:48
sstream
ed::models::ModelLoader::loadModelData
tue::config::DataConstPointer loadModelData(std::string type, std::vector< std::string > &types, std::stringstream &error, const bool allow_sdf=false)
loadModelData load data of model of type 'type'
Definition: model_loader.cpp:156
ed::UpdateRequest
Definition: update_request.h:24
tue::config::ReaderWriter::loadFromSDFFile
bool loadFromSDFFile(const std::string &filename)
std::string
tue::config::Reader::nextArrayItem
bool nextArrayItem()
std::shared_ptr
ed::UpdateRequest::addData
void addData(const UUID &id, const tue::config::DataConstPointer &data)
Definition: update_request.h:148
ed::models::ModelLoader::createSDF
bool createSDF(const tue::config::DataConstPointer &data, const UUID &parent_id, const geo::Pose3D &parent_pose, const UUID &id_override, const boost::shared_ptr< const geo::Pose3D > pose_override, UpdateRequest &req, std::stringstream &error)
createSDF add SDF entity to update_request from config data.
Definition: model_loader.cpp:466
types.h
ed::UpdateRequest::addType
void addType(const UUID &id, const std::string &type)
Definition: update_request.h:109
entity.h
std::pair
tue::config::Reader::value
bool value(const std::string &name, T &value, const RequiredOrOptional=REQUIRED) const
ed::models::ModelLoader::model_paths_
std::vector< std::string > model_paths_
Definition: model_loader.h:97
tue::filesystem::Path
geo::Transform3T::identity
static Transform3T identity()
std::vector< std::string >
tue::config::DataPointer
tue::config::Reader::hasGroup
bool hasGroup(const std::string &name)
std::stringstream
reader.h
tue::config::ReaderWriter::writeArray
bool writeArray(const std::string &name)
tue::filesystem::Path::exists
bool exists() const
ed::models::ModelLoader::readModelCache
ModelData readModelCache(std::string type) const
readModelCache read the model cache, which contains the data and all types
Definition: model_loader.cpp:143
geo::Transform3T
tue::config::ReaderWriter::loadFromYAMLFile
bool loadFromYAMLFile(const std::string &filename, const ResolveConfig &resolve_config=ResolveConfig::defaultConfig())
ed::models::ModelLoader::loadSDFData
tue::config::DataConstPointer loadSDFData(std::string uri, std::stringstream &error)
loadSDFData load data of SDF model of uri 'uri'
Definition: model_loader.cpp:225
std::shared_ptr::reset
T reset(T... args)
tue::config::ReaderWriter::addArrayItem
bool addArrayItem()
std::vector::push_back
T push_back(T... args)
tue::config::ReaderWriter
tue::config::Reader::readGroup
bool readGroup(const std::string &name, const RequiredOrOptional opt=OPTIONAL)
ed::models::ModelOrFile
ModelOrFile
The ModelOrFile enum This is used to determine the URI type in SDF.
Definition: shape_loader_private.h:25
ed::models::ModelLoader::create
bool create(const UUID &id, const std::string &type, UpdateRequest &req, std::stringstream &error, const bool allow_sdf=false)
create add entity to update_request with id 'id' of the type 'type'. If allow_sdf is true,...
Definition: model_loader.cpp:285
update_request.h
tue::config::ReaderWriter::data
DataPointer data() const
ed::UpdateRequest::setFlag
void setFlag(const UUID &id, const std::string &flag)
Definition: update_request.h:201
ed::log::error
std::ostream & error()
Definition: logging.cpp:74
ed::models::ModelLoader::model_cache_
std::map< std::string, ModelData > model_cache_
Definition: model_loader.h:90
tue::config::Reader::data
DataConstPointer data() const
ed::models::ModelLoader::shape_cache_
std::map< std::string, geo::ShapePtr > shape_cache_
Definition: model_loader.h:93
tue::config::Reader
ed::models::loadShape
geo::ShapePtr loadShape(const std::string &model_path, tue::config::Reader cfg, std::map< std::string, geo::ShapePtr > &shape_cache, std::stringstream &error)
loadShape load the shape of a model.
Definition: shape_loader.cpp:621
ed::models::split
std::vector< std::string > split(const std::string &strToSplit, char delimeter)
split Implementation by using delimiter as a character. Multiple delimeters are removed.
Definition: shape_loader.cpp:33
tue::config::ReaderWriter::error
const std::string & error() const
tue::config::DataConstPointer::empty
bool empty() const
ed::UpdateRequest::setPose
void setPose(const UUID &id, const geo::Pose3D &pose)
Definition: update_request.h:132
tue::config::Reader::endGroup
bool endGroup()
shape_loader_private.h
ed::UpdateRequest::setCollision
void setCollision(const UUID &id, const geo::ShapeConstPtr &collision)
Definition: update_request.h:57
tue::config::OPTIONAL
OPTIONAL
ed::UUID
Definition: uuid.h:10
CompositeShape.h
std::map
ed::models::readSDFGeometry
bool readSDFGeometry(tue::config::Reader r, geo::CompositeShapePtr &composite, std::stringstream &error, geo::Pose3D pose_offset=geo::Pose3D::identity())
Definition: model_loader.cpp:29
ed::models::ModelLoader::ed_model_paths_
std::vector< std::string > ed_model_paths_
Definition: model_loader.h:96
ed::UpdateRequest::setType
void setType(const UUID &id, const std::string &type)
Definition: update_request.h:106
tue::config::ReaderWriter::endArray
bool endArray()
ed::UpdateRequest::setVisual
void setVisual(const UUID &id, const geo::ShapeConstPtr &visual)
Definition: update_request.h:53
ed::Entity::generateID
static UUID generateID()
Definition: entity.cpp:198
ed::models::ModelLoader::file_paths_
std::vector< std::string > file_paths_
Definition: model_loader.h:98
geo::CompositeShape
configuration.h
tue::config::ReaderWriter::value
bool value(const std::string &name, T &value, RequiredOrOptional opt=REQUIRED)
path.h
tue::config::ReaderWriter::setValue
void setValue(const std::string &name, const T &value)
ed::models::ModelLoader::ModelData
std::pair< tue::config::DataConstPointer, std::vector< std::string > > ModelData
Definition: model_loader.h:87
std::endl
T endl(T... args)
transform_cache.h
ed::models::ModelLoader::exists
bool exists(const std::string &type) const
exists Check of a model of type 'type' exist
Definition: model_loader.cpp:264
std::vector::begin
T begin(T... args)
tue::config::DataConstPointer
tue::config::DataPointer::add
bool add(const DataConstPointer &ptr)
ed::models::MODEL
@ MODEL
Definition: shape_loader_private.h:27
std::string::empty
T empty(T... args)
ed::models::ModelLoader::ModelLoader
ModelLoader()
Definition: model_loader.cpp:51
ed
Definition: convex_hull.h:8
tue::filesystem::Path::string
const std::string & string() const
ed::models::ModelLoader::getSDFPath
std::string getSDFPath(const std::string &uri) const
getSDFPath get file path of SDF model with uri 'uri'
Definition: model_loader.cpp:104
tue::config::Reader::readArray
bool readArray(const std::string &name, const RequiredOrOptional opt=OPTIONAL)
std::vector::end
T end(T... args)
ed::models::FILE
@ FILE
Definition: shape_loader_private.h:28
ed::models::ModelLoader::getModelPath
std::string getModelPath(const std::string &type) const
getModelPath get file path of model of type 'type'
Definition: model_loader.cpp:90
ed::models::readPose
bool readPose(tue::config::Reader &cfg, geo::Pose3D &pose, tue::config::RequiredOrOptional pos_req, tue::config::RequiredOrOptional rot_req)
readPose read pose into Pose3D. Both ED yaml and SDF. Also reads pos(position) of SDF.
Definition: shape_loader.cpp:561
tue::config::Reader::endArray
bool endArray()
ed::models::ModelLoader::~ModelLoader
~ModelLoader()
Definition: model_loader.cpp:78
model_loader.h
ed::UUID::str
const std::string & str() const
Definition: uuid.h:27
writer.h
ed::UpdateRequest::addVolume
void addVolume(const UUID &id, const std::string Volume_name, const geo::ShapeConstPtr &Volume_shape)
Definition: update_request.h:61