shape_volume.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
19 
20 using namespace buoyancy;
21 
24 {
25  double epsilon = 1e-20;
26 
27  ShapeVolume* shape = nullptr;
28 
29  if (sdf->HasElement("box"))
30  {
31  auto boxElem = sdf->GetElement("box");
32  if (boxElem->HasElement("size"))
33  {
34  ignition::math::Vector3d dim = boxElem->GetElement("size")
35  ->Get<ignition::math::Vector3d>();
36  if (dim[0] > epsilon && dim[1] > epsilon && dim[2] > epsilon)
37  {
38  shape = dynamic_cast<ShapeVolume*>(
39  new BoxVolume(dim[0], dim[1], dim[2]));
40  }
41  else
42  {
43  throw ParseException("box", "incorrect dimensions");
44  }
45  }
46  else
47  {
48  throw ParseException("box", "missing <size> element");
49  }
50  }
51  else if (sdf->HasElement("sphere"))
52  {
53  auto sphereElem = sdf->GetElement("sphere");
54  if (sphereElem->HasElement("radius"))
55  {
56  auto r = sphereElem->GetElement("radius")->Get<double>();
57  if (r > epsilon)
58  {
59  shape = dynamic_cast<ShapeVolume*>(new SphereVolume(r));
60  }
61  else
62  {
63  throw ParseException("sphere", "incorrect dimensions");
64  }
65  }
66  else
67  {
68  throw ParseException("sphere", "missing <radius> element");
69  }
70  }
71  else if (sdf->HasElement("cylinder"))
72  {
73  auto cylinderElem = sdf->GetElement("cylinder");
74  if (cylinderElem->HasElement("radius") &&
75  cylinderElem->HasElement("length"))
76  {
77  auto r = cylinderElem->GetElement("radius")->Get<double>();
78  auto l = cylinderElem->GetElement("length")->Get<double>();
79  if (r > epsilon || l > epsilon)
80  {
81  shape = dynamic_cast<ShapeVolume*>(new CylinderVolume(r, l));
82  }
83  else
84  {
85  throw ParseException("cylinder", "incorrect dimensions");
86  }
87  }
88  else
89  {
90  throw ParseException("cylinder", "missing <radius> or <length> element");
91  }
92  }
93  else
94  {
95  throw ParseException(
96  "geometry", "missing <box>, <cylinder> or <sphere> element");
97  }
98 
99  return std::unique_ptr<ShapeVolume>(shape);
100 }
101 
103 std::string ShapeVolume::Display()
104 {
105  switch (type)
106  {
107  case ShapeType::None:
108  return "None";
109  case ShapeType::Box:
110  return "Box";
111  case ShapeType::Cylinder:
112  return "Cylinder";
113  case ShapeType::Sphere:
114  return "Sphere";
115  }
116 }
117 
119 BoxVolume::BoxVolume(double x, double y, double z)
120  : x(x),
121  y(y),
122  z(z),
123  polyhedron(Polyhedron::makeCube(x, y, z))
124 {
126  volume = x * y * z;
127  averageLength = (x + y + z) / 3.0;
128 }
129 
131 std::string BoxVolume::Display()
132 {
133  std::stringstream ss;
134  ss << ShapeVolume::Display() << ":" << x << "," << y << "," << z;
135  return ss.str();
136 }
137 
139 Volume BoxVolume::CalculateVolume(const ignition::math::Pose3d &pose,
140  double fluidLevel)
141 {
142  Plane waterSurface;
143  waterSurface.offset = fluidLevel;
144  return this->polyhedron.SubmergedVolume(pose.Pos(), pose.Rot(), waterSurface);
145 }
146 
149  : r(r),
150  h(h),
151  polyhedron(Polyhedron::makeCylinder(r, h, 20))
152 {
154  volume = M_PI * r * r * h;
155  averageLength = (2 * r + h) / 2.0;
156 }
157 
160 {
161  std::stringstream ss;
162  ss << ShapeVolume::Display() << ":" << r << "," << h;
163  return ss.str();
164 }
165 
167 Volume CylinderVolume::CalculateVolume(const ignition::math::Pose3d &pose,
168  double fluidLevel)
169 {
170  Plane waterSurface;
171  waterSurface.offset = fluidLevel;
172  return this->polyhedron.SubmergedVolume(pose.Pos(), pose.Rot(), waterSurface);
173 }
174 
177  : r(r)
178 {
180  volume = 4./3. * M_PI * r * r * r;
181  averageLength = 2 * r;
182 }
183 
186 {
187  std::stringstream ss;
188  ss << ShapeVolume::Display() << ":" << r;
189  return ss.str();
190 }
191 
193 Volume SphereVolume::CalculateVolume(const ignition::math::Pose3d &pose,
194  double fluidLevel)
195 {
196  Volume output{};
197  // Location of bottom of object relative to the fluid surface - assumes
198  // origin is at cog of the object.
199  double h = fluidLevel - (pose.Pos().Z() - r);
200 
201  if (h <= 0) {
202  return output;
203  }
204 
205  // limits of integration
206  double intLimitLower = -r;
207  double intLimitUpper = (-r + h) > r ? r : (-r + h);
208 
209  // volume = integral of (R^2 - z^2) dz * pi
210  output.volume = (pow(r, 2) * (intLimitUpper - intLimitLower)
211  - (pow(intLimitUpper, 3)/3.0 - pow(intLimitLower, 3)/3.0)) * M_PI;
212  output.centroid.X() = pose.Pos().X();
213  output.centroid.Y() = pose.Pos().Y();
214 
215  if (output.volume > 0) {
216  // centroid is always centered to object in X and Y plane
217  output.centroid.X() = pose.Pos().X();
218  output.centroid.Y() = pose.Pos().Y();
219  // z_bar = (integral of (z(R)^2 - z^3) dz) * pi / volume
220  output.centroid.Z() = (pow(r, 2) / 2.0 *
221  (pow(intLimitUpper, 2) - pow(intLimitLower, 2)) -
222  (pow(intLimitUpper, 4) - pow(intLimitLower, 4))/ 4.0)
223  * M_PI / output.volume;
224  // convert centroid.z to global frame
225  output.centroid.Z() = pose.Pos().Z() + output.centroid.Z();
226  }
227  return output;
228 }
BoxVolume(double x, double y, double z)
Default constructor.
std::string Display() override
Display string for cylinder shape.
double epsilon
std::string Display() override
Display string for box shape.
Box shape volume.
Definition: shape_volume.hh:73
virtual std::string Display()
Display string for shape object.
std::unique_ptr< ShapeVolume > ShapeVolumePtr
Definition: shape_volume.hh:70
float offset
Offset w.r.t. normal.
Volume CalculateVolume(const ignition::math::Pose3d &pose, double fluidLevel) override
Calculates volume + centroid of submerged shape if the shape is out of water returns Volume{}...
Volume CalculateVolume(const ignition::math::Pose3d &pose, double fluidLevel) override
Calculates volume + centroid of submerged shape if the shape is out of water returns Volume{}...
double r
Radius of sphere.
Polyhedron polyhedron
Polyhedron defining a cylinder.
double r
Radius of cylinder.
Submerged volume calculation using polyhedron based on: Exact Buoyancy for Polyhedra by Eric Catto...
Polyhedron polyhedron
Polyhedron defining a box.
Definition: shape_volume.hh:99
double x
Length.
Definition: shape_volume.hh:89
double volume
Full volume of object.
Definition: shape_volume.hh:64
double h
Height of cylinder.
Parent shape object for volume objects.
Definition: shape_volume.hh:40
Sphere shape volume.
SphereVolume(double r)
Default constructor.
double y
Width.
Definition: shape_volume.hh:92
double averageLength
Average length of object estimate used for drag torque calculation.
Definition: shape_volume.hh:68
std::string Display() override
Display string for sphere shape.
Cylinder shape volume.
static std::unique_ptr< ShapeVolume > makeShape(const sdf::ElementPtr sdf)
Factory method for shape. Parses a shape object from sdf data.
Definition: shape_volume.cc:23
ShapeType type
Type of shape.
Definition: shape_volume.hh:61
Represents output volume with centroid.
Custom exception for parsing errors.
Represents a plane as a normal and offset.
double z
Height.
Definition: shape_volume.hh:95
CylinderVolume(double r, double l)
Default constructor.
Volume CalculateVolume(const ignition::math::Pose3d &pose, double fluidLevel) override
Calculates volume + centroid of submerged shape if the shape is out of water returns Volume{}...
Volume SubmergedVolume(const ignition::math::Vector3d &x, const ignition::math::Quaterniond &q, Plane &plane)
Compute submerge volume and center of buoyancy of a polyhedron.


usv_gazebo_plugins
Author(s): Brian Bingham , Carlos Aguero
autogenerated on Thu May 7 2020 03:54:47