Codebase list ignition-math / a3230ec
Update upstream source from tag 'upstream/6.7.0+ds' Update to upstream version '6.7.0+ds' with Debian dir fc074369cc023f6dd125d7fe728736417c7ae2f0 Timo Röhling 3 years ago
91 changed file(s) with 5465 addition(s) and 429 deletion(s). Raw diff Collapse all Expand all
0 # More info:
1 # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
2
3 * @scpeters
4 tutorials/* @maryaB-osr
0 #!/bin/sh -l
1
2 set -x
3
4 BUILD_DIR=`pwd`
5
6 # Install
7 make install
8
9 # Compile examples
10 cd ../examples
11 mkdir build
12 cd build
13 cmake ..
14 make
15 ./graph_example
16
17 cd $BUILD_DIR
0 libeigen3-dev
1 libignition-cmake2-dev
2 ruby-dev
3 swig
0 name: Ubuntu CI
1
2 on: [push, pull_request]
3
4 jobs:
5 bionic-ci:
6 runs-on: ubuntu-latest
7 name: Ubuntu Bionic CI
8 steps:
9 - name: Checkout
10 uses: actions/checkout@v2
11 - name: Compile and test
12 id: ci
13 uses: ignition-tooling/action-ignition-ci@master
14 with:
15 codecov-token: ${{ secrets.CODECOV_TOKEN }}
16 focal-ci:
17 runs-on: ubuntu-latest
18 name: Ubuntu Focal CI
19 steps:
20 - name: Checkout
21 uses: actions/checkout@v2
22 - name: Compile and test
23 id: ci
24 uses: ignition-tooling/action-ignition-ci@focal
0 name: PR Collection Labeler
1
2 on: pull_request_target
3
4 jobs:
5 pr_collection_labeler:
6 runs-on: ubuntu-latest
7 steps:
8 - name: Add collection labels
9 if: github.event.action == 'opened'
10 uses: ignition-tooling/pr-collection-labeler@v1
11 with:
12 github-token: ${{ secrets.GITHUB_TOKEN }}
0 on:
1 issues:
2 types: [opened]
3 pull_request_target:
4 types: [opened]
5 name: Ticket opened
6 jobs:
7 assign:
8 name: Add ticket to inbox
9 runs-on: ubuntu-latest
10 steps:
11 - name: Add ticket to inbox
12 uses: technote-space/create-project-card-action@v1
13 with:
14 PROJECT: Core development
15 COLUMN: Inbox
16 GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }}
17 CHECK_ORG_PROJECT: true
18
0 # CMake folders
1 build
2 build_*
3
4 # OS generated files
5 .DS_Store
6 *.swp
22 #============================================================================
33 # Initialize the project
44 #============================================================================
5 project(ignition-math6 VERSION 6.4.0)
5 project(ignition-math6 VERSION 6.7.0)
66
77 #============================================================================
88 # Find ignition-cmake
0 See the [Ignition Robotics contributing guide](https://bitbucket.org/ignitionrobotics/ign-gazebo/src/default/CONTRIBUTING.md).
0 See the [Ignition Robotics contributing guide](https://ignitionrobotics.org/docs/all/contributing).
00 ## Ignition Math 6.x
11
2 ### Ignition Math 6.4.0
2 ## Ignition Math 6.x.x
3
4 ## Ignition Math 6.7.0 (2020-1X-XX)
5
6 1. Capsule: new shape class with inertia calculation method
7 * [Pull request 163](https://github.com/ignitionrobotics/ign-math/pull/163)
8
9 1. Add missing header to Color.hh
10 * [Pull request 162](https://github.com/ignitionrobotics/ign-math/pull/162)
11
12 1. Improve tests of `Vector2`, `Vector3`, `Vector4`, `Quaternion`, and `Pose3`
13 * [Pull request 172](https://github.com/ignitionrobotics/ign-math/pull/172)
14 * [Pull request 173](https://github.com/ignitionrobotics/ign-math/pull/173)
15 * [Pull request 174](https://github.com/ignitionrobotics/ign-math/pull/174)
16 * [Issue 76](https://github.com/ignitionrobotics/ign-math/issues/76)
17
18 1. Pose3: document `operator*`
19 * [Pull request 170](https://github.com/ignitionrobotics/ign-math/pull/170)
20
21 1. Quaternion: add Normalized() method
22 * [Pull request 169](https://github.com/ignitionrobotics/ign-math/pull/169)
23
24 1. Vector2: add Round(), Rounded() methods
25 * [Pull request 166](https://github.com/ignitionrobotics/ign-math/pull/166)
26 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
27
28 1. Add test for printing `inf` `Vector3`
29 * [Pull request 168](https://github.com/ignitionrobotics/ign-math/pull/168)
30 * [Issue 64](https://github.com/ignitionrobotics/ign-math/issues/64)
31
32 ## Ignition Math 6.6.0 (2020-09-16)
33
34 1. Add chrono duration helper functions
35 * [Pull request 158](https://github.com/ignitionrobotics/ign-math/pull/158)
36
37 ## Ignition Math 6.5.0 (2020-09-04)
38
39 1. Add string to time function
40 * [Pull request 152](https://github.com/ignitionrobotics/ign-math/pull/152)
41
42 1. Added functions to convert between time_point and secNsec
43 * [Pull request 150](https://github.com/ignitionrobotics/ign-math/pull/150)
44
45 1. Fix IGNITION_MATH_XXX_VERSION
46 * [Pull request 151](https://github.com/ignitionrobotics/ign-math/pull/151)
47
48 1. Add Max and Min function to Vector2.hh
49 * [Pull request 133](https://github.com/ignitionrobotics/ign-math/pull/133)
50 * [Pull request 148](https://github.com/ignitionrobotics/ign-math/pull/148)
51 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
52
53 1. Round, Rounded, Correct, Distance(x, y, z, w) and operator< addition to Vector 4
54 * [Pull request 146](https://github.com/ignitionrobotics/ign-math/pull/146)
55 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
56
57 1. Sum and normalized functions for Vector4
58 * [Pull request 140](https://github.com/ignitionrobotics/ign-math/pull/140)
59 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
60
61 1. Vector4 Ruby tests - Vector4.i and Vector4_TEST.rb
62 * [Pull request 137](https://github.com/ignitionrobotics/ign-math/pull/137)
63 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
64
65 1. Vector3 to vector4 functions
66 * [Pull request 132](https://github.com/ignitionrobotics/ign-math/pull/132)
67 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
68
69 1. Update vector2 fuctions from vector3
70 * [Pull request 130](https://github.com/ignitionrobotics/ign-math/pull/130)
71 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
72
73 1. Add Abs, Dot and AbsDot and respective tests to Vector4
74 * [Pull request 135](https://github.com/ignitionrobotics/ign-math/pull/135)
75 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
76
77 1. Create abs, absDot and Correct functions for Vector2d
78 * [Pull request 143](https://github.com/ignitionrobotics/ign-math/pull/143)
79 * [Issue 71](https://github.com/ignitionrobotics/ign-math/issues/71)
80
81 1. Document Ruby tests
82 * [Pull request 145](https://github.com/ignitionrobotics/ign-math/pull/145)
83
84 1. Add header for numeric_limits allowing build on ubuntu 16.04
85 * [Pull request 119](https://github.com/ignitionrobotics/ign-math/pull/119)
86
87 1. Add setter/getter for Pose's each element
88 * [Pull request 125](https://github.com/ignitionrobotics/ign-math/pull/125)
89 * [Issue 35](https://github.com/ignitionrobotics/ign-math/issues/35)
90
91 1. Implement AxisAlignedBox Volume function
92 * [Pull request 126](https://github.com/ignitionrobotics/ign-math/pull/126)
93
94 1. Add operator + for AxisAlignedBox and Vector3.
95 * [Pull request 122](https://github.com/ignitionrobotics/ign-math/pull/122)
96
97 1. Make alpha optional when parsing a Color from an input stream.
98 * [Pull request 106](https://github.com/ignitionrobotics/ign-math/pull/106)
99
100 1. GitHub actions CI and workflow updates
101 * [Pull request 117](https://github.com/ignitionrobotics/ign-math/pull/117)
102 * [Pull request 139](https://github.com/ignitionrobotics/ign-math/pull/139)
103 * [Pull request 110](https://github.com/ignitionrobotics/ign-math/pull/110)
104
105 1. Added a Gauss-Markov Process class.
106 * [BitBucket pull request 342](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/342)
107
108 1. Fix bug in Inertial addition of off-diagonal moment of inertia terms with pose offsets.
109 * [BitBucket pull request 344](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/344)
110
111 1. Create FAKE_INSTALL target so example compilation can be tested without doing a real install.
112 * Angle: [BitBucket pull request 335](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/335)
113
114 1. Updating documentation.
115 * Angle: [BitBucket pull request 325](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/325)
116
117 1. GraphAlgorithms: add ToUndirected(DirectedGraph) that copies to an UndirectedGraph.
118 * [BitBucket pull request 332](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/332)
119
120 1. Doxygen fixes for graph classes
121 * [BitBucket pull request 331](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/331)
122
123 ## Ignition Math 6.4.0
3124
4125 1. Added a function that rounds up a number to the nearest multiple of
5126 another number.
6 * [Pull request 318](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/318)
127 * [BitBucket pull request 318](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/318)
7128
8129 ### Ignition Math 6.3.0
9130
10 1. Added Odometry class that computes odometry for a two wheeled vehicle.
11 * [Pull request 313](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/313)
12
13 1. Added RollingMean class.
14 * [Pull request 314](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/314)
131 1. Added Odometry class that computes odometry for a two wheeled vehicle.
132 * [BitBucket pull request 313](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/313)
133
134 1. Added RollingMean class.
135 * [BitBucket pull request 314](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/314)
15136
16137 ### Ignition Math 6.2.0
17138
18139 1. eigen3: Use linear() instead of rotation() to prevent computation of SVD
19 * [Pull request 311](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/311)
140 * [BitBucket pull request 311](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/311)
20141
21142 1. Change definition of Pose3 `*` operator to fix multiplication order
22 * [Pull request 301](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/301)
23 * [Issue 60](https://bitbucket.org/ignitionrobotics/ign-math/issues/60)
143 * [BitBucket pull request 301](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/301)
144 * [Issue 60](https://github.com/ignitionrobotics/ign-math/issues/60)
24145
25146 ### Ignition Math 6.1.0
26147
27148 1. eigen3: add conversion functions for Eigen::AlignedBox3d <=> ignition::math::AxisAlignedBox
28 * [Pull request 302](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/302)
149 * [BitBucket pull request 302](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/302)
29150
30151 ### Ignition Math 6.0.0
31152
32153 1. Helper function that converts from `std::chrono::steady_clock::duration` to
33154 {seconds, nanoseconds}.
34 * [Pull request XXX](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/XXX)
155 * [BitBucket pull request XXX](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/XXX)
35156
36157 1. Upgrade to c++17.
37 * [Pull request 268](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/268)
158 * [BitBucket pull request 268](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/268)
38159
39160 ## Ignition Math 5.x
40161
41162 ### Ignition Math 5.x.x
42163
164 ### Ignition Math 5.1.0 (2019-09-11)
165
166 1. GraphAlgorithms: add ToUndirected(DirectedGraph) that copies to an UndirectedGraph.
167 * [BitBucket pull request 332](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/332)
168
169 1. Doxygen fixes for graph classes
170 * [BitBucket pull request 331](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/331)
171
43172 1. eigen3: Use linear() instead of rotation() to prevent computation of SVD
44 * [Pull request 312](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/312)
173 * [BitBucket pull request 312](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/312)
45174
46175 1. Change definition of Pose3 `*` operator to fix multiplication order
47 * [Pull request 301](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/301)
48 * [Issue 60](https://bitbucket.org/ignitionrobotics/ign-math/issues/60)
176 * [BitBucket pull request 301](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/301)
177 * [Issue 60](https://github.com/ignitionrobotics/ign-math/issues/60)
49178
50179 1. eigen3: add conversion functions for Eigen::AlignedBox3d <=> ignition::math::AxisAlignedBox
51 * [Pull request 302](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/302)
180 * [BitBucket pull request 302](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/302)
52181
53182
54183 ### Ignition Math 5.0.0 (2018-12-12)
55184
56185 1. Added a Stopwatch class
57 * [Pull request 279](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/279)
186 * [BitBucket pull request 279](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/279)
58187
59188 1. Added material properties to OrientedBox
60 * [Pull request 269](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/269)
189 * [BitBucket pull request 269](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/269)
61190
62191 1. Added a Cylinder class.
63 * [Pull request 250](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/250)
192 * [BitBucket pull request 250](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/250)
64193
65194 1. The `Box` class has been changed to a templatized class that is not
66195 axis-aligned. The previous `Box` functionality is now in the
67196 `AxisAlignedBox` class.
68 * [Pull request 257](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/257)
197 * [BitBucket pull request 257](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/257)
69198
70199 1. Added eigen3 component with functions for converting between Eigen and ign-math types.
71 * [Pull request 256](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/256)
200 * [BitBucket pull request 256](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/256)
72201
73202 1. Added a `MassMatrix3::SetFromCylinder` function that uses a `Material`
74203 to specify a density.
75 * [Pull request 248](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/248)
204 * [BitBucket pull request 248](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/248)
76205
77206 1. Added a Sphere class.
78 * [Pull request 255](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/255)
207 * [BitBucket pull request 255](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/255)
79208
80209 1. Added a `MassMatrix3::SetFromSphere` function that uses a `Material` to
81210 specify a density.
82 * [Pull request 247](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/247)
211 * [BitBucket pull request 247](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/247)
83212
84213 1. Added a `MassMatrix3::SetFromBox` function that uses a `Material` to specify
85214 a density.
86 * [Pull request 246](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/246)
215 * [BitBucket pull request 246](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/246)
87216
88217 1. Deprecated mutator functions in MassMatrix3 that lacked a `Set` prefix.
89 * [Pull request 262](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/262)
218 * [BitBucket pull request 262](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/262)
90219
91220 1. Updated the MassMatrix3::ValidMoments(), MassMatrix3::IsValid(), MassMatrix3::IsPositive(),
92221 and Inertial::SetMassMatrix functions to accept a tolerance parameter.
93 * [Pull request 264](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/264)
222 * [BitBucket pull request 264](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/264)
94223
95224 1. Add MassMatrix3::IsNearPositive and use it in MassMatrix3::IsValid, use >= instead of >
96225 in MassMatrix3::ValidMoments
97 * [Pull request 278](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/278)
226 * [BitBucket pull request 278](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/278)
98227
99228 ## Ignition Math 4.x
100229
102231
103232 1. Add Graph::EdgeFromVertices function that return an edge, if one exists,
104233 between two vertices.
105 * [Pull request 254](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/254)
234 * [BitBucket pull request 254](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/254)
106235
107236 1. Added multiply assign operator to Matrix4.
108 * [Pull request 252](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/252)
237 * [BitBucket pull request 252](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/252)
109238
110239
111240 1. Add Plane copy constructor and fix cppcheck on artful
112 * [Pull request 230](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/230)
241 * [BitBucket pull request 230](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/230)
113242
114243 1. Added MovingWindowFilter, a copy from Ignition Common. This version will
115244 replace the version found in Ignition Common.
116 * [Pull request 239](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/239)
245 * [BitBucket pull request 239](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/239)
117246
118247 1. Added a Material class, which holds information about materials like wood,
119248 steel, and iron.
120 * [Pull request 243](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/243)
249 * [BitBucket pull request 243](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/243)
121250
122251 ### Ignition Math 4.0.0 (2017-12-26)
123252
124253 1. Use std::stoi and std::stod in math::parse* functions to reduce code
125 * [Pull request 224](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/224)
126 * [Issue 50](https://bitbucket.org/ignitionrobotics/ign-math/issues/50)
254 * [BitBucket pull request 224](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/224)
255 * [Issue 50](https://github.com/ignitionrobotics/ign-math/issues/50)
127256
128257 1. Fixing const-correctness for operator* of Pose3
129 * [Pull request 205](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/205)
258 * [BitBucket pull request 205](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/205)
130259
131260 1. Deprecate Matrix4::Translate and replace by Matrix4::SetTranslation
132 * [Pull request 222](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/222)
261 * [BitBucket pull request 222](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/222)
133262
134263 1. Use ignition-cmake to simplify build scripts
135 * [Pull request 200](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/200)
264 * [BitBucket pull request 200](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/200)
136265
137266 1. Make constructor SemanticVersion(string) explicit
138 * [Pull request 203](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/203)
267 * [BitBucket pull request 203](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/203)
139268
140269 1. Switch to C++14
141 * [Pull request 180](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/180)
270 * [BitBucket pull request 180](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/180)
142271
143272 1. Removed the box 'extent' field. The default constructor now sets a box's
144273 corners to extrema in order to indicate an uninitialized box.
145 * [Pull request 172](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/172)
146 * [Issue 72](https://bitbucket.org/ignitionrobotics/ign-math/issues/72)
147 * [Issue 53](https://bitbucket.org/ignitionrobotics/ign-math/issues/53)
274 * [BitBucket pull request 172](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/172)
275 * [Issue 72](https://github.com/ignitionrobotics/ign-math/issues/72)
276 * [Issue 53](https://github.com/ignitionrobotics/ign-math/issues/53)
148277
149278 1. Added graph utilites:
150279 1. Added a Vertex class:
151 * [Pull request 170](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/170)
280 * [BitBucket pull request 170](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/170)
152281 1. Added an Edge class:
153 * [Pull request 174](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/174)
282 * [BitBucket pull request 174](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/174)
154283 1. Added a Graph class:
155 * [Pull request 175](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/175)
284 * [BitBucket pull request 175](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/175)
156285 1. Added a GraphAlgorithms class:
157 * [Pull request 177](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/177)
286 * [BitBucket pull request 177](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/177)
158287 1. Added a function to calculate connected components in undirected
159288 graphs:
160 * [Pull request 190](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/190)
289 * [BitBucket pull request 190](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/190)
161290 1. Improved the performance of `graph::InDegree()` and `graph::IncidentsTo()`.
162 * [Pull request 188](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/188)
163 * [Issue 79](https://bitbucket.org/ignitionrobotics/ign-math/issues/79)
291 * [BitBucket pull request 188](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/188)
292 * [Issue 79](https://github.com/ignitionrobotics/ign-math/issues/79)
164293
165294 1. Added Inline Versioned Namespace
166 * [Pull request 216](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/216/)
295 * [BitBucket pull request 216](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/216/)
167296
168297 ## Ignition Math 3.x
169298
174303 ### Ignition Math 3.3.0 (2017-11-27)
175304
176305 1. Fixed frustum falsely saying it contained AABB in some cases
177 * [Pull request 193](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/193)
178 * [Issue 78](https://bitbucket.org/ignitionrobotics/ign-math/issues/78)
306 * [BitBucket pull request 193](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/193)
307 * [Issue 78](https://github.com/ignitionrobotics/ign-math/issues/78)
179308
180309 1. Create consistent bracket operators across all Vector# types
181 * [Pull request 181](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/181)
310 * [BitBucket pull request 181](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/181)
182311
183312 1. Change name to the generic BUILDING_DLL macro to avoid conflicts
184 * [Pull request 173](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/173)
313 * [BitBucket pull request 173](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/173)
185314
186315 1. Fix some compiler warnings
187 * [Pull request 196](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/196)
316 * [BitBucket pull request 196](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/196)
188317
189318 1. Suppress gtest warnings
190 * [Pull request 199](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/199)
319 * [BitBucket pull request 199](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/199)
191320
192321 1. Move private headers to src folder
193 * [Pull request 198](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/198)
322 * [BitBucket pull request 198](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/198)
194323
195324 1. Update configure.bat
196 * [Pull request 206](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/206)
325 * [BitBucket pull request 206](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/206)
197326
198327 ### Ignition Math 3.2.0 (2017-05-15)
199328
200329 1. Construct on first use in Rand class
201 * [Pull request 165](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/165)
330 * [BitBucket pull request 165](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/165)
202331
203332 1. Extended Spline API: derivative interpolation, arc length calculation
204333 and tangent forcing.
205 * [Pull request 162](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/162)
334 * [BitBucket pull request 162](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/162)
206335
207336 ### Ignition Math 3.1.0 (2017-04-11)
208337
209338 1. Added signum functions to Helpers.hh.
210339 * Contribution from Martin Pecka
211 * [Pull request 153](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/153)
340 * [BitBucket pull request 153](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/153)
212341
213342 ### Ignition Math 3.0.0 (2017-01-05)
214343
215344 1. Deprecate many IGN_* macros in favor of static const variables in Helpers.hh
216 * [Pull request 138](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/138)
217 * [Pull request 137](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/137)
345 * [BitBucket pull request 138](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/138)
346 * [BitBucket pull request 137](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/137)
218347
219348 1. Removed exceptions. Return values should be evaluated to determine if
220349 errors have occured.
221 * [Pull request 132](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/132)
350 * [BitBucket pull request 132](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/132)
222351
223352 1. Added `operator=(const Quaternion<T> &_q)` to `Matrix3`.
224 * [Pull request 111](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/111)
353 * [BitBucket pull request 111](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/111)
225354
226355 1. Fix xenial cppcheck
227 * [Pull request xxx](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/xxx)
356 * [BitBucket pull request xxx](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/xxx)
228357
229358 1. Require cmake 2.8.12
230 * [Pull request 76](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/76)
359 * [BitBucket pull request 76](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/76)
231360
232361 1. Migrate to relocatable CMake package.
233362 Contribution from Silvio Traversaro.
234 * [Pull request 67](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/67)
363 * [BitBucket pull request 67](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/67)
235364
236365 1. Fix logic of installation of CMake configuration files in Windows.
237366 Contribution from Silvio Traversaro.
238 * [Pull request 63](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/63)
367 * [BitBucket pull request 63](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/63)
239368
240369 ## Ignition Math 2.x
241370
244373 ## Ignition Math 2.9 (2017-11-22)
245374
246375 1. Fixed frustum falsely saying it contained AABB in some cases
247 * [Pull request 193](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/193)
376 * [BitBucket pull request 193](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/193)
248377
249378 1. Added Color
250 * [Pull request 150](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/150)
379 * [BitBucket pull request 150](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/150)
251380
252381 1. Backport updated configure.bat to ign-math2 and fix cppcheck warnings
253 * [Pull request 207](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/207)
382 * [BitBucket pull request 207](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/207)
254383
255384 ### Ignition Math 2.8
256385
257386 ### Ignition Math 2.8.0
258387
259388 1. Added OrientedBox
260 * [Pull request 146](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/146)
389 * [BitBucket pull request 146](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/146)
261390
262391 1. Added an assignment operator to the Frustum class.
263 * [Pull request 144](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/144)
392 * [BitBucket pull request 144](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/144)
264393
265394 ### Ignition Math 2.7
266395
267396 ### Ignition Math 2.7.0
268397
269398 1. Add static const variables as alternative to macros in Helpers.hh
270 * [Pull request 137](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/137)
399 * [BitBucket pull request 137](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/137)
271400
272401 1. Add new methods for floating numbers: lessOrEqual and greaterOrEqual
273 * [Pull request 134](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/134)
402 * [BitBucket pull request 134](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/134)
274403
275404 ### Ignition Math 2.6
276405
278407
279408 1. Added copy constructor, equality operators and assignment operators to
280409 SphericalCoordinates class.
281 * [Pull request 131](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/131)
410 * [BitBucket pull request 131](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/131)
282411
283412 1. Fix Euler angle conversion of quaternions near singularities
284 * [Pull request 129](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/129)
413 * [BitBucket pull request 129](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/129)
285414
286415 1. Backport triangle3, helper functions, equality helper to work with 387 fp unit
287416 (Contribution from Rich Mattes).
288 * [Pull request 125](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/125)
289 * [Pull request 58](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/58)
290 * [Pull request 56](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/56)
417 * [BitBucket pull request 125](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/125)
418 * [BitBucket pull request 58](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/58)
419 * [BitBucket pull request 56](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/56)
291420
292421 1. Added Matrix4<T>::LookAt
293 * [Pull request 124](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/124)
422 * [BitBucket pull request 124](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/124)
294423
295424 1. Set Inertial Rotations
296 * [Pull request 121](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/121)
425 * [BitBucket pull request 121](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/121)
297426
298427 1. Added SemanticVersion class
299 * [Pull request 120](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/120)
428 * [BitBucket pull request 120](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/120)
300429
301430 ### Ignition Math 2.5
302431
303432 ### Ignition Math 2.5.0
304433
305434 1. Added PID class
306 * [Pull request 117](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/117)
435 * [BitBucket pull request 117](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/117)
307436
308437 1. Added SphericalCoordinate class
309 * [Pull request 108](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/108)
438 * [BitBucket pull request 108](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/108)
310439
311440 ### Ignition Math 2.4
312441
314443
315444 1. Combine inertial properties of different objects, returning the equivalent
316445 inertial properties as if the objects were welded together.
317 * [Pull request 115](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/115)
446 * [BitBucket pull request 115](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/115)
318447
319448 #### Ignition Math 2.4.0
320449
321450 1. New MassMatrix3 class
322 * [Pull request 112](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/112)
451 * [BitBucket pull request 112](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/112)
323452 1. MassMatrix3 helper functions
324 * [Pull request 110](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/110)
453 * [BitBucket pull request 110](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/110)
325454 1. Added Temperature class
326455 * A contribution from Shintaro Noda
327 * [Pull request 113](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/113)
456 * [BitBucket pull request 113](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/113)
328457
329458 ### Ignition Math 2.3.0
330459
331460 1. Added simple volumes formulas
332 * [Pull request 84](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/84)
461 * [BitBucket pull request 84](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/84)
333462 1. Add Length and SquaredLength for Vector2 with test
334 * [Pull request 73](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/73)
463 * [BitBucket pull request 73](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/73)
335464 1. Add Equal function with numerical tolerance argument
336 * [Pull request 75](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/75)
465 * [BitBucket pull request 75](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/75)
337466 1. First part of MassMatrix3 class, mostly accessors and modifiers
338 * [Pull request 77](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/77)
467 * [BitBucket pull request 77](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/77)
339468 1. Add Transpose methods for Matrix3,4 with test
340 * [Pull request 74](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/74)
469 * [BitBucket pull request 74](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/74)
341470 1. Multiplication improvements for Vector/Matrix classes
342 * [Pull request 69](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/69)
471 * [BitBucket pull request 69](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/69)
343472 1. Scalar +,- operators for Vector[234]
344 * [Pull request 71](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/71)
473 * [BitBucket pull request 71](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/71)
345474 1. Add Determinant method for Matrix[34]
346 * [Pull request 72](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/72)
475 * [BitBucket pull request 72](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/72)
347476 1. Fixes for compiling and running tests on Windows 7/Visual Studio 2013
348477 Contribution from Silvio Traversaro.
349 * [Pull request 62](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/62)
478 * [BitBucket pull request 62](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/62)
11
22 **Maintainer:** nate AT openrobotics DOT org
33
4 [![Bitbucket open issues](https://img.shields.io/bitbucket/issues-raw/ignitionrobotics/ign-math.svg)](https://bitbucket.org/ignitionrobotics/ign-math/issues)
5 [![Bitbucket open pull requests](https://img.shields.io/bitbucket/pr-raw/ignitionrobotics/ign-math.svg)](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests)
4 [![GitHub open issues](https://img.shields.io/github/issues-raw/ignitionrobotics/ign-math.svg)](https://github.com/ignitionrobotics/ign-math/issues)
5 [![GitHub open pull requests](https://img.shields.io/github/issues-pr-raw/ignitionrobotics/ign-math.svg)](https://github.com/ignitionrobotics/ign-math/pulls)
66 [![Discourse topics](https://img.shields.io/discourse/https/community.gazebosim.org/topics.svg)](https://community.gazebosim.org)
77 [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](https://www.apache.org/licenses/LICENSE-2.0)
88
99 Build | Status
1010 -- | --
11 Test coverage | [![codecov](https://codecov.io/bb/ignitionrobotics/ign-math/branch/default/graph/badge.svg)](https://codecov.io/bb/ignitionrobotics/ign-math)
12 Ubuntu Bionic | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_math-ci-default-bionic-amd64)](https://build.osrfoundation.org/job/ignition_math-ci-default-bionic-amd64)
13 Homebrew | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_math-ci-default-homebrew-amd64)](https://build.osrfoundation.org/job/ignition_math-ci-default-homebrew-amd64)
14 Windows | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_math-ci-default-windows7-amd64)](https://build.osrfoundation.org/job/ignition_math-ci-default-windows7-amd64)
11 Test coverage | [![codecov](https://codecov.io/gh/ignitionrobotics/ign-math/branch/master/graph/badge.svg)](https://codecov.io/gh/ignitionrobotics/ign-math)
12 Ubuntu Bionic | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_math-ci-master-bionic-amd64)](https://build.osrfoundation.org/job/ignition_math-ci-master-bionic-amd64)
13 Homebrew | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_math-ci-master-homebrew-amd64)](https://build.osrfoundation.org/job/ignition_math-ci-master-homebrew-amd64)
14 Windows | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_math-ci-master-windows7-amd64)](https://build.osrfoundation.org/job/ignition_math-ci-master-windows7-amd64)
1515
1616 Ignition Math, a component of [Ignition
1717 Robotics](https://ignitionrobotics.org), provides general purpose math
1919
2020 # Table of Contents
2121
22 [Features](#markdown-header-features)
22 [Features](#features)
2323
24 [Install](#markdown-header-install)
24 [Install](#install)
2525
26 * [Binary Install](#markdown-header-binary-install)
26 [Usage](#usage)
2727
28 * [Source Install](#markdown-header-source-install)
28 [Documentation](#documentation)
2929
30 * [Prerequisites](#markdown-header-prerequisites)
30 [Testing](#testing)
3131
32 * [Building from Source](#markdown-header-building-from-source)
32 [Folder Structure](#folder-structure)
3333
34 [Usage](#markdown-header-usage)
34 [Code of Conduct](#code-of-conduct)
3535
36 [Documentation](#markdown-header-documentation)
36 [Contributing](#code-of-contributing)
3737
38 [Testing](#markdown-header-testing)
38 [Versioning](#versioning)
3939
40 [Folder Structure](#markdown-header-folder-structure)
41
42 [Code of Conduct](#markdown-header-code-of-conduct)
43
44 [Contributing](#markdown-header-code-of-contributing)
45
46 [Versioning](#markdown-header-versioning)
47
48 [License](#markdown-header-license)
40 [License](#license)
4941
5042 # Features
5143
5951
6052 # Install
6153
62 We recommend following the [Binary Install](#markdown-header-binary-install) instructions to get up and running as quickly and painlessly as possible.
63
64 The [Source Install](#markdown-header-source-install) instructions should be used if you need the very latest software improvements, you need to modify the code, or you plan to make a contribution.
65
66 ## Binary Install
67
68 On Ubuntu systems, `apt-get` can be used to install `ignition-math`:
69
70 ```
71 sudo apt install libignition-math<#>-dev
72 ```
73
74 Be sure to replace `<#>` with a number value, such as 1 or 2, depending on
75 which version you need.
76
77 ## Source Install
78
79 Source installation can be performed in UNIX systems by first installing the
80 necessary prerequisites followed by building from source.
81
82 ### Prerequisites
83
84 The optional Eigen component of Ignition Math requires:
85
86 * [Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page). Refer to the [Eigen Documentation](http://eigen.tuxfamily.org/index.php?title=Main_Page#Documentation) for installation instructions. On Ubuntu systems, `apt-get` can be used to install Eigen:
87
88 ```
89 sudo apt-get install libeigen3-dev
90 ```
91
92 ### Building from source
93
94 1. Clone the repository
95
96 ```
97 hg clone https://bitbucket.org/ignitionrobotics/ign-math
98 ```
99
100 2. Configure and build
101
102 ```
103 cd ign-math; mkdir build; cd build; cmake ..; make
104 ```
105
106 3. Optionally, install Ignition Math
107
108 ```
109 sudo make install
110 ```
54 See the [installation tutorial](https://ignitionrobotics.org/api/math/6.6/install.html).
11155
11256 # Usage
11357
114 Please refer to the [examples directory](https://bitbucket.org/ignitionrobotics/ign-math/raw/default/examples/?at=default).
58 Please refer to the [examples directory](https://github.com/ignitionrobotics/ign-math/raw/master/examples/).
11559
11660 # Documentation
11761
12872 2. Clone the repository
12973
13074 ```
131 hg clone https://bitbucket.org/ignitionrobotics/ign-math
75 git clone https://github.com/ignitionrobotics/ign-math
13276 ```
13377
13478 3. Configure and build the documentation.
14791
14892 Follow these steps to run tests and static code analysis in your clone of this repository.
14993
150 1. Follow the [source install instruction](#markdown-header-source-install).
94 1. Follow the [source install instruction](https://ignitionrobotics.org/libs/math#source-install).
15195
15296 2. Run tests.
15397
160104 ```
161105 make codecheck
162106 ```
107
108 ## Ruby Tests
109
110 ### Usage
111
112 The C++ classes are available in Ruby code by interface files (`.i`) used by swig to build a C++ extension module.
113
114 The interfaces and Ruby test codes are in the `src` folder. To use a C++ class in Ruby you need to:
115
116 1. Create an interface file describing the class as in Swig and Ruby reference at [The Ruby-to-C/C++ Mapping](http://www.swig.org/Doc1.3/Ruby.html#Ruby_nn11)
117
118 2. Include the interface file in `/src/ing_math.i`
119
120 3. Create the Ruby file and import the class as in Swig and Ruby reference at [C++ Classes](http://www.swig.org/Doc1.3/Ruby.html#Ruby_nn18)
121
122 ### Tests
123
124 `make test` already runs all tests, including the ones made in Ruby, but you can run a Ruby test individually using
125
126 ```
127 ctest -R Ruby_TEST.rb
128 ```
163129
164130 # Folder Structure
165131
183149 # Contributing
184150
185151 Please see
186 [CONTRIBUTING.md](https://bitbucket.org/ignitionrobotics/ign-gazebo/src/406665896aa40bb42f14cf61d48b3d94f2fc5dd8/CONTRIBUTING.md?at=default&fileviewer=file-view-default).
152 [CONTRIBUTING.md](https://github.com/ignitionrobotics/ign-gazebo/blob/master/CONTRIBUTING.md).
187153
188154 # Code of Conduct
189155
190156 Please see
191 [CODE_OF_CONDUCT.md](https://bitbucket.org/ignitionrobotics/ign-gazebo/src/406665896aa40bb42f14cf61d48b3d94f2fc5dd8/CODE_OF_CONDUCT.md?at=default&fileviewer=file-view-default).
157 [CODE_OF_CONDUCT.md](https://github.com/ignitionrobotics/ign-gazebo/blob/master/CODE_OF_CONDUCT.md).
192158
193159 # Versioning
194160
196162
197163 # License
198164
199 This library is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). See also the [LICENSE](https://bitbucket.org/ignitionrobotics/ign-math/src/default/LICENSE) file.
165 This library is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). See also the [LICENSE](https://github.com/ignitionrobotics/ign-math/blob/master/LICENSE) file.
0 os:
1 - Visual Studio 2017
2
3 configuration:
4 - Debug
5 - Release
6
7 environment:
8 CTEST_OUTPUT_ON_FAILURE: 1
9
10 install:
11 - git clone https://github.com/ignitionrobotics/ign-cmake
12 - cd ign-cmake
13 - git checkout ign-cmake2
14 - md build
15 - cd build
16 - cmake .. -DBUILD_TESTING:BOOL=False
17 - cmake --build . --target INSTALL
18 - cd ../..
19 build_script:
20 - md build
21 - cd build
22 - cmake .. -DCMAKE_CXX_FLAGS="-WX"
23 - cmake --build . --config %CONFIGURATION%
24
25 after_build:
26 - cmake --build . --config %CONFIGURATION% --target INSTALL
27
28 test_script:
29 - cmake --build . --config %CONFIGURATION% --target RUN_TESTS
30 # Build the examples to make sure that find_package(ignition-math* REQUIRED) works
31 - cd ../examples
32 - md build
33 - cd build
34 - cmake ..
35 - cmake --build . --config %CONFIGURATION%
36 - cd ..
37
0 image: ubuntu:bionic
1
2 pipelines:
3 default:
4 - step:
5 script:
6 - apt-get update
7 - apt-get -y install cmake build-essential curl git cppcheck ruby-dev swig g++-8 libeigen3-dev doxygen
8 - update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800 --slave /usr/bin/g++ g++ /usr/bin/g++-8 --slave /usr/bin/gcov gcov /usr/bin/gcov-8
9 - gcc -v
10 - g++ -v
11 - gcov -v
12 # lcov
13 - git clone https://github.com/linux-test-project/lcov.git
14 - cd lcov
15 # see https://github.com/linux-test-project/lcov/issues/55
16 - git checkout 1e0df571
17 - make install
18 - cd ..
19 # Ignition cmake
20 - echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable bionic main" > /etc/apt/sources.list.d/gazebo-stable.list
21 # - echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-prerelease bionic main" > /etc/apt/sources.list.d/gazebo-prerelease.list
22 - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D2486D2DD83DB69272AFE98867170598AF249743
23 - apt-get update
24 - apt-get -y install
25 libignition-cmake2-dev
26 # Ignition math
27 - mkdir build
28 - cd build
29 - cmake .. -DCMAKE_BUILD_TYPE=coverage
30 - make
31 # Make sure documentation generation generated no warnings.
32 - make doc
33 - bash <(curl -s https://github.com/ignitionrobotics/ign-cmake/raw/master/tools/doc_check.sh)
34 - make test
35 - make coverage
36 # Use a special version of codecov for handling gcc8 output.
37 - bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/4678d212cce2078bbaaf5027af0c0dafaad6a095/codecov) -X gcovout -X gcov
38 - make codecheck
39 - make install
40 # Examples
41 - cd ..
42 - cd examples
43 - mkdir build
44 - cd build
45 - cmake ..
46 - make
47 - ./graph_example
22 # Find the Ignition-Math library
33 set(IGN_MATH_VER 6)
44 find_package(ignition-math${IGN_MATH_VER} REQUIRED)
5
6 add_executable(angle_example angle_example.cc)
7 target_link_libraries(angle_example ignition-math${IGN_MATH_VER}::ignition-math${IGN_MATH_VER})
8
9 add_executable(gauss_markov_process gauss_markov_process_example.cc)
10 target_link_libraries(gauss_markov_process ignition-math${IGN_MATH_VER}::ignition-math${IGN_MATH_VER})
511
612 add_executable(vector2_example vector2_example.cc)
713 target_link_libraries(vector2_example ignition-math${IGN_MATH_VER}::ignition-math${IGN_MATH_VER})
0 /*
1 * Copyright (C) 2019 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16 //! [complete]
17 #include <iostream>
18 #include <ignition/math/Angle.hh>
19
20 int main(int argc, char **argv)
21 {
22 // Create an angle.
23 ignition::math::Angle a;
24
25 // A default constructed angle should be zero.
26 std::cout << "The angle 'a' should be zero: " << a << std::endl;
27 a = ignition::math::Angle::Pi;
28
29 // Output the angle in radians and degrees.
30 std::cout << "Pi in radians: " << a << std::endl;
31 std::cout << "Pi in degrees: " << a.Degree() << std::endl;
32
33 // The Angle class overloads the +=, and many other, math operators.
34 a += ignition::math::Angle::HalfPi;
35 std::cout << "Pi + PI/2 in radians: " << a << std::endl;
36 std::cout << "Normalized to the range -Pi and Pi: "
37 << a.Normalized() << std::endl;
38 }
39 //! [complete]
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16 //! [complete]
17 #include <iostream>
18 #include <ignition/math/GaussMarkovProcess.hh>
19
20 // You can plot the data generated by this program by following these
21 // steps.
22 //
23 // 1. Run this program and save the output to a file:
24 // ./gauss_markov_process > plot.data
25 //
26 // 2. Use gnuplot to create a plot:
27 // gnuplot -e 'set terminal jpeg; plot "plot.data" with lines' > out.jpg
28 int main(int argc, char **argv)
29 {
30 // Create the process with:
31 // * Start value of 20.2
32 // * Theta (rate at which the process should approach the mean) of 0.1
33 // * Mu (mean value) 0.
34 // * Sigma (volatility) of 0.5.
35 ignition::math::GaussMarkovProcess gmp(20.2, 0.1, 0, 0.5);
36
37 std::chrono::steady_clock::duration dt = std::chrono::milliseconds(100);
38
39 // This process should decrease toward the mean value of 0.
40 // With noise of 0.5, the process will walk a bit.
41 for (int i = 0; i < 1000; ++i)
42 {
43 double value = gmp.Update(dt);
44 std::cout << value << std::endl;
45 }
46
47 return 0;
48 }
49 //! [complete]
2020 #include <ignition/math/Helpers.hh>
2121 #include <ignition/math/config.hh>
2222
23 /// \def IGN_RTOD(d)
2324 /// \brief Macro that converts radians to degrees
24 /// \param[in] radians
25 /// \param[in] r radians
2526 /// \return degrees
2627 #define IGN_RTOD(r) ((r) * 180 / IGN_PI)
2728
29 /// \def IGN_DTOR(d)
2830 /// \brief Converts degrees to radians
29 /// \param[in] degrees
31 /// \param[in] d degrees
3032 /// \return radians
3133 #define IGN_DTOR(d) ((d) * IGN_PI / 180)
3234
35 /// \def IGN_NORMALIZE(a)
3336 /// \brief Macro that normalizes an angle in the range -Pi to Pi
34 /// \param[in] angle
37 /// \param[in] a angle
3538 /// \return the angle, in range
3639 #define IGN_NORMALIZE(a) (atan2(sin(a), cos(a)))
3740
4346 inline namespace IGNITION_MATH_VERSION_NAMESPACE {
4447 //
4548 /// \class Angle Angle.hh ignition/math/Angle.hh
46 /// \brief An angle and related functions.
49 /// \brief The Angle class is used to simplify and clarify the use of
50 /// radians and degrees measurements. A default constructed Angle instance
51 /// has a value of zero radians/degrees.
52 ///
53 /// Unless otherwise specified, the Angle class assumes units are in
54 /// radians. An example of this are the stream insertion (<<) and
55 /// extraction (>>) operators.
56 ///
57 /// ## Example
58 ///
59 /// \snippet examples/angle_example.cc complete
4760 class IGNITION_MATH_VISIBLE Angle
4861 {
49 /// \brief math::Angle(0)
62 /// \brief An angle with a value of zero.
63 /// Equivalent to math::Angle(0).
5064 public: static const Angle Zero;
5165
52 /// \brief math::Angle(IGN_PI)
66 /// \brief An angle with a value of Pi.
67 /// Equivalent to math::Angle(IGN_PI).
5368 public: static const Angle Pi;
5469
55 /// \brief math::Angle(IGN_PI * 0.5)
70 /// \brief An angle with a value of Pi * 0.5.
71 /// Equivalent to math::Angle(IGN_PI * 0.5).
5672 public: static const Angle HalfPi;
5773
58 /// \brief math::Angle(IGN_PI * 2)
74 /// \brief An angle with a value of Pi * 2.
75 /// Equivalent to math::Angle(IGN_PI * 2).
5976 public: static const Angle TwoPi;
6077
61 /// \brief Constructor
78 /// \brief Default constructor that initializes an Angle to zero
79 /// radians/degrees.
6280 public: Angle();
6381
64 /// \brief Conversion Constructor
65 /// \param[in] _radian Radians
82 /// \brief Conversion constructor that initializes an Angle to the
83 /// specified radians. This constructor supports implicit conversion
84 /// of a double to an Angle. For example:
85 ///
86 /// \code
87 /// Angle a = 3.14;
88 /// \endcode
89 //
90 /// \param[in] _radian The radians used to initialize this Angle.
6691 // cppcheck-suppress noExplicitConstructor
6792 public: Angle(const double _radian);
6893
69 /// \brief Copy constructor
94 /// \brief Copy constructor that initializes this Angle to the value
95 /// contained in the _angle parameter.
7096 /// \param[in] _angle Angle to copy
7197 public: Angle(const Angle &_angle);
7298
7399 /// \brief Destructor
74100 public: virtual ~Angle();
75101
76 /// \brief Set the value from an angle in radians
77 /// \param[in] _radian Radian value
102 /// \brief Set the value from an angle in radians.
103 /// \param[in] _radian Radian value.
104 /// \sa SetRadian(double)
78105 public: void Radian(double _radian);
106
107 /// \brief Set the value from an angle in radians.
108 /// \param[in] _radian Radian value.
109 public: void SetRadian(double _radian);
79110
80111 /// \brief Set the value from an angle in degrees
81112 /// \param[in] _degree Degree value
113 /// \sa SetDegree(double)
82114 public: void Degree(double _degree);
83115
84 /// \brief Get the angle in radians
85 /// \return double containing the angle's radian value
116 /// \brief Set the value from an angle in degrees
117 /// \param[in] _degree Degree value
118 public: void SetDegree(double _degree);
119
120 /// \brief Get the angle in radians.
121 /// \return Double containing the angle's radian value.
86122 public: double Radian() const;
87123
88 /// \brief Get the angle in degrees
89 /// \return double containing the angle's degree value
124 /// \brief Get the angle in degrees.
125 /// \return Double containing the angle's degree value.
90126 public: double Degree() const;
91127
92 /// \brief Normalize the angle in the range -Pi to Pi
128 /// \brief Normalize the angle in the range -Pi to Pi. This
129 /// modifies the value contained in this Angle instance.
130 /// \sa Normalized()
93131 public: void Normalize();
132
133 /// \brief Return the normalized angle in the range -Pi to Pi. This
134 /// does not modify the value contained in this Angle instance.
135 /// \return The normalized value of this Angle.
136 public: Angle Normalized() const;
94137
95138 /// \brief Return the angle's radian value
96139 /// \return double containing the angle's radian value
103146 return value;
104147 }
105148
106 /// \brief Substraction, result = this - _angle
107 /// \param[in] _angle Angle for substraction
108 /// \return the new angle
149 /// \brief Subtraction operator, result = this - _angle.
150 /// \param[in] _angle Angle for subtraction.
151 /// \return The new angle.
109152 public: Angle operator-(const Angle &_angle) const;
110153
111 /// \brief Addition operator, result = this + _angle
112 /// \param[in] _angle Angle for addition
113 /// \return the new angle
154 /// \brief Addition operator, result = this + _angle.
155 /// \param[in] _angle Angle for addition.
156 /// \return The new angle.
114157 public: Angle operator+(const Angle &_angle) const;
115158
116 /// \brief Multiplication operator, result = this * _angle
117 /// \param[in] _angle Angle for multiplication
118 /// \return the new angle
159 /// \brief Multiplication operator, result = this * _angle.
160 /// \param[in] _angle Angle for multiplication.
161 /// \return The new angle
119162 public: Angle operator*(const Angle &_angle) const;
120163
121 /// \brief Division, result = this / _angle
122 /// \param[in] _angle Angle for division
123 /// \return the new angle
164 /// \brief Division operator, result = this / _angle.
165 /// \param[in] _angle Angle for division.
166 /// \return The new angle.
124167 public: Angle operator/(const Angle &_angle) const;
125168
126 /// \brief Subtraction set, this = this - _angle
127 /// \param[in] _angle Angle for subtraction
128 /// \return angle
169 /// \brief Subtraction set operator, this = this - _angle.
170 /// \param[in] _angle Angle for subtraction.
171 /// \return The new angle.
129172 public: Angle operator-=(const Angle &_angle);
130173
131 /// \brief Addition set, this = this + _angle
132 /// \param[in] _angle Angle for addition
133 /// \return angle
174 /// \brief Addition set operator, this = this + _angle.
175 /// \param[in] _angle Angle for addition.
176 /// \return The new angle.
134177 public: Angle operator+=(const Angle &_angle);
135178
136 /// \brief Multiplication set, this = this * _angle
137 /// \param[in] _angle Angle for multiplication
138 /// \return angle
179 /// \brief Multiplication set operator, this = this * _angle.
180 /// \param[in] _angle Angle for multiplication.
181 /// \return The new angle.
139182 public: Angle operator*=(const Angle &_angle);
140183
141 /// \brief Division set, this = this / _angle
142 /// \param[in] _angle Angle for division
143 /// \return angle
184 /// \brief Division set operator, this = this / _angle.
185 /// \param[in] _angle Angle for division.
186 /// \return The new angle.
144187 public: Angle operator/=(const Angle &_angle);
145188
146 /// \brief Equality operator, result = this == _angle
147 /// \param[in] _angle Angle to check for equality
148 /// \return true if this == _angle
189 /// \brief Equality operator, result = this == _angle.
190 /// \param[in] _angle Angle to check for equality.
191 /// \return True if this == _angle.
149192 public: bool operator==(const Angle &_angle) const;
150193
151 /// \brief Inequality
152 /// \param[in] _angle Angle to check for inequality
153 /// \return true if this != _angle
194 /// \brief Inequality operator
195 /// \param[in] _angle Angle to check for inequality.
196 /// \return True if this != _angle.
154197 public: bool operator!=(const Angle &_angle) const;
155198
156 /// \brief Less than operator
157 /// \param[in] _angle Angle to check
158 /// \return true if this < _angle
199 /// \brief Less than operator.
200 /// \param[in] _angle Angle to check.
201 /// \return True if this < _angle.
159202 public: bool operator<(const Angle &_angle) const;
160203
161 /// \brief Less or equal operator
162 /// \param[in] _angle Angle to check
163 /// \return true if this <= _angle
204 /// \brief Less than or equal operator.
205 /// \param[in] _angle Angle to check.
206 /// \return True if this <= _angle.
164207 public: bool operator<=(const Angle &_angle) const;
165208
166 /// \brief Greater than operator
167 /// \param[in] _angle Angle to check
168 /// \return true if this > _angle
209 /// \brief Greater than operator.
210 /// \param[in] _angle Angle to check.
211 /// \return True if this > _angle.
169212 public: bool operator>(const Angle &_angle) const;
170213
171 /// \brief Greater or equal operator
172 /// \param[in] _angle Angle to check
173 /// \return true if this >= _angle
214 /// \brief Greater than or equal operator.
215 /// \param[in] _angle Angle to check.
216 /// \return True if this >= _angle.
174217 public: bool operator>=(const Angle &_angle) const;
175218
176 /// \brief Stream insertion operator. Outputs in degrees
177 /// \param[in] _out output stream
178 /// \param[in] _a angle to output
179 /// \return The output stream
219 /// \brief Stream insertion operator. Outputs in radians.
220 /// \param[in] _out Output stream.
221 /// \param[in] _a Angle to output.
222 /// \return The output stream.
180223 public: friend std::ostream &operator<<(std::ostream &_out,
181224 const ignition::math::Angle &_a)
182225 {
184227 return _out;
185228 }
186229
187 /// \brief Stream extraction operator. Assumes input is in radians
188 /// \param in input stream
189 /// \param pt angle to read value into
190 /// \return The input stream
230 /// \brief Stream extraction operator. Assumes input is in radians.
231 /// \param[in,out] _in Input stream.
232 /// \param[out] _a Angle to read value into.
233 /// \return The input stream.
191234 public: friend std::istream &operator>>(std::istream &_in,
192235 ignition::math::Angle &_a)
193236 {
198241 }
199242
200243 /// The angle in radians
201 private: double value;
244 private: double value{0};
202245 };
203246 }
204247 }
125125 /// \param _v The vector to use during subtraction
126126 /// \return The new box
127127 public: AxisAlignedBox operator-(const Vector3d &_v);
128
129 /// \brief Add a vector to the min and max values
130 /// \param _v The vector to use during addition
131 /// \return The new box
132 public: AxisAlignedBox operator+(const Vector3d &_v);
128133
129134 /// \brief Output operator
130135 /// \param[in] _out Output stream
265270 /// \brief Get the mass matrix for this box. This function
266271 /// is only meaningful if the box's size and material
267272 /// have been set.
268 /// \param[out] _massMatrix The computed mass matrix will be stored
273 /// \param[out] _massMat The computed mass matrix will be stored
269274 /// here.
270275 /// \return False if computation of the mass matrix failed, which
271276 /// could be due to an invalid size (<=0) or density (<=0).
158158 /// \brief Get the mass matrix for this box. This function
159159 /// is only meaningful if the box's size and material
160160 /// have been set.
161 /// \param[out] _massMatrix The computed mass matrix will be stored
161 /// \param[out] _massMat The computed mass matrix will be stored
162162 /// here.
163163 /// \return False if computation of the mass matrix failed, which
164164 /// could be due to an invalid size (<=0) or density (<=0).
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16 #ifndef IGNITION_MATH_CAPSULE_HH_
17 #define IGNITION_MATH_CAPSULE_HH_
18
19 #include <optional>
20 #include "ignition/math/MassMatrix3.hh"
21 #include "ignition/math/Material.hh"
22
23 namespace ignition
24 {
25 namespace math
26 {
27 // Foward declarations
28 class CapsulePrivate;
29
30 // Inline bracket to help doxygen filtering.
31 inline namespace IGNITION_MATH_VERSION_NAMESPACE {
32 //
33 /// \class Capsule Capsule.hh ignition/math/Capsule.hh
34 /// \brief A representation of a capsule or sphere-capped cylinder.
35 ///
36 /// The capsule class supports defining a capsule with a radius,
37 /// length, and material properties. The shape is equivalent to a cylinder
38 /// aligned with the Z-axis and capped with hemispheres. Radius and
39 /// length are in meters. See Material for more on material properties.
40 /// \tparam Precision Scalar numeric type.
41 template<typename Precision>
42 class Capsule
43 {
44 /// \brief Default constructor. The default radius and length are both
45 /// zero.
46 public: Capsule() = default;
47
48 /// \brief Construct a capsule with a length and radius.
49 /// \param[in] _length Length of the capsule.
50 /// \param[in] _radius Radius of the capsule.
51 public: Capsule(const Precision _length, const Precision _radius);
52
53 /// \brief Construct a capsule with a length, radius, and material.
54 /// \param[in] _length Length of the capsule.
55 /// \param[in] _radius Radius of the capsule.
56 /// \param[in] _mat Material property for the capsule.
57 public: Capsule(const Precision _length, const Precision _radius,
58 const Material &_mat);
59
60 /// \brief Get the radius in meters.
61 /// \return The radius of the capsule in meters.
62 public: Precision Radius() const;
63
64 /// \brief Set the radius in meters.
65 /// \param[in] _radius The radius of the capsule in meters.
66 public: void SetRadius(const Precision _radius);
67
68 /// \brief Get the length in meters.
69 /// \return The length of the capsule in meters.
70 public: Precision Length() const;
71
72 /// \brief Set the length in meters.
73 /// \param[in] _length The length of the capsule in meters.
74 public: void SetLength(const Precision _length);
75
76 /// \brief Get the material associated with this capsule.
77 /// \return The material assigned to this capsule
78 public: const Material &Mat() const;
79
80 /// \brief Set the material associated with this capsule.
81 /// \param[in] _mat The material assigned to this capsule
82 public: void SetMat(const Material &_mat);
83
84 /// \brief Get the mass matrix for this capsule. This function
85 /// is only meaningful if the capsule's radius, length, and material
86 /// have been set.
87 /// \return The computed mass matrix if parameters are valid
88 /// (radius > 0), (length > 0), and (density > 0). Otherwise
89 /// std::nullopt is returned.
90 public: std::optional< MassMatrix3<Precision> > MassMatrix() const;
91
92 /// \brief Check if this capsule is equal to the provided capsule.
93 /// Radius, length, and material properties will be checked.
94 public: bool operator==(const Capsule &_capsule) const;
95
96 /// \brief Get the volume of the capsule in m^3.
97 /// \return Volume of the capsule in m^3.
98 public: Precision Volume() const;
99
100 /// \brief Compute the capsule's density given a mass value. The
101 /// capsule is assumed to be solid with uniform density. This
102 /// function requires the capsule's radius and length to be set to
103 /// values greater than zero. The Material of the capsule is ignored.
104 /// \param[in] _mass Mass of the capsule, in kg. This value should be
105 /// greater than zero.
106 /// \return Density of the capsule in kg/m^3. A NaN is returned
107 /// if radius, length or _mass is <= 0.
108 public: Precision DensityFromMass(const Precision _mass) const;
109
110 /// \brief Set the density of this capsule based on a mass value.
111 /// Density is computed using
112 /// Precision DensityFromMass(const Precision _mass) const. The
113 /// capsule is assumed to be solid with uniform density. This
114 /// function requires the capsule's radius and length to be set to
115 /// values greater than zero. The existing Material density value is
116 /// overwritten only if the return value from this true.
117 /// \param[in] _mass Mass of the capsule, in kg. This value should be
118 /// greater than zero.
119 /// \return True if the density was set. False is returned if the
120 /// capsule's radius, length, or the _mass value are <= 0.
121 /// \sa Precision DensityFromMass(const Precision _mass) const
122 public: bool SetDensityFromMass(const Precision _mass);
123
124 /// \brief Radius of the capsule.
125 private: Precision radius = 0.0;
126
127 /// \brief Length of the capsule.
128 private: Precision length = 0.0;
129
130 /// \brief the capsule's material.
131 private: Material material;
132 };
133
134 /// \typedef Capsule<int> Capsulei
135 /// \brief Capsule with integer precision.
136 typedef Capsule<int> Capsulei;
137
138 /// \typedef Capsule<double> Capsuled
139 /// \brief Capsule with double precision.
140 typedef Capsule<double> Capsuled;
141
142 /// \typedef Capsule<float> Capsulef
143 /// \brief Capsule with float precision.
144 typedef Capsule<float> Capsulef;
145 }
146 }
147 }
148 #include "ignition/math/detail/Capsule.hh"
149
150 #endif
1717 #define IGNITION_MATH_COLOR_HH_
1818
1919 #include <iostream>
20 #include <cctype>
2021
2122 #include <ignition/math/Helpers.hh>
2223 #include <ignition/math/Vector3.hh>
5152 /// \brief (0, 1, 1)
5253 public: static const Color Cyan;
5354
54 /// \def RGBA
55 /// \typedef RGBA
5556 /// \brief A RGBA packed value as an unsigned int
5657 public: typedef unsigned int RGBA;
5758
58 /// \def BGRA
59 /// \typedef BGRA
5960 /// \brief A BGRA packed value as an unsigned int
6061 public: typedef unsigned int BGRA;
6162
62 /// \def ARGB
63 /// \typedef ARGB
6364 /// \brief A ARGB packed value as an unsigned int
6465 public: typedef unsigned int ARGB;
6566
66 /// \def ABGR
67 /// \typedef ABGR
6768 /// \brief A ABGR packed value as an unsigned int
6869 public: typedef unsigned int ABGR;
6970
246247 }
247248
248249 /// \brief Stream insertion operator
249 /// \param[in] _in the input stream
250 /// \param[in] _in the input stream. If the input stream does not include
251 /// an alpha value, a default alpha value of 1.0 will be used.
250252 /// \param[in] _pt
251253 public: friend std::istream &operator>> (std::istream &_in, Color &_pt)
252254 {
253255 // Skip white spaces
254256 _in.setf(std::ios_base::skipws);
255 _in >> _pt.r >> _pt.g >> _pt.b >> _pt.a;
257 _in >> _pt.r >> _pt.g >> _pt.b;
258 // Since alpha is optional, check if it's there before parsing
259 while (!_in.eof() && std::isspace(_in.peek()))
260 {
261 _in.get();
262 }
263 if (!_in.eof())
264 {
265 _in >> _pt.a;
266 }
267 else
268 {
269 _pt.a = 1.0;
270 }
256271 return _in;
257272 }
258273
289304 public: float &A();
290305
291306 /// \brief Set the red value
292 /// \param _r New red value
307 /// \param[in] _r New red value
293308 public: void R(const float _r);
294309
295310 /// \brief Set the green value
296 /// \param _r New green value
311 /// \param[in] _g New green value
297312 public: void G(const float _g);
298313
299314 /// \brief Set the blue value
300 /// \param _r New blue value
315 /// \param[in] _b New blue value
301316 public: void B(const float _b);
302317
303318 /// \brief Set the alpha value
304 /// \param _r New alpha value
319 /// \param[in] _a New alpha value
305320 public: void A(const float _a);
306321
307322 /// \brief Red value
3131 inline namespace IGNITION_MATH_VERSION_NAMESPACE {
3232 //
3333 /// \class Cylinder Cylinder.hh ignition/math/Cylinder.hh
34 /// \brief A represntation of a cylinder.
34 /// \brief A representation of a cylinder.
3535 ///
3636 /// The cylinder class supports defining a cylinder with a radius,
3737 /// length, rotational offset, and material properties. Radius and
115115 /// \brief Get the mass matrix for this cylinder. This function
116116 /// is only meaningful if the cylinder's radius, length, and material
117117 /// have been set. Optionally, set the rotational offset.
118 /// \param[out] _massMatrix The computed mass matrix will be stored
118 /// \param[out] _massMat The computed mass matrix will be stored
119119 /// here.
120120 /// \return False if computation of the mass matrix failed, which
121121 /// could be due to an invalid radius (<=0), length (<=0), or density
9999 /// steerings position
100100 /// \param[in] _leftPos Left wheel position in radians.
101101 /// \param[in] _rightPos Right wheel postion in radians.
102 /// \param[in] _time Current time point.
102103 /// \return True if the odometry is actually updated.
103104 public: bool Update(const Angle &_leftPos, const Angle &_rightPos,
104105 const clock::time_point &_time);
7777 }
7878
7979 // Documentation Inherited.
80 public: virtual void Fc(double _fc, double _fs)
80 public: virtual void Fc(double _fc, double _fs) override
8181 {
8282 b1 = exp(-2.0 * IGN_PI * _fc / _fs);
8383 a0 = 1.0 - b1;
8484 }
8585
8686 /// \brief Update the filter's output.
87 /// \paran[in] _x Input value.
87 /// \param[in] _x Input value.
8888 /// \return The filter's current output.
8989 public: const T& Process(const T &_x)
9090 {
119119 }
120120
121121 /// \brief Update the filter's output.
122 /// \paran[in] _x Input value.
122 /// \param[in] _x Input value.
123123 /// \return The filter's current output.
124124 public: const math::Quaterniond& Process(
125125 const math::Quaterniond &_x)
167167 }
168168
169169 // Documentation Inherited.
170 public: void Fc(double _fc, double _fs)
170 public: void Fc(double _fc, double _fs) override
171171 {
172172 this->Fc(_fc, _fs, 0.5);
173173 }
190190
191191 /// \brief Set the current filter's output.
192192 /// \param[in] _val New filter's output.
193 public: virtual void Set(const T &_val)
193 public: virtual void Set(const T &_val) override
194194 {
195195 this->y0 = this->y1 = this->y2 = this->x1 = this->x2 = _val;
196196 }
168168 public: void SetPose(const Pose3d &_pose);
169169
170170 /// \brief Assignment operator. Set this frustum to the parameter.
171 /// \param[in] _b Frustum to copy
171 /// \param[in] _f Frustum to copy
172172 /// \return The new frustum.
173173 public: Frustum &operator=(const Frustum &_f);
174174
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16 #ifndef IGNITION_MATH_GAUSSMARKOVPROCESS_HH_
17 #define IGNITION_MATH_GAUSSMARKOVPROCESS_HH_
18
19 #include <chrono>
20 #include <memory>
21 #include <ignition/math/Export.hh>
22 #include <ignition/math/config.hh>
23
24 namespace ignition
25 {
26 namespace math
27 {
28 // Use a steady clock
29 using clock = std::chrono::steady_clock;
30
31 // Inline bracket to help doxygen filtering.
32 inline namespace IGNITION_MATH_VERSION_NAMESPACE {
33 //
34 // Forward declarations.
35 class GaussMarkovProcessPrivate;
36
37 /** \class GaussMarkovProcess GaussMarkovProcess.hh\
38 * ignition/math/GaussMarkovProcess.hh
39 **/
40 /// \brief Implementation of a stationary gauss-markov process, also
41 /// known as a Ornstein Ulenbeck process.
42 ///
43 /// See the Update(const clock::duration &) for details on the forumla
44 /// used to update the process.
45 ///
46 /// ## Example usage
47 ///
48 /// \snippet examples/gauss_markov_process_example.cc complete
49 class IGNITION_MATH_VISIBLE GaussMarkovProcess
50 {
51 // Default constructor. This sets all the parameters to zero.
52 public: GaussMarkovProcess();
53
54 /// \brief Create a process with the provided process parameters.
55 /// This will also call Set(), and in turn Reset().
56 /// \param[in] _start The start value of the process.
57 /// \param[in] _theta The theta (\f$\theta\f$) parameter. A value of
58 /// zero will be used if this parameter is negative.
59 /// \param[in] _mu The mu (\f$\mu\f$) parameter.
60 /// \param[in] _sigma The sigma (\f$\sigma\f$) parameter. A value of
61 /// zero will be used if this parameter is negative.
62 /// \sa Update(const clock::duration &)
63 public: GaussMarkovProcess(double _start, double _theta, double _mu,
64 double _sigma);
65
66 /// \brief Destructor.
67 public: ~GaussMarkovProcess();
68
69 /// \brief Set the process parameters. This will also call Reset().
70 /// \param[in] _start The start value of the process.
71 /// \param[in] _theta The theta (\f$\theta\f$) parameter.
72 /// \param[in] _mu The mu (\f$\mu\f$) parameter.
73 /// \param[in] _sigma The sigma (\f$\sigma\f$) parameter.
74 /// \sa Update(const clock::duration &)
75 public: void Set(double _start, double _theta, double _mu, double _sigma);
76
77 /// \brief Get the start value.
78 /// \return The start value.
79 /// \sa Set(double, double, double, double)
80 public: double Start() const;
81
82 /// \brief Get the current process value.
83 /// \return The value of the process.
84 public: double Value() const;
85
86 /// \brief Get the theta (\f$\theta\f$) value.
87 /// \return The theta value.
88 /// \sa Set(double, double, double, double)
89 public: double Theta() const;
90
91 /// \brief Get the mu (\f$\mu\f$) value.
92 /// \return The mu value.
93 /// \sa Set(double, double, double, double)
94 public: double Mu() const;
95
96 /// \brief Get the sigma (\f$\sigma\f$) value.
97 /// \return The sigma value.
98 /// \sa Set(double, double, double, double)
99 public: double Sigma() const;
100
101 /// \brief Reset the process. This will set the current process value
102 /// to the start value.
103 public: void Reset();
104
105 /// \brief Update the process and get the new value.
106 ///
107 /// The following equation is computed:
108 ///
109 /// \f$x_{t+1} += \theta * (\mu - x_t) * dt + \sigma * dW_t\f$
110 ///
111 /// where
112 ///
113 /// * \f$\theta, \mu, \sigma\f$ are parameters specified by the
114 /// user. In order, the parameters are theta, mu, and sigma. Theta
115 /// and sigma must be greater than or equal to zero. You can think
116 /// of mu as representing the mean or equilibrium value, sigma as the
117 /// degree of volatility, and theta as the rate by which changes
118 /// dissipate and revert towards the mean.
119 /// * \f$dt\f$ is the time step in seconds.
120 /// * \f$dW_t\f$ is a random number drawm from a normal distribution
121 /// with mean of zero and variance of 1.
122 /// * \f$x_t\f$ is the current value of the Gauss-Markov process
123 /// * \f$x_{t+1}\f$ is the new value of the Gauss-Markvov process
124 ///
125 /// See also: https://en.wikipedia.org/wiki/Ornstein%E2%80%93Uhlenbeck_process
126 ///
127 /// This implementation include a drift parameter, mu. In financial
128 /// mathematics, this is known as a Vasicek model.
129 ///
130 /// \param[in] _dt Length of the timestep after which a new sample
131 /// should be taken.
132 /// \return The new value of this process.
133 public: double Update(const clock::duration &_dt);
134
135 public: double Update(double _dt);
136
137 #ifdef _WIN32
138 // Disable warning C4251 which is triggered by
139 // std::unique_ptr
140 #pragma warning(push)
141 #pragma warning(disable: 4251)
142 #endif
143 /// \brief Private data pointer.
144 private: std::unique_ptr<GaussMarkovProcessPrivate> dataPtr;
145 #ifdef _WIN32
146 #pragma warning(pop)
147 #endif
148 };
149 }
150 }
151 }
152 #endif
1616 #ifndef IGNITION_MATH_FUNCTIONS_HH_
1717 #define IGNITION_MATH_FUNCTIONS_HH_
1818
19 #include <algorithm>
1920 #include <chrono>
2021 #include <cmath>
21 #include <algorithm>
22 #include <cstdint>
23 #include <iomanip>
24 #include <iostream>
2225 #include <limits>
26 #include <regex>
27 #include <sstream>
2328 #include <string>
24 #include <iostream>
25 #include <vector>
2629 #include <tuple>
2730 #include <utility>
28 #include <cstdint>
31 #include <vector>
2932
3033 #include <ignition/math/config.hh>
3134 #include "ignition/math/Export.hh"
726729 }
727730 }
728731
732 /// \brief Convert a std::chrono::steady_clock::time_point to a seconds and
733 /// nanoseconds pair.
734 /// \param[in] _time The time point to convert.
735 /// \return A pair where the first element is the number of seconds and
736 /// the second is the number of nanoseconds.
737 inline std::pair<int64_t, int64_t> timePointToSecNsec(
738 const std::chrono::steady_clock::time_point &_time)
739 {
740 auto now_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
741 _time.time_since_epoch());
742 auto now_s = std::chrono::duration_cast<std::chrono::seconds>(
743 _time.time_since_epoch());
744 int64_t seconds = now_s.count();
745 int64_t nanoseconds = std::chrono::duration_cast
746 <std::chrono::nanoseconds>(now_ns - now_s).count();
747 return {seconds, nanoseconds};
748 }
749
750 /// \brief Convert seconds and nanoseconds to
751 /// std::chrono::steady_clock::time_point.
752 /// \param[in] _sec The seconds to convert.
753 /// \param[in] _nanosec The nanoseconds to convert.
754 /// \return A std::chrono::steady_clock::time_point based on the number of
755 /// seconds and the number of nanoseconds.
756 inline std::chrono::steady_clock::time_point secNsecToTimePoint(
757 const uint64_t &_sec, const uint64_t &_nanosec)
758 {
759 auto duration = std::chrono::seconds(_sec) + std::chrono::nanoseconds(
760 _nanosec);
761 std::chrono::steady_clock::time_point result;
762 using std::chrono::duration_cast;
763 result += duration_cast<std::chrono::steady_clock::duration>(duration);
764 return result;
765 }
766
767 /// \brief Convert seconds and nanoseconds to
768 /// std::chrono::steady_clock::duration.
769 /// \param[in] _sec The seconds to convert.
770 /// \param[in] _nanosec The nanoseconds to convert.
771 /// \return A std::chrono::steady_clock::duration based on the number of
772 /// seconds and the number of nanoseconds.
773 inline std::chrono::steady_clock::duration secNsecToDuration(
774 const uint64_t &_sec, const uint64_t &_nanosec)
775 {
776 return std::chrono::seconds(_sec) + std::chrono::nanoseconds(
777 _nanosec);
778 }
779
729780 /// \brief Convert a std::chrono::steady_clock::duration to a seconds and
730781 /// nanoseconds pair.
731782 /// \param[in] _dur The duration to convert.
737788 auto s = std::chrono::duration_cast<std::chrono::seconds>(_dur);
738789 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(_dur-s);
739790 return {s.count(), ns.count()};
791 }
792
793 // TODO(anyone): Replace this with std::chrono::days.
794 /// This will exist in C++-20
795 typedef std::chrono::duration<uint64_t, std::ratio<86400>> days;
796
797 /// \brief break down durations
798 /// NOTE: the template arguments must be properly ordered according
799 /// to magnitude and there can be no duplicates.
800 /// This function uses the braces initializer to split all the templated
801 /// duration. The initializer will be called recursievely due the `...`
802 /// \param[in] d Duration to break down
803 /// \return A tuple based on the durations specified
804 template<class...Durations, class DurationIn>
805 std::tuple<Durations...> breakDownDurations(DurationIn d) {
806 std::tuple<Durations...> retval;
807 using discard = int[];
808 (void)discard{0, (void((
809 (std::get<Durations>(retval) =
810 std::chrono::duration_cast<Durations>(d)),
811 (d -= std::chrono::duration_cast<DurationIn>(
812 std::get<Durations>(retval))))), 0)...};
813 return retval;
814 }
815
816 /// \brief Convert a std::chrono::steady_clock::time_point to a string
817 /// \param[in] _point The std::chrono::steady_clock::time_point to convert.
818 /// \return A string formatted with the time_point
819 inline std::string timePointToString(
820 const std::chrono::steady_clock::time_point &_point)
821 {
822 auto duration = _point - secNsecToTimePoint(0, 0);
823 auto cleanDuration = breakDownDurations<days,
824 std::chrono::hours,
825 std::chrono::minutes,
826 std::chrono::seconds,
827 std::chrono::milliseconds>(
828 duration);
829 std::ostringstream output_string;
830 output_string << std::setw(2) << std::setfill('0')
831 << std::get<0>(cleanDuration).count() << " "
832 << std::setw(2) << std::setfill('0')
833 << std::get<1>(cleanDuration).count() << ":"
834 << std::setw(2) << std::setfill('0')
835 << std::get<2>(cleanDuration).count() << ":"
836 << std::setfill('0') << std::setw(6)
837 << std::fixed << std::setprecision(3)
838 << std::get<3>(cleanDuration).count() +
839 std::get<4>(cleanDuration).count()/1000.0;
840 return output_string.str();
841 }
842
843 /// \brief Convert a std::chrono::steady_clock::duration to a string
844 /// \param[in] _duration The std::chrono::steady_clock::duration to convert.
845 /// \return A string formatted with the duration
846 inline std::string durationToString(
847 const std::chrono::steady_clock::duration &_duration)
848 {
849 auto cleanDuration = breakDownDurations<days,
850 std::chrono::hours,
851 std::chrono::minutes,
852 std::chrono::seconds,
853 std::chrono::milliseconds>(
854 _duration);
855 std::ostringstream outputString;
856 outputString << std::setw(2) << std::setfill('0')
857 << std::get<0>(cleanDuration).count() << " "
858 << std::setw(2) << std::setfill('0')
859 << std::get<1>(cleanDuration).count() << ":"
860 << std::setw(2) << std::setfill('0')
861 << std::get<2>(cleanDuration).count() << ":"
862 << std::setfill('0') << std::setw(6)
863 << std::fixed << std::setprecision(3)
864 << std::get<3>(cleanDuration).count() +
865 std::get<4>(cleanDuration).count()/1000.0;
866 return outputString.str();
867 }
868
869 // The following regex takes a time string in the general format of
870 // "dd hh:mm:ss.nnn" where n is milliseconds, if just one number is
871 // provided, it is assumed to be seconds
872 static const std::regex time_regex(
873 "^([0-9]+ ){0,1}" // day:
874 // Any positive integer
875
876 "(?:([1-9]:|[0-1][0-9]:|2[0-3]:){0,1}" // hour:
877 // 1 - 9:
878 // 01 - 19:
879 // 20 - 23:
880
881 "([0-9]:|[0-5][0-9]:)){0,1}" // minute:
882 // 0 - 9:
883 // 00 - 59:
884
885 "(?:([0-9]|[0-5][0-9]){0,1}" // second:
886 // 0 - 9
887 // 00 - 59
888
889 "(\\.[0-9]{1,3}){0,1})$"); // millisecond:
890 // .0 - .9
891 // .00 - .99
892 // .000 - 0.999
893
894
895 /// \brief Split a std::chrono::steady_clock::duration to a string
896 /// \param[in] _timeString The string to convert in general format
897 /// \param[out] numberDays number of days in the string
898 /// \param[out] numberHours number of hours in the string
899 /// \param[out] numberMinutes number of minutes in the string
900 /// \param[out] numberSeconds number of seconds in the string
901 /// \param[out] numberMilliseconds number of milliseconds in the string
902 /// \return True if the regex was able to split the string otherwise False
903 inline bool splitTimeBasedOnTimeRegex(
904 const std::string &_timeString,
905 uint64_t & numberDays, uint64_t & numberHours,
906 uint64_t & numberMinutes, uint64_t & numberSeconds,
907 uint64_t & numberMilliseconds)
908 {
909 std::smatch matches;
910
911 // `matches` should always be a size of 6 as there are 6 matching
912 // groups in the regex.
913 // 1. The whole regex
914 // 2. The days
915 // 3. The hours
916 // 4. The minutes
917 // 5. The seconds
918 // 6. The milliseconds
919 // We can also index them as such below.
920 // Note that the space will remain in the day match, the colon
921 // will remain in the hour and minute matches, and the period will
922 // remain in the millisecond match
923 if (!std::regex_search(_timeString, matches, time_regex) ||
924 matches.size() != 6)
925 return false;
926
927 std::string dayString = matches[1];
928 std::string hourString = matches[2];
929 std::string minuteString = matches[3];
930 std::string secondString = matches[4];
931 std::string millisecondString = matches[5];
932
933 // Days are the only unbounded number, so check first to see if stoi
934 // runs successfully
935 if (!dayString.empty())
936 {
937 // Erase the space
938 dayString.erase(dayString.length() - 1);
939 try
940 {
941 numberDays = std::stoi(dayString);
942 }
943 catch (const std::out_of_range &)
944 {
945 return false;
946 }
947 }
948
949 if (!hourString.empty())
950 {
951 // Erase the colon
952 hourString.erase(hourString.length() - 1);
953 numberHours = std::stoi(hourString);
954 }
955
956 if (!minuteString.empty())
957 {
958 // Erase the colon
959 minuteString.erase(minuteString.length() - 1);
960 numberMinutes = std::stoi(minuteString);
961 }
962
963 if (!secondString.empty())
964 {
965 numberSeconds = std::stoi(secondString);
966 }
967
968 if (!millisecondString.empty())
969 {
970 // Erase the period
971 millisecondString.erase(0, 1);
972
973 // Multiplier because "4" = 400 ms, "04" = 40 ms, and "004" = 4 ms
974 numberMilliseconds = std::stoi(millisecondString) *
975 static_cast<uint64_t>(1000 / pow(10, millisecondString.length()));
976 }
977 return true;
978 }
979
980 /// \brief Convert a string to a std::chrono::steady_clock::duration
981 /// \param[in] _timeString The string to convert in general format
982 /// "dd hh:mm:ss.nnn" where n is millisecond value
983 /// \return A std::chrono::steady_clock::duration containing the
984 /// string's time value. If it isn't possible to convert, the duration will
985 /// be zero.
986 inline std::chrono::steady_clock::duration stringToDuration(
987 const std::string &_timeString)
988 {
989 using namespace std::chrono_literals;
990 std::chrono::steady_clock::duration duration{
991 std::chrono::steady_clock::duration::zero()};
992
993 if (_timeString.empty())
994 return duration;
995
996 uint64_t numberDays = 0;
997 uint64_t numberHours = 0;
998 uint64_t numberMinutes = 0;
999 uint64_t numberSeconds = 0;
1000 uint64_t numberMilliseconds = 0;
1001
1002 if (!splitTimeBasedOnTimeRegex(_timeString, numberDays, numberHours,
1003 numberMinutes, numberSeconds,
1004 numberMilliseconds))
1005 {
1006 return duration;
1007 }
1008
1009 // TODO(anyone): Replace below day conversion with std::chrono::days.
1010 /// This will exist in C++-20
1011 duration = std::chrono::steady_clock::duration::zero();
1012 auto delta = std::chrono::milliseconds(numberMilliseconds) +
1013 std::chrono::seconds(numberSeconds) +
1014 std::chrono::minutes(numberMinutes) +
1015 std::chrono::hours(numberHours) +
1016 std::chrono::hours(24 * numberDays);
1017 duration += delta;
1018
1019 return duration;
1020 }
1021
1022 /// \brief Convert a string to a std::chrono::steady_clock::time_point
1023 /// \param[in] _timeString The string to convert in general format
1024 /// "dd hh:mm:ss.nnn" where n is millisecond value
1025 /// \return A std::chrono::steady_clock::time_point containing the
1026 /// string's time value. If it isn't possible to convert, the time will
1027 /// be negative 1 second.
1028 inline std::chrono::steady_clock::time_point stringToTimePoint(
1029 const std::string &_timeString)
1030 {
1031 using namespace std::chrono_literals;
1032 std::chrono::steady_clock::time_point timePoint{-1s};
1033
1034 if (_timeString.empty())
1035 return timePoint;
1036
1037 uint64_t numberDays = 0;
1038 uint64_t numberHours = 0;
1039 uint64_t numberMinutes = 0;
1040 uint64_t numberSeconds = 0;
1041 uint64_t numberMilliseconds = 0;
1042
1043 if (!splitTimeBasedOnTimeRegex(_timeString, numberDays, numberHours,
1044 numberMinutes, numberSeconds,
1045 numberMilliseconds))
1046 {
1047 return timePoint;
1048 }
1049
1050 // TODO(anyone): Replace below day conversion with std::chrono::days.
1051 /// This will exist in C++-20
1052 timePoint = math::secNsecToTimePoint(0, 0);
1053 auto duration = std::chrono::milliseconds(numberMilliseconds) +
1054 std::chrono::seconds(numberSeconds) +
1055 std::chrono::minutes(numberMinutes) +
1056 std::chrono::hours(numberHours) +
1057 std::chrono::hours(24 * numberDays);
1058 timePoint += duration;
1059
1060 return timePoint;
7401061 }
7411062
7421063 // Degrade precision on Windows, which cannot handle 'long double'
237237 ixxyyzz.X() += m1 * (std::pow(dc[1], 2) + std::pow(dc[2], 2));
238238 ixxyyzz.Y() += m1 * (std::pow(dc[2], 2) + std::pow(dc[0], 2));
239239 ixxyyzz.Z() += m1 * (std::pow(dc[0], 2) + std::pow(dc[1], 2));
240 ixxyyzz.X() -= m1 * dc[0] * dc[1];
241 ixxyyzz.Y() -= m1 * dc[0] * dc[2];
242 ixxyyzz.Z() -= m1 * dc[1] * dc[2];
240 ixyxzyz.X() -= m1 * dc[0] * dc[1];
241 ixyxzyz.Y() -= m1 * dc[0] * dc[2];
242 ixyxzyz.Z() -= m1 * dc[1] * dc[2];
243243 }
244244 {
245245 auto dc = com2 - com;
246246 ixxyyzz.X() += m2 * (std::pow(dc[1], 2) + std::pow(dc[2], 2));
247247 ixxyyzz.Y() += m2 * (std::pow(dc[2], 2) + std::pow(dc[0], 2));
248248 ixxyyzz.Z() += m2 * (std::pow(dc[0], 2) + std::pow(dc[1], 2));
249 ixxyyzz.X() -= m2 * dc[0] * dc[1];
250 ixxyyzz.Y() -= m2 * dc[0] * dc[2];
251 ixxyyzz.Z() -= m2 * dc[1] * dc[2];
249 ixyxzyz.X() -= m2 * dc[0] * dc[1];
250 ixyxzyz.Y() -= m2 * dc[0] * dc[2];
251 ixyxzyz.Z() -= m2 * dc[1] * dc[2];
252252 }
253253 this->massMatrix = MassMatrix3<T>(mass, ixxyyzz, ixyxzyz);
254254 this->pose = Pose3<T>(com, Quaternion<T>::Identity);
297297
298298 /// \brief Stream extraction operator
299299 /// \param[in] _out output stream
300 /// \param[in] _pt Line2 to output
300 /// \param[in] _line Line2 to output
301301 /// \return The stream
302302 public: friend std::ostream &operator<<(
303303 std::ostream &_out, const Line2<T> &_line)
153153 /// point of this line and the closest point in the provided line.
154154 /// \param[in] _line Line to compare against this.
155155 /// \param[out] _result The shortest line between _line and this.
156 /// \param[in] _epsilon Error tolerance.
156157 /// \return True if a solution was found. False if a solution is not
157158 /// possible.
158159 public: bool Distance(const Line3<T> &_line, Line3<T> &_result,
5959 {}
6060
6161 /// \brief Copy constructor.
62 /// \param[in] _massMatrix MassMatrix3 element to copy
62 /// \param[in] _m MassMatrix3 element to copy
6363 public: MassMatrix3(const MassMatrix3<T> &_m)
6464 : mass(_m.Mass()), Ixxyyzz(_m.DiagonalMoments()),
6565 Ixyxzyz(_m.OffDiagonalMoments())
173173 /// \brief Set the off-diagonal moments of inertia (Ixy, Ixz, Iyz).
174174 /// \param[in] _ixyxzyz off-diagonal moments of inertia
175175 /// \return True if the MassMatrix3 is valid.
176 /// \deprecated See bool SetOffDiagonalMoments(const Vector3<T> &_ixyxzyz)
177176 public: bool SetOffDiagonalMoments(const Vector3<T> &_ixyxzyz)
178177 {
179178 this->Ixyxzyz = _ixyxzyz;
399398 /// \brief Sets Moments of Inertia (MOI) from a Matrix3.
400399 /// Symmetric component of input matrix is used by averaging
401400 /// off-axis terms.
402 /// \param[in] Moments of Inertia as a Matrix3
401 /// \param[in] _moi Moments of Inertia as a Matrix3
403402 /// \return True if the MassMatrix3 is valid.
404403 /// \deprecated See SetMoi(const Matrix3<T> &_moi)
405404 public: bool IGN_DEPRECATED(5.0) MOI(const Matrix3<T> &_moi)
410409 /// \brief Sets Moments of Inertia (MOI) from a Matrix3.
411410 /// Symmetric component of input matrix is used by averaging
412411 /// off-axis terms.
413 /// \param[in] Moments of Inertia as a Matrix3
412 /// \param[in] _moi Moments of Inertia as a Matrix3
414413 /// \return True if the MassMatrix3 is valid.
415414 public: bool SetMoi(const Matrix3<T> &_moi)
416415 {
984983 + std::pow(cos(phi11c.Radian()) - cos(phi12c.Radian()), 2);
985984 if (errc < err)
986985 {
987 err = errc;
988986 phi1 = phi11c.Radian();
989987 signsPhi23.Set(-1, -1);
990988 }
10701068 const Quaternion<T> &_rot = Quaternion<T>::Identity)
10711069 {
10721070 // Check that _mass and _size are strictly positive
1073 // and that quatenion is valid
1071 // and that quaternion is valid
10741072 if (_mass <= 0 || _size.Min() <= 0 || _rot == Quaternion<T>::Zero)
10751073 {
10761074 return false;
10881086 const Quaternion<T> &_rot = Quaternion<T>::Identity)
10891087 {
10901088 // Check that _mass and _size are strictly positive
1091 // and that quatenion is valid
1089 // and that quaternion is valid
10921090 if (this->Mass() <= 0 || _size.Min() <= 0 ||
10931091 _rot == Quaternion<T>::Zero)
10941092 {
11211119 const Quaternion<T> &_rot = Quaternion<T>::Identity)
11221120 {
11231121 // Check that density, _radius and _length are strictly positive
1124 // and that quatenion is valid
1122 // and that quaternion is valid
11251123 if (_mat.Density() <= 0 || _length <= 0 || _radius <= 0 ||
11261124 _rot == Quaternion<T>::Zero)
11271125 {
11451143 const Quaternion<T> &_rot = Quaternion<T>::Identity)
11461144 {
11471145 // Check that _mass, _radius and _length are strictly positive
1148 // and that quatenion is valid
1146 // and that quaternion is valid
11491147 if (_mass <= 0 || _length <= 0 || _radius <= 0 ||
11501148 _rot == Quaternion<T>::Zero)
11511149 {
11661164 const Quaternion<T> &_rot)
11671165 {
11681166 // Check that _mass and _size are strictly positive
1169 // and that quatenion is valid
1167 // and that quaternion is valid
11701168 if (this->Mass() <= 0 || _length <= 0 || _radius <= 0 ||
11711169 _rot == Quaternion<T>::Zero)
11721170 {
4040 /// enum.
4141 ///
4242 /// This class will replace the
43 /// [MaterialDensity class](https://bitbucket.org/ignitionrobotics/ign-common/src/ign-common1/include/ignition/common/MaterialDensity.hh)
43 /// [MaterialDensity class](https://github.com/ignitionrobotics/ign-common/blob/ign-common1/include/ignition/common/MaterialDensity.hh)
4444 /// found in the Ignition Common library, which was at version 1 at the
4545 /// time of this writing.
4646 ///
503503
504504 return _out;
505505 }
506
506507 /// \brief Stream extraction operator
507 /// \param _in input stream
508 /// \param _pt Matrix3 to read values into
508 /// \param[in,out] _in input stream
509 /// \param[out] _m Matrix3 to read values into
509510 /// \return the stream
510511 public: friend std::istream &operator>>(
511512 std::istream &_in, ignition::math::Matrix3<T> &_m)
621621
622622 /// \brief Multiplication assignment operator. This matrix will
623623 /// become equal to this * _m2.
624 /// \param _mat Incoming matrix.
624 /// \param[in] _m2 Incoming matrix.
625625 /// \return This matrix * _mat.
626626 public: Matrix4<T> operator*=(const Matrix4<T> &_m2)
627627 {
630630 }
631631
632632 /// \brief Multiplication operator
633 /// \param _mat Incoming matrix
633 /// \param[in] _m2 Incoming matrix
634634 /// \return This matrix * _mat
635635 public: Matrix4<T> operator*(const Matrix4<T> &_m2) const
636636 {
826826 }
827827
828828 /// \brief Stream extraction operator
829 /// \param _in input stream
830 /// \param _pt Matrix4<T> to read values into
829 /// \param[in,out] _in input stream
830 /// \param[out] _m Matrix4<T> to read values into
831831 /// \return the stream
832832 public: friend std::istream &operator>>(
833833 std::istream &_in, ignition::math::Matrix4<T> &_m)
5252 /// \brief keep track of number of elements
5353 public: unsigned int samples = 0;
5454 };
55 /// \endcond
5655
5756 //////////////////////////////////////////////////
5857 template<typename T>
6362 this->valIter = this->valHistory.begin();
6463 this->sum = T();
6564 }
65 /// \endcond
6666
6767 /// \brief Base class for MovingWindowFilter. This replaces the
6868 /// version of MovingWindowFilter in the Ignition Common library.
212212 return this->p != _pose.p || this->q != _pose.q;
213213 }
214214
215 /// \brief Multiplication operator
216 /// \param[in] _pose the other pose
217 /// \return itself
215 /// \brief Multiplication operator.
216 /// Given X_OP (frame P relative to O) and X_PQ (frame Q relative to P)
217 /// then X_OQ = X_OP * X_PQ (frame Q relative to O).
218 /// \param[in] _pose The pose to multiply by.
219 /// \return The resulting pose.
218220 public: Pose3<T> operator*(const Pose3<T> &_pose) const
219221 {
220222 return Pose3<T>(_pose.CoordPositionAdd(*this), this->q * _pose.q);
230232 return *this;
231233 }
232234
233 /// \brief Equal operator
235 /// \brief Assignment operator
234236 /// \param[in] _pose Pose3<T> to copy
235237 public: Pose3<T> &operator=(const Pose3<T> &_pose)
236238 {
328330 }
329331
330332 /// \brief Rotate vector part of a pose about the origin
331 /// \param[in] _rot rotation
333 /// \param[in] _q rotation
332334 /// \return the rotated pose
333335 public: Pose3<T> RotatePositionAboutOrigin(const Quaternion<T> &_q) const
334336 {
367369 return this->p;
368370 }
369371
372 /// \brief Get the X value of the position.
373 /// \return Value X of the origin of the pose.
374 /// \note The return is made by value since
375 /// Vector3<T>.X() is already a reference.
376 public: inline const T X() const
377 {
378 return this->p.X();
379 }
380
381 /// \brief Set X value of the position.
382 public: inline void SetX(T x)
383 {
384 this->p.X() = x;
385 }
386
387 /// \brief Get the Y value of the position.
388 /// \return Value Y of the origin of the pose.
389 /// \note The return is made by value since
390 /// Vector3<T>.Y() is already a reference.
391 public: inline const T Y() const
392 {
393 return this->p.Y();
394 }
395
396 /// \brief Set the Y value of the position.
397 public: inline void SetY(T y)
398 {
399 this->p.Y() = y;
400 }
401
402 /// \brief Get the Z value of the position.
403 /// \return Value Z of the origin of the pose.
404 /// \note The return is made by value since
405 /// Vector3<T>.Z() is already a reference.
406 public: inline const T Z() const
407 {
408 return this->p.Z();
409 }
410
411 /// \brief Set the Z value of the position.
412 public: inline void SetZ(T z)
413 {
414 this->p.Z() = z;
415 }
416
370417 /// \brief Get the rotation.
371418 /// \return Quaternion representation of the rotation.
372419 public: inline const Quaternion<T> &Rot() const
379426 public: inline Quaternion<T> &Rot()
380427 {
381428 return this->q;
429 }
430
431 /// \brief Get the Roll value of the rotation.
432 /// \return Roll value of the orientation.
433 /// \note The return is made by value since
434 /// Quaternion<T>.Roll() is already a reference.
435 public: inline const T Roll() const
436 {
437 return this->q.Roll();
438 }
439
440 /// \brief Get the Pitch value of the rotation.
441 /// \return Pitch value of the orientation.
442 /// \note The return is made by value since
443 /// Quaternion<T>.Pitch() is already a reference.
444 public: inline const T Pitch() const
445 {
446 return this->q.Pitch();
447 }
448
449 /// \brief Get the Yaw value of the rotation.
450 /// \return Yaw value of the orientation.
451 /// \note The return is made by value since
452 /// Quaternion<T>.Yaw() is already a reference.
453 public: inline const T Yaw() const
454 {
455 return this->q.Yaw();
382456 }
383457
384458 /// \brief Stream insertion operator
104104 /// \brief Destructor
105105 public: ~Quaternion() {}
106106
107 /// \brief Equal operator
107 /// \brief Assignment operator
108108 /// \param[in] _qt Quaternion<T> to copy
109109 public: Quaternion<T> &operator=(const Quaternion<T> &_qt)
110110 {
243243 }
244244 }
245245
246 /// \brief Gets a normalized version of this quaternion
247 /// \return a normalized quaternion
248 public: Quaternion<T> Normalized() const
249 {
250 Quaternion<T> result = *this;
251 result.Normalize();
252 return result;
253 }
254
246255 /// \brief Set the quaternion from an axis and angle
247 /// \param[in] _x X axis
248 /// \param[in] _y Y axis
249 /// \param[in] _z Z axis
250 /// \param[in] _a Angle in radians
256 /// \param[in] _ax X axis
257 /// \param[in] _ay Y axis
258 /// \param[in] _az Z axis
259 /// \param[in] _aa Angle in radians
251260 public: void Axis(T _ax, T _ay, T _az, T _aa)
252261 {
253262 T l;
283292 }
284293
285294 /// \brief Set this quaternion from 4 floating numbers
286 /// \param[in] _u u
295 /// \param[in] _w w
287296 /// \param[in] _x x
288297 /// \param[in] _y y
289298 /// \param[in] _z z
658667 /// \brief Multiplication operator
659668 /// \param[in] _qt Quaternion<T> for multiplication
660669 /// \return This quaternion multiplied by the parameter
661 public: Quaternion<T> operator*=(const Quaternion<T> &qt)
662 {
663 *this = *this * qt;
670 public: Quaternion<T> operator*=(const Quaternion<T> &_qt)
671 {
672 *this = *this * _qt;
664673 return *this;
665674 }
666675
838847
839848 /// \brief Spherical quadratic interpolation
840849 /// given the ends and an interpolation parameter between 0 and 1
841 /// \param[in] _ft the interpolation parameter
850 /// \param[in] _fT the interpolation parameter
842851 /// \param[in] _rkP the beginning quaternion
843852 /// \param[in] _rkA first intermediate quaternion
844853 /// \param[in] _rkB second intermediate quaternion
859868
860869 /// \brief Spherical linear interpolation between 2 quaternions,
861870 /// given the ends and an interpolation parameter between 0 and 1
862 /// \param[in] _ft the interpolation parameter
871 /// \param[in] _fT the interpolation parameter
863872 /// \param[in] _rkP the beginning quaternion
864873 /// \param[in] _rkQ the end quaternion
865874 /// \param[in] _shortestPath when true, the rotation may be inverted to
7474 /// \brief Parse a version string and set the major, minor, patch
7575 /// numbers, and prerelease and build strings.
7676 /// \param[in] _versionStr The version string, such as "1.2.3-pr+123"
77 /// \retur True on success.
77 /// \return True on success.
7878 public: bool Parse(const std::string &_versionStr);
7979
8080 /// \brief Returns the version as a string
8484 class IGNITION_MATH_VISIBLE SignalMaximum : public SignalStatistic
8585 {
8686 // Documentation inherited.
87 public: virtual double Value() const;
87 public: virtual double Value() const override;
8888
8989 /// \brief Get a short version of the name of this statistical measure.
9090 /// \return "max"
91 public: virtual std::string ShortName() const;
92
93 // Documentation inherited.
94 public: virtual void InsertData(const double _data);
91 public: virtual std::string ShortName() const override;
92
93 // Documentation inherited.
94 public: virtual void InsertData(const double _data) override;
9595 };
9696 /// \}
9797
100100 class IGNITION_MATH_VISIBLE SignalMean : public SignalStatistic
101101 {
102102 // Documentation inherited.
103 public: virtual double Value() const;
103 public: virtual double Value() const override;
104104
105105 /// \brief Get a short version of the name of this statistical measure.
106106 /// \return "mean"
107 public: virtual std::string ShortName() const;
108
109 // Documentation inherited.
110 public: virtual void InsertData(const double _data);
107 public: virtual std::string ShortName() const override;
108
109 // Documentation inherited.
110 public: virtual void InsertData(const double _data) override;
111111 };
112112 /// \}
113113
116116 class IGNITION_MATH_VISIBLE SignalMinimum : public SignalStatistic
117117 {
118118 // Documentation inherited.
119 public: virtual double Value() const;
119 public: virtual double Value() const override;
120120
121121 /// \brief Get a short version of the name of this statistical measure.
122122 /// \return "min"
123 public: virtual std::string ShortName() const;
124
125 // Documentation inherited.
126 public: virtual void InsertData(const double _data);
123 public: virtual std::string ShortName() const override;
124
125 // Documentation inherited.
126 public: virtual void InsertData(const double _data) override;
127127 };
128128 /// \}
129129
133133 class IGNITION_MATH_VISIBLE SignalRootMeanSquare : public SignalStatistic
134134 {
135135 // Documentation inherited.
136 public: virtual double Value() const;
136 public: virtual double Value() const override;
137137
138138 /// \brief Get a short version of the name of this statistical measure.
139139 /// \return "rms"
140 public: virtual std::string ShortName() const;
141
142 // Documentation inherited.
143 public: virtual void InsertData(const double _data);
140 public: virtual std::string ShortName() const override;
141
142 // Documentation inherited.
143 public: virtual void InsertData(const double _data) override;
144144 };
145145 /// \}
146146
152152 class IGNITION_MATH_VISIBLE SignalMaxAbsoluteValue : public SignalStatistic
153153 {
154154 // Documentation inherited.
155 public: virtual double Value() const;
155 public: virtual double Value() const override;
156156
157157 /// \brief Get a short version of the name of this statistical measure.
158158 /// \return "maxAbs"
159 public: virtual std::string ShortName() const;
160
161 // Documentation inherited.
162 public: virtual void InsertData(const double _data);
159 public: virtual std::string ShortName() const override;
160
161 // Documentation inherited.
162 public: virtual void InsertData(const double _data) override;
163163 };
164164 /// \}
165165
169169 class IGNITION_MATH_VISIBLE SignalVariance : public SignalStatistic
170170 {
171171 // Documentation inherited.
172 public: virtual double Value() const;
172 public: virtual double Value() const override;
173173
174174 /// \brief Get a short version of the name of this statistical measure.
175175 /// \return "var"
176 public: virtual std::string ShortName() const;
177
178 // Documentation inherited.
179 public: virtual void InsertData(const double _data);
176 public: virtual std::string ShortName() const override;
177
178 // Documentation inherited.
179 public: virtual void InsertData(const double _data) override;
180180 };
181181 /// \}
182182
238238 public: void Reset();
239239
240240 /// \brief Assignment operator
241 /// \param[in] _v A SignalStats to copy
241 /// \param[in] _s A SignalStats to copy
242242 /// \return this
243243 public: SignalStats &operator=(const SignalStats &_s);
244244
7272
7373 /// \brief Get the mass matrix for this sphere. This function
7474 /// is only meaningful if the sphere's radius and material have been set.
75 /// \param[out] _massMatrix The computed mass matrix will be stored
75 /// \param[out] _massMat The computed mass matrix will be stored
7676 /// here.
7777 /// \return False if computation of the mass matrix failed, which
7878 /// could be due to an invalid radius (<=0) or density (<=0).
114114 /// Example: _latA = 38.0016667 and _lonA = -123.0016667) represents
115115 /// the point with latitude 38d 0'6.00"N and longitude 123d 0'6.00"W.
116116 /// \param[in] _latA Latitude of point A.
117 /// \param[in] _longA Longitude of point A.
117 /// \param[in] _lonA Longitude of point A.
118118 /// \param[in] _latB Latitude of point B.
119 /// \param[in] _longB Longitude of point B.
119 /// \param[in] _lonB Longitude of point B.
120120 /// \return Distance in meters.
121121 public: static double Distance(const ignition::math::Angle &_latA,
122122 const ignition::math::Angle &_lonA,
173173
174174 /// \brief Convert a Cartesian velocity vector with components East,
175175 /// North, Up to a local cartesian frame vector XYZ.
176 /// \param[in] Vector with components (x,y,z): (East, North, Up).
176 /// \param[in] _xyz Vector with components (x,y,z): (East, North, Up).
177177 /// \return Cartesian vector in the world frame.
178178 public: ignition::math::Vector3d LocalFromGlobalVelocity(
179179 const ignition::math::Vector3d &_xyz) const;
197197 /// \brief Interpolates the mth derivative of the spline at
198198 /// parameter value \p _t.
199199 /// \param[in] _mth order of curve derivative to interpolate.
200 /// \param[in] _t parameter value (range 0 to 1).
200 /// \param[in] _1 parameter value (range 0 to 1).
201201 /// \return the interpolated mth derivative, or [INF, INF, INF]
202202 /// on error. Use Vector3d::IsFinite() to check for an error.
203203 public: Vector3d InterpolateMthDerivative(const unsigned int _mth,
210210 /// \param[in] _fromIndex point index to treat as t = 0, fromIndex + 1
211211 /// is deemed to be t = 1.
212212 /// \param[in] _mth order of curve derivative to interpolate.
213 /// \param[in] _t parameter value (range 0 to 1).
213 /// \param[in] _s parameter value (range 0 to 1).
214214 /// \return the interpolated mth derivative, or [INF, INF, INF] on
215215 /// error. Use Vector3d::IsFinite() to check for an error.
216216 public: Vector3d InterpolateMthDerivative(const unsigned int _fromIndex,
1616 #ifndef IGNITION_MATH_VECTOR2_HH_
1717 #define IGNITION_MATH_VECTOR2_HH_
1818
19 #include <algorithm>
20
1921 #include <ignition/math/Helpers.hh>
2022 #include <ignition/math/config.hh>
2123
6466 /// \brief Destructor
6567 public: virtual ~Vector2() {}
6668
69 /// \brief Return the sum of the values
70 /// \return the sum
71 public: T Sum() const
72 {
73 return this->data[0] + this->data[1];
74 }
75
6776 /// \brief Calc distance to the given point
6877 /// \param[in] _pt The point to measure to
6978 /// \return the distance
100109 }
101110 }
102111
112 /// \brief Returns a normalized vector
113 /// \return unit length vector
114 public: Vector2 Normalized() const
115 {
116 Vector2<T> result = *this;
117 result.Normalize();
118 return result;
119 }
120
121 /// \brief Round to near whole number, return the result.
122 /// \return the result
123 public: Vector2 Round()
124 {
125 this->data[0] = nearbyint(this->data[0]);
126 this->data[1] = nearbyint(this->data[1]);
127 return *this;
128 }
129
130 /// \brief Get a rounded version of this vector
131 /// \return a rounded vector
132 public: Vector2 Rounded() const
133 {
134 Vector2<T> result = *this;
135 result.Round();
136 return result;
137 }
138
103139 /// \brief Set the contents of the vector
104140 /// \param[in] _x value along x
105141 /// \param[in] _y value along y
115151 public: T Dot(const Vector2<T> &_v) const
116152 {
117153 return (this->data[0] * _v[0]) + (this->data[1] * _v[1]);
154 }
155
156 /// \brief Get the absolute value of the vector
157 /// \return a vector with positive elements
158 public: Vector2 Abs() const
159 {
160 return Vector2(std::abs(this->data[0]),
161 std::abs(this->data[1]));
162 }
163
164 /// \brief Return the absolute dot product of this vector and
165 /// another vector. This is similar to the Dot function, except the
166 /// absolute value of each component of the vector is used.
167 ///
168 /// result = abs(x1 * x2) + abs(y1 * y2)
169 ///
170 /// \param[in] _v The vector
171 /// \return The absolute dot product
172 public: T AbsDot(const Vector2<T> &_v) const
173 {
174 return std::abs(this->data[0] * _v[0]) +
175 std::abs(this->data[1] * _v[1]);
176 }
177
178 /// \brief Corrects any nan values
179 public: inline void Correct()
180 {
181 // std::isfinite works with floating point values,
182 // need to explicit cast to avoid ambiguity in vc++.
183 if (!std::isfinite(static_cast<double>(this->data[0])))
184 this->data[0] = 0;
185 if (!std::isfinite(static_cast<double>(this->data[1])))
186 this->data[1] = 0;
187 }
188
189 /// \brief Set this vector's components to the maximum of itself and the
190 /// passed in vector
191 /// \param[in] _v the maximum clamping vector
192 public: void Max(const Vector2<T> &_v)
193 {
194 this->data[0] = std::max(_v[0], this->data[0]);
195 this->data[1] = std::max(_v[1], this->data[1]);
196 }
197
198 /// \brief Set this vector's components to the minimum of itself and the
199 /// passed in vector
200 /// \param[in] _v the minimum clamping vector
201 public: void Min(const Vector2<T> &_v)
202 {
203 this->data[0] = std::min(_v[0], this->data[0]);
204 this->data[1] = std::min(_v[1], this->data[1]);
205 }
206
207 /// \brief Get the maximum value in the vector
208 /// \return the maximum element
209 public: T Max() const
210 {
211 return std::max(this->data[0], this->data[1]);
212 }
213
214 /// \brief Get the minimum value in the vector
215 /// \return the minimum element
216 public: T Min() const
217 {
218 return std::min(this->data[0], this->data[1]);
118219 }
119220
120221 /// \brief Assignment operator
321321 }
322322
323323 /// \brief Assignment operator
324 /// \param[in] _value assigned to all elements
324 /// \param[in] _v assigned to all elements
325325 /// \return this
326326 public: Vector3 &operator=(T _v)
327327 {
1616 #ifndef IGNITION_MATH_VECTOR4_HH_
1717 #define IGNITION_MATH_VECTOR4_HH_
1818
19 #include <algorithm>
20
1921 #include <ignition/math/Matrix4.hh>
2022 #include <ignition/math/Helpers.hh>
2123 #include <ignition/math/config.hh>
8183 (this->data[3]-_pt[3])*(this->data[3]-_pt[3]));
8284 }
8385
86 /// \brief Calc distance to the given point
87 /// \param[in] _x value along x
88 /// \param[in] _y value along y
89 /// \param[in] _z value along z
90 /// \param[in] _w value along w
91 /// \return the distance
92 public: T Distance(T _x, T _y, T _z, T _w) const
93 {
94 return this->Distance(Vector4(_x, _y, _z, _w));
95 }
96
8497 /// \brief Returns the length (magnitude) of the vector
8598 /// \return The length
8699 public: T Length() const
96109 + std::pow(this->data[1], 2)
97110 + std::pow(this->data[2], 2)
98111 + std::pow(this->data[3], 2);
112 }
113
114 /// \brief Round to near whole number.
115 public: void Round()
116 {
117 this->data[0] = nearbyint(this->data[0]);
118 this->data[1] = nearbyint(this->data[1]);
119 this->data[2] = nearbyint(this->data[2]);
120 this->data[3] = nearbyint(this->data[3]);
121 }
122
123 /// \brief Get a rounded version of this vector
124 /// \return a rounded vector
125 public: Vector4 Rounded() const
126 {
127 Vector4<T> result = *this;
128 result.Round();
129 return result;
130 }
131
132 /// \brief Corrects any nan values
133 public: inline void Correct()
134 {
135 // std::isfinite works with floating point values,
136 // need to explicit cast to avoid ambiguity in vc++.
137 if (!std::isfinite(static_cast<double>(this->data[0])))
138 this->data[0] = 0;
139 if (!std::isfinite(static_cast<double>(this->data[1])))
140 this->data[1] = 0;
141 if (!std::isfinite(static_cast<double>(this->data[2])))
142 this->data[2] = 0;
143 if (!std::isfinite(static_cast<double>(this->data[3])))
144 this->data[3] = 0;
99145 }
100146
101147 /// \brief Normalize the vector length
112158 }
113159 }
114160
161 /// \brief Return a normalized vector
162 /// \return unit length vector
163 public: Vector4 Normalized() const
164 {
165 Vector4<T> result = *this;
166 result.Normalize();
167 return result;
168 }
169
170 /// \brief Return the dot product of this vector and another vector
171 /// \param[in] _v the vector
172 /// \return the dot product
173 public: T Dot(const Vector4<T> &_v) const
174 {
175 return this->data[0] * _v[0] +
176 this->data[1] * _v[1] +
177 this->data[2] * _v[2] +
178 this->data[3] * _v[3];
179 }
180
181 /// \brief Return the absolute dot product of this vector and
182 /// another vector. This is similar to the Dot function, except the
183 /// absolute value of each component of the vector is used.
184 ///
185 /// result = abs(x1 * x2) + abs(y1 * y2) + abs(z1 * z2) + abs(w1 * w2)
186 ///
187 /// \param[in] _v the vector
188 /// \return The absolute dot product
189 public: T AbsDot(const Vector4<T> &_v) const
190 {
191 return std::abs(this->data[0] * _v[0]) +
192 std::abs(this->data[1] * _v[1]) +
193 std::abs(this->data[2] * _v[2]) +
194 std::abs(this->data[3] * _v[3]);
195 }
196
197 /// \brief Get the absolute value of the vector
198 /// \return a vector with positive elements
199 public: Vector4 Abs() const
200 {
201 return Vector4(std::abs(this->data[0]),
202 std::abs(this->data[1]),
203 std::abs(this->data[2]),
204 std::abs(this->data[3]));
205 }
206
115207 /// \brief Set the contents of the vector
116208 /// \param[in] _x value along x axis
117209 /// \param[in] _y value along y axis
125217 this->data[3] = _w;
126218 }
127219
220 /// \brief Set this vector's components to the maximum of itself and the
221 /// passed in vector
222 /// \param[in] _v the maximum clamping vector
223 public: void Max(const Vector4<T> &_v)
224 {
225 this->data[0] = std::max(_v[0], this->data[0]);
226 this->data[1] = std::max(_v[1], this->data[1]);
227 this->data[2] = std::max(_v[2], this->data[2]);
228 this->data[3] = std::max(_v[3], this->data[3]);
229 }
230
231 /// \brief Set this vector's components to the minimum of itself and the
232 /// passed in vector
233 /// \param[in] _v the minimum clamping vector
234 public: void Min(const Vector4<T> &_v)
235 {
236 this->data[0] = std::min(_v[0], this->data[0]);
237 this->data[1] = std::min(_v[1], this->data[1]);
238 this->data[2] = std::min(_v[2], this->data[2]);
239 this->data[3] = std::min(_v[3], this->data[3]);
240 }
241
242 /// \brief Get the maximum value in the vector
243 /// \return the maximum element
244 public: T Max() const
245 {
246 return *std::max_element(this->data, this->data+4);
247 }
248
249 /// \brief Get the minimum value in the vector
250 /// \return the minimum element
251 public: T Min() const
252 {
253 return *std::min_element(this->data, this->data+4);
254 }
255
256 /// \brief Return the sum of the values
257 /// \return the sum
258 public: T Sum() const
259 {
260 return this->data[0] + this->data[1] + this->data[2] + this->data[3];
261 }
262
128263 /// \brief Assignment operator
129264 /// \param[in] _v the vector
130265 /// \return a reference to this vector
305440 /// \brief Division assignment operator
306441 /// \remarks Performs element wise division,
307442 /// which has limited use.
308 /// \param[in] _pt another vector
443 /// \param[in] _v another vector
309444 /// \return a result vector
310445 public: const Vector4<T> operator/(T _v) const
311446 {
547682 this->data[3] = _v;
548683 }
549684
685 /// \brief Less than operator.
686 /// \param[in] _pt Vector to compare.
687 /// \return True if this vector's X(), Y(), Z() or W() value is less
688 /// than the given vector's corresponding values.
689 public: bool operator<(const Vector4<T> &_pt) const
690 {
691 return this->data[0] < _pt[0] || this->data[1] < _pt[1] ||
692 this->data[2] < _pt[2] || this->data[3] < _pt[3];
693 }
694
550695 /// \brief Stream insertion operator
551696 /// \param[in] _out output stream
552697 /// \param[in] _pt Vector4 to output
00 /* Config.hh. Generated by CMake for @PROJECT_NAME_NO_VERSION@. */
11
22 /* Version number */
3 #define IGNITION_MATH_MAJOR_VERSION ${PROJECT_MAJOR_VERSION}
4 #define IGNITION_MATH_MINOR_VERSION ${PROJECT_MINOR_VERSION}
5 #define IGNITION_MATH_PATCH_VERSION ${PROJECT_PATCH_VERSION}
3 #define IGNITION_MATH_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}
4 #define IGNITION_MATH_MINOR_VERSION ${PROJECT_VERSION_MINOR}
5 #define IGNITION_MATH_PATCH_VERSION ${PROJECT_VERSION_PATCH}
66
77 #define IGNITION_MATH_VERSION "${PROJECT_VERSION}"
88 #define IGNITION_MATH_VERSION_FULL "${PROJECT_VERSION_FULL}"
99
1010 #define IGNITION_MATH_VERSION_NAMESPACE v${PROJECT_VERSION_MAJOR}
1111
12 #define IGNITION_MATH_VERSION_HEADER "Ignition math, version ${PROJECT_VERSION_FULL}\nCopyright (C) 2014 Open Source Robotics Foundation.\nReleased under the Apache 2.0 License.\n\n"
12 #define IGNITION_MATH_VERSION_HEADER "Ignition ${IGN_DESIGNATION}, version ${PROJECT_VERSION_FULL}\nCopyright (C) 2014 Open Source Robotics Foundation.\nReleased under the Apache 2.0 License.\n\n"
1313
1414 #cmakedefine IGNITION_MATH_BUILD_TYPE_PROFILE 1
1515 #cmakedefine IGNITION_MATH_BUILD_TYPE_DEBUG 1
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16 #ifndef IGNITION_MATH_DETAIL_CAPSULE_HH_
17 #define IGNITION_MATH_DETAIL_CAPSULE_HH_
18
19 #include <limits>
20 #include <optional>
21 #include <ignition/math/Helpers.hh>
22 #include <ignition/math/Inertial.hh>
23
24 namespace ignition
25 {
26 namespace math
27 {
28
29 //////////////////////////////////////////////////
30 template<typename T>
31 Capsule<T>::Capsule(const T _length, const T _radius)
32 {
33 this->length = _length;
34 this->radius = _radius;
35 }
36
37 //////////////////////////////////////////////////
38 template<typename T>
39 Capsule<T>::Capsule(const T _length, const T _radius, const Material &_mat)
40 {
41 this->length = _length;
42 this->radius = _radius;
43 this->material = _mat;
44 }
45
46 //////////////////////////////////////////////////
47 template<typename T>
48 T Capsule<T>::Radius() const
49 {
50 return this->radius;
51 }
52
53 //////////////////////////////////////////////////
54 template<typename T>
55 void Capsule<T>::SetRadius(const T _radius)
56 {
57 this->radius = _radius;
58 }
59
60 //////////////////////////////////////////////////
61 template<typename T>
62 T Capsule<T>::Length() const
63 {
64 return this->length;
65 }
66
67 //////////////////////////////////////////////////
68 template<typename T>
69 void Capsule<T>::SetLength(const T _length)
70 {
71 this->length = _length;
72 }
73
74 //////////////////////////////////////////////////
75 template<typename T>
76 const Material &Capsule<T>::Mat() const
77 {
78 return this->material;
79 }
80
81 //////////////////////////////////////////////////
82 template<typename T>
83 void Capsule<T>::SetMat(const Material &_mat)
84 {
85 this->material = _mat;
86 }
87
88 //////////////////////////////////////////////////
89 template<typename T>
90 bool Capsule<T>::operator==(const Capsule &_capsule) const
91 {
92 return equal(this->radius, _capsule.Radius()) &&
93 equal(this->length, _capsule.Length()) &&
94 this->material == _capsule.Mat();
95 }
96
97 //////////////////////////////////////////////////
98 template<typename T>
99 std::optional< MassMatrix3<T> > Capsule<T>::MassMatrix() const
100 {
101 // mass and moment of inertia of cylinder about centroid
102 MassMatrix3<T> cylinder;
103 cylinder.SetFromCylinderZ(this->material, this->length, this->radius);
104
105 // mass and moment of inertia of hemisphere about centroid
106 const T r2 = this->radius * this->radius;
107 const T hemisphereMass = this->material.Density() *
108 2. / 3. * IGN_PI * r2 * this->radius;
109 // efunda.com/math/solids/solids_display.cfm?SolidName=Hemisphere
110 const T ixx = 83. / 320. * hemisphereMass * r2;
111 const T izz = 2. / 5. * hemisphereMass * r2;
112 MassMatrix3<T> hemisphere(hemisphereMass, Vector3<T>(ixx, ixx, izz),
113 Vector3<T>::Zero);;
114
115 // Distance from centroid of cylinder to centroid of hemisphere,
116 // since centroid of hemisphere is 3/8 radius from its flat base
117 const T dz = this->length / 2. + this->radius * 3. / 8.;
118 Inertial<T> upperCap(hemisphere, Pose3<T>(0, 0, dz, 0, 0, 0));
119 Inertial<T> lowerCap(hemisphere, Pose3<T>(0, 0, -dz, 0, 0, 0));
120
121 // Use Inertial class to add MassMatrix3 objects at different poses
122 Inertial<T> capsule =
123 Inertial<T>(cylinder, Pose3<T>::Zero) + upperCap + lowerCap;
124
125 if (!capsule.MassMatrix().IsValid())
126 {
127 return std::nullopt;
128 }
129
130 return std::make_optional(capsule.MassMatrix());
131 }
132
133 //////////////////////////////////////////////////
134 template<typename T>
135 T Capsule<T>::Volume() const
136 {
137 return IGN_PI * std::pow(this->radius, 2) *
138 (this->length + 4. / 3. * this->radius);
139 }
140
141 //////////////////////////////////////////////////
142 template<typename T>
143 bool Capsule<T>::SetDensityFromMass(const T _mass)
144 {
145 T newDensity = this->DensityFromMass(_mass);
146 if (isnan(newDensity))
147 return false;
148
149 this->material.SetDensity(newDensity);
150 return true;
151 }
152
153 //////////////////////////////////////////////////
154 template<typename T>
155 T Capsule<T>::DensityFromMass(const T _mass) const
156 {
157 if (this->radius <= 0 || this->length <=0 || _mass <= 0)
158 return std::numeric_limits<T>::quiet_NaN();
159
160 return _mass / this->Volume();
161 }
162
163 }
164 }
165 #endif
3434 inline namespace IGNITION_MATH_VERSION_NAMESPACE {
3535 namespace graph
3636 {
37 /// \def EdgeId.
37 /// \typedef EdgeId.
3838 /// \brief The unique Id for an edge.
3939 using EdgeId = uint64_t;
4040
160160 /// (v1) and the head end (v2): (v1)->(v2). The operation e2.To(v1)
161161 /// returns kNullId. The operation e2.To(v2) returns v1.
162162 ///
163 /// \param[in] _from Destination vertex.
163 /// \param[in] _to Destination vertex.
164164 /// \return The other vertex of the edge that can reach "_to"
165165 /// vertex or kNullId otherwise.
166166 public: virtual VertexId To(const VertexId &_to) const = 0;
243243 /// description language.
244244 /// \param[out] _out The output stream.
245245 /// \param[in] _e Edge to write to the stream.
246 /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
246 /// \sa https://en.wikipedia.org/wiki/DOT_(graph_description_language).
247247 public: friend std::ostream &operator<<(std::ostream &_out,
248248 const UndirectedEdge<E> &_e)
249249 {
319319 /// description language.
320320 /// \param[out] _out The output stream.
321321 /// \param[in] _e Edge to write to the stream.
322 /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
322 /// \sa https://en.wikipedia.org/wiki/DOT_(graph_description_language).
323323 public: friend std::ostream &operator<<(std::ostream &_out,
324324 const DirectedEdge<E> &_e)
325325 {
204204 /// \brief Add a new edge to the graph.
205205 /// \param[in] _vertices The set of Ids of the two vertices.
206206 /// \param[in] _data User data.
207 /// \param[in] _weight Edge weight.
207208 /// \return Reference to the new edge created or NullEdge if the
208209 /// edge was not created (e.g. incorrect vertices).
209210 public: EdgeType &AddEdge(const VertexId_P &_vertices,
683684 /// description language.
684685 /// \param[out] _out The output stream.
685686 /// \param[in] _g Graph to write to the stream.
686 /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
687 /// \sa https://en.wikipedia.org/wiki/DOT_(graph_description_language).
687688 public: template<typename VV, typename EE, typename EEdgeType>
688689 friend std::ostream &operator<<(std::ostream &_out,
689690 const Graph<VV, EE, EEdgeType> &_g);
3636 inline namespace IGNITION_MATH_VERSION_NAMESPACE {
3737 namespace graph
3838 {
39 /// \def CostInfo.
39 /// \typedef CostInfo.
4040 /// \brief Used in Dijkstra. For a given source vertex, this pair represents
4141 /// the cost (first element) to reach a destination vertex (second element).
4242 using CostInfo = std::pair<double, VertexId>;
281281 /// A connected component of an undirected graph is a subgraph in which any
282282 /// two vertices are connected to each other by paths, and which is connected
283283 /// to no additional vertices in the supergraph.
284 /// \ref https://en.wikipedia.org/wiki/Connected_component_(graph_theory)
284 /// \sa https://en.wikipedia.org/wiki/Connected_component_(graph_theory)
285285 /// \param[in] _graph A graph.
286286 /// \return A vector of graphs. Each element of the graph is a component
287287 /// (subgraph) of the original graph.
324324
325325 return res;
326326 }
327
328 /// \brief Copy a DirectedGraph to an UndirectedGraph with the same vertices
329 /// and edges.
330 /// \param[in] _graph A directed graph.
331 /// \return An undirected graph with the same vertices and edges as the
332 /// original graph.
333 template<typename V, typename E>
334 UndirectedGraph<V, E> ToUndirectedGraph(const DirectedGraph<V, E> &_graph)
335 {
336 std::vector<Vertex<V>> vertices;
337 std::vector<EdgeInitializer<E>> edges;
338
339 // Add all vertices.
340 for (auto const &vPair : _graph.Vertices())
341 {
342 vertices.push_back(vPair.second.get());
343 }
344
345 // Add all edges.
346 for (auto const &ePair : _graph.Edges())
347 {
348 auto const &e = ePair.second.get();
349 edges.push_back({e.Vertices(), e.Data(), e.Weight()});
350 }
351
352 return UndirectedGraph<V, E>(vertices, edges);
353 }
327354 }
328355 }
329356 }
3535 inline namespace IGNITION_MATH_VERSION_NAMESPACE {
3636 namespace graph
3737 {
38 /// \def VertexId.
38 /// \typedef VertexId.
3939 /// \brief The unique Id of each vertex.
4040 using VertexId = uint64_t;
4141
114114 /// description language.
115115 /// \param[out] _out The output stream.
116116 /// \param[in] _v Vertex to write to the stream.
117 /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
117 /// \sa https://en.wikipedia.org/wiki/DOT_(graph_description_language).
118118 public: friend std::ostream &operator<<(std::ostream &_out,
119119 const Vertex<V> &_v)
120120 {
5353 }
5454
5555 //////////////////////////////////////////////////
56 void Angle::SetRadian(double _radian)
57 {
58 this->value = _radian;
59 }
60
61 //////////////////////////////////////////////////
5662 void Angle::Degree(double _degree)
63 {
64 this->value = _degree * IGN_PI / 180.0;
65 }
66
67 //////////////////////////////////////////////////
68 void Angle::SetDegree(double _degree)
5769 {
5870 this->value = _degree * IGN_PI / 180.0;
5971 }
7486 void Angle::Normalize()
7587 {
7688 this->value = atan2(sin(this->value), cos(this->value));
89 }
90
91 //////////////////////////////////////////////////
92 Angle Angle::Normalized() const
93 {
94 return atan2(sin(this->value), cos(this->value));
7795 }
7896
7997 //////////////////////////////////////////////////
3333 public: Angle(double _radian);
3434 public: Angle(const Angle &_angle);
3535 public: virtual ~Angle();
36 public: void Radian(double _radian);
37 public: void Degree(double _degree);
36 public: void SetRadian(double _radian);
37 public: void SetDegree(double _degree);
3838 public: double Radian() const;
3939 public: double Degree() const;
4040 public: void Normalize();
41 public: Angle Normalized() const;
4142 public: inline double operator*() const;
4243 public: Angle operator-(const Angle &_angle) const;
4344 public: Angle operator+(const Angle &_angle) const;
2929 math::Angle angle1;
3030 EXPECT_TRUE(math::equal(0.0, angle1.Radian()));
3131
32 angle1.SetDegree(90.0);
33 EXPECT_TRUE(angle1 == IGN_PI_2);
3234 angle1.Degree(180.0);
3335 EXPECT_TRUE(angle1 == IGN_PI);
3436
4446 math::Angle angle(0.5);
4547 EXPECT_TRUE(math::equal(0.5, angle.Radian()));
4648
49 angle.SetRadian(IGN_PI_2);
50 EXPECT_TRUE(math::equal(IGN_RTOD(IGN_PI_2), angle.Degree()));
51
4752 angle.Radian(IGN_PI);
4853 EXPECT_TRUE(math::equal(IGN_RTOD(IGN_PI), angle.Degree()));
4954
55 math::Angle normalized = angle.Normalized();
5056 angle.Normalize();
5157 EXPECT_TRUE(math::equal(IGN_RTOD(IGN_PI), angle.Degree()));
58 EXPECT_EQ(normalized, angle);
5259
5360 angle = math::Angle(0.1) + math::Angle(0.2);
5461 EXPECT_TRUE(math::equal(0.3, angle.Radian()));
2424 assert(angle1.Radian() == 0.0,
2525 "Angle::Radian() should equal zero")
2626
27 angle1.Degree(180.0)
27 angle1.SetDegree(180.0)
2828 assert(angle1 == Ignition::Math::Angle.Pi,
2929 "180.0 degrees should equal PI")
3030
5252 angle = Ignition::Math::Angle.new(0.5)
5353 assert(0.5 == angle.Radian, "Angle should equal 0.5")
5454
55 angle.Radian(Math::PI)
55 angle.SetRadian(Math::PI)
5656 assert(Ignition::Math::Angle.Pi.Degree == angle.Degree,
57 "Pi in degrees should equal Angle.Radian(Pi).Degree")
57 "Pi in degrees should equal Angle.SetRadian(Pi).Degree")
58
59 angleNorm = angle.Normalized()
5860
5961 angle.Normalize()
6062 assert(Ignition::Math::Angle.new(Math::PI).Degree == angle.Degree,
6163 "Normalized angle should equal PI")
64 assert(angleNorm == angle, "Normalized angles should be equal")
6265
6366 angle = Ignition::Math::Angle.new(0.1) + Ignition::Math::Angle.new(0.2)
6467 assert((angle.Radian - 0.3).abs < 1e-6, "Angle should equal 0.3")
158158 }
159159
160160 //////////////////////////////////////////////////
161 AxisAlignedBox AxisAlignedBox::operator+(const Vector3d &_v)
162 {
163 return AxisAlignedBox(this->dataPtr->min + _v, this->dataPtr->max + _v);
164 }
165
166 //////////////////////////////////////////////////
161167 bool AxisAlignedBox::Intersects(const AxisAlignedBox &_box) const
162168 {
163169 // Check the six separating planes.
277283 dir.Normalize();
278284 return this->Intersect(Line3d(_origin + dir * _min, _origin + dir * _max));
279285 }
286 /////////////////////////////////////////////////
287 double AxisAlignedBox::Volume() const
288 {
289 return this->XLength() * this->YLength() * this->ZLength();
290 }
280291
281292 /////////////////////////////////////////////////
282293 // Find the intersection of a line from v0 to v1 and an
208208 }
209209
210210 /////////////////////////////////////////////////
211 TEST(AxisAlignedBoxTest, Plus)
212 {
213 AxisAlignedBox box1(1, 2, 3, 4, 5, 6);
214 Vector3d add(1, 1, 1);
215
216 AxisAlignedBox box2 = box1 + add;
217 EXPECT_EQ(box2.Min(), box1.Min() + add);
218 EXPECT_EQ(box2.Max(), box1.Max() + add);
219 }
220
221 /////////////////////////////////////////////////
211222 TEST(AxisAlignedBoxTest, PlusEmpty)
212223 {
213224 AxisAlignedBox box1;
238249 box.Merge(AxisAlignedBox(Vector3d(-1, -1, -1), Vector3d(2, 2, 2)));
239250 EXPECT_TRUE(box == AxisAlignedBox(Vector3d(-1, -2, -1),
240251 Vector3d(2, 2, 3)));
252 }
253
254 /////////////////////////////////////////////////
255 TEST_F(ExampleAxisAlignedBox, Volume)
256 {
257 EXPECT_DOUBLE_EQ(1.0, box.Volume());
241258 }
242259
243260 /////////////////////////////////////////////////
565582 Vector3d(-0.707107, 0, -0.707107), 0, 1000)), dist, 1e-5);
566583 EXPECT_EQ(pt, Vector3d(1, 0, 0.3));
567584 }
585
586 /////////////////////////////////////////////////
587 TEST(AxisAlignedBoxTest, Volume)
588 {
589 AxisAlignedBox box;
590 EXPECT_DOUBLE_EQ(0.0, box.Volume());
591
592 AxisAlignedBox box2(math::Vector3d(-1, -2, -3), math::Vector3d(1, 2, 3));
593 EXPECT_DOUBLE_EQ(48.0, box2.Volume());
594 }
2222 set(swig_files
2323 ruby
2424 Angle
25 GaussMarkovProcess
26 Rand
2527 Vector2
26 Vector3)
28 Vector3
29 Vector4)
2730 endif()
2831
2932 #################################################
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16 #include <gtest/gtest.h>
17 #include <cmath>
18 #include <iostream>
19
20 #include "ignition/math/Capsule.hh"
21 #include "ignition/math/Helpers.hh"
22
23 using namespace ignition;
24
25 /////////////////////////////////////////////////
26 TEST(CapsuleTest, Constructor)
27 {
28 // Default constructor
29 {
30 math::Capsuled capsule;
31 EXPECT_DOUBLE_EQ(0.0, capsule.Length());
32 EXPECT_DOUBLE_EQ(0.0, capsule.Radius());
33 EXPECT_EQ(math::Material(), capsule.Mat());
34
35 math::Capsuled capsule2;
36 EXPECT_EQ(capsule, capsule2);
37 }
38
39 // Length and radius constructor
40 {
41 math::Capsuled capsule(1.0, 2.0);
42 EXPECT_DOUBLE_EQ(1.0, capsule.Length());
43 EXPECT_DOUBLE_EQ(2.0, capsule.Radius());
44 EXPECT_EQ(math::Material(), capsule.Mat());
45
46 math::Capsuled capsule2(1.0, 2.0);
47 EXPECT_EQ(capsule, capsule2);
48 }
49
50 // Length, radius, mat
51 {
52 math::Capsuled capsule(1.0, 2.0,
53 math::Material(math::MaterialType::WOOD));
54 EXPECT_DOUBLE_EQ(1.0, capsule.Length());
55 EXPECT_DOUBLE_EQ(2.0, capsule.Radius());
56 EXPECT_EQ(math::Material(math::MaterialType::WOOD), capsule.Mat());
57
58 math::Capsuled capsule2(1.0, 2.0,
59 math::Material(math::MaterialType::WOOD));
60 EXPECT_EQ(capsule, capsule2);
61 }
62 }
63
64 //////////////////////////////////////////////////
65 TEST(CapsuleTest, Mutators)
66 {
67 math::Capsuled capsule;
68 EXPECT_DOUBLE_EQ(0.0, capsule.Length());
69 EXPECT_DOUBLE_EQ(0.0, capsule.Radius());
70 EXPECT_EQ(math::Material(), capsule.Mat());
71
72 capsule.SetLength(100.1);
73 capsule.SetRadius(.123);
74 capsule.SetMat(math::Material(math::MaterialType::PINE));
75
76 EXPECT_DOUBLE_EQ(100.1, capsule.Length());
77 EXPECT_DOUBLE_EQ(.123, capsule.Radius());
78 EXPECT_EQ(math::Material(math::MaterialType::PINE), capsule.Mat());
79 }
80
81 //////////////////////////////////////////////////
82 TEST(CapsuleTest, VolumeAndDensity)
83 {
84 double mass = 1.0;
85 math::Capsuled capsule(1.0, 0.001);
86 double expectedVolume = (IGN_PI * std::pow(0.001, 2) * (1.0 + 4./3. * 0.001));
87 EXPECT_DOUBLE_EQ(expectedVolume, capsule.Volume());
88
89 double expectedDensity = mass / expectedVolume;
90 EXPECT_DOUBLE_EQ(expectedDensity, capsule.DensityFromMass(mass));
91
92 // Bad density
93 math::Capsuled capsule2;
94 EXPECT_TRUE(math::isnan(capsule2.DensityFromMass(mass)));
95 }
96
97 //////////////////////////////////////////////////
98 TEST(CapsuleTest, Mass)
99 {
100 double mass = 2.0;
101 double l = 2.0;
102 double r = 0.1;
103 math::Capsuled capsule(l, r);
104 capsule.SetDensityFromMass(mass);
105
106 const double cylinderVolume = IGN_PI * r*r * l;
107 const double sphereVolume = IGN_PI * 4. / 3. * r*r*r;
108 const double volume = cylinderVolume + sphereVolume;
109 const double cylinderMass = mass * cylinderVolume / volume;
110 const double sphereMass = mass * sphereVolume / volume;
111
112 // expected values based on formula used in Open Dynamics Engine
113 // https://bitbucket.org/odedevs/ode/src/0.16.2/ode/src/mass.cpp#lines-148:153
114 // and the following article:
115 // https://www.gamedev.net/tutorials/_/technical/math-and-physics/capsule-inertia-tensor-r3856/
116 double ixxIyy = (1/12.0) * cylinderMass * (3*r*r + l*l)
117 + sphereMass * (0.4*r*r + 0.375*r*l + 0.25*l*l);
118 double izz = r*r * (0.5 * cylinderMass + 0.4 * sphereMass);
119
120 math::MassMatrix3d expectedMassMat;
121 expectedMassMat.SetInertiaMatrix(ixxIyy, ixxIyy, izz, 0.0, 0.0, 0.0);
122 expectedMassMat.SetMass(mass);
123
124 auto massMat = capsule.MassMatrix();
125 ASSERT_NE(std::nullopt, massMat);
126 EXPECT_EQ(expectedMassMat, *massMat);
127 EXPECT_EQ(expectedMassMat.DiagonalMoments(), massMat->DiagonalMoments());
128 EXPECT_DOUBLE_EQ(expectedMassMat.Mass(), massMat->Mass());
129 }
336336 }
337337
338338 /////////////////////////////////////////////////
339 TEST(Color, OperatorStreamIn)
340 {
341 math::Color c(0.1f, 0.2f, 0.3f, 0.5f);
342 math::Color test;
343 std::stringstream ss("0.1 0.2 0.3 0.5");
344 ss >> test;
345 EXPECT_EQ(c, test);
346 }
347
348 /////////////////////////////////////////////////
349 TEST(Color, OperatorStreamInWithoutAlpha)
350 {
351 math::Color c(0.1f, 0.2f, 0.3f, 1.0f);
352 {
353 math::Color test;
354 std::stringstream ss("0.1 0.2 0.3");
355 ss.exceptions(std::stringstream::failbit);
356 EXPECT_NO_THROW(ss >> test);
357 EXPECT_EQ(c, test);
358 }
359 {
360 math::Color test;
361 std::stringstream ss("0.1 0.2 \t0.3 \t");
362 ss.exceptions(std::stringstream::failbit);
363 EXPECT_NO_THROW(ss >> test);
364 EXPECT_EQ(c, test);
365 }
366
367 {
368 math::Color test(0.5f, 0.6f, 0.7f, 0.8f);
369 std::stringstream ss("0.1 0.2 \t0.3 \t");
370 ss.exceptions(std::stringstream::failbit);
371 EXPECT_NO_THROW(ss >> test);
372 EXPECT_EQ(c, test);
373 }
374 }
375
376 /////////////////////////////////////////////////
339377 TEST(Color, HSV)
340378 {
341379 math::Color clr;
192192 // Field of view
193193 Angle(IGN_DTOR(45)),
194194 // Aspect ratio
195 320.0/320.0,
195 1.0,
196196 // Pose
197197 Pose3d(0, 0, 0, 0, 0, IGN_PI*0.5));
198198
222222 // Field of view
223223 Angle(IGN_DTOR(45)),
224224 // Aspect ratio
225 320.0/320.0,
225 1.0,
226226 // Pose
227227 Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
228228
253253 // Field of view
254254 Angle(IGN_DTOR(45)),
255255 // Aspect ratio
256 320.0/320.0,
256 1.0,
257257 // Pose
258258 Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
259259
278278 // Field of view
279279 Angle(IGN_DTOR(45)),
280280 // Aspect ratio
281 320.0/320.0,
281 1.0,
282282 // Pose
283283 Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
284284
300300 // Field of view
301301 Angle(IGN_DTOR(45)),
302302 // Aspect ratio
303 320.0/320.0,
303 1.0,
304304 // Pose
305305 Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
306306
307 EXPECT_DOUBLE_EQ(frustum.AspectRatio(), 320.0/320.0);
307 EXPECT_DOUBLE_EQ(frustum.AspectRatio(), 1);
308308
309309 frustum.SetAspectRatio(1.3434);
310310
322322 // Field of view
323323 Angle(IGN_DTOR(45)),
324324 // Aspect ratio
325 320.0/320.0,
325 1.0,
326326 // Pose
327327 Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
328328
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16
17 #include <ignition/math/GaussMarkovProcess.hh>
18 #include <ignition/math/Rand.hh>
19
20 using namespace ignition::math;
21
22 //////////////////////////////////////////////////
23 class ignition::math::GaussMarkovProcessPrivate
24 {
25 /// \brief Current process value.
26 public: double value{0};
27
28 /// \brief Process start value.
29 public: double start{0};
30
31 /// \brief Process theta value.
32 public: double theta{0};
33
34 /// \brief Process mu value.
35 public: double mu{0};
36
37 /// \brief Process sigma value.
38 public: double sigma{0};
39 };
40
41 //////////////////////////////////////////////////
42 GaussMarkovProcess::GaussMarkovProcess()
43 : dataPtr(new GaussMarkovProcessPrivate)
44 {
45 }
46
47 //////////////////////////////////////////////////
48 GaussMarkovProcess::GaussMarkovProcess(double _start, double _theta, double _mu,
49 double _sigma)
50 : dataPtr(new GaussMarkovProcessPrivate)
51 {
52 this->Set(_start, _theta, _mu, _sigma);
53 }
54
55 //////////////////////////////////////////////////
56 GaussMarkovProcess::~GaussMarkovProcess()
57 {
58 }
59
60 //////////////////////////////////////////////////
61 void GaussMarkovProcess::Set(double _start, double _theta, double _mu,
62 double _sigma)
63 {
64 this->dataPtr->start = _start;
65 this->dataPtr->theta = std::max(0.0, _theta);
66 this->dataPtr->mu = _mu;
67 this->dataPtr->sigma = std::max(0.0, _sigma);
68 this->Reset();
69 }
70
71 //////////////////////////////////////////////////
72 void GaussMarkovProcess::Reset()
73 {
74 this->dataPtr->value = this->dataPtr->start;
75 }
76
77 //////////////////////////////////////////////////
78 double GaussMarkovProcess::Start() const
79 {
80 return this->dataPtr->start;
81 }
82
83 //////////////////////////////////////////////////
84 double GaussMarkovProcess::Value() const
85 {
86 return this->dataPtr->value;
87 }
88
89 //////////////////////////////////////////////////
90 double GaussMarkovProcess::Theta() const
91 {
92 return this->dataPtr->theta;
93 }
94
95 //////////////////////////////////////////////////
96 double GaussMarkovProcess::Mu() const
97 {
98 return this->dataPtr->mu;
99 }
100
101 //////////////////////////////////////////////////
102 double GaussMarkovProcess::Sigma() const
103 {
104 return this->dataPtr->sigma;
105 }
106
107 //////////////////////////////////////////////////
108 double GaussMarkovProcess::Update(const clock::duration &_dt)
109 {
110 // Time difference in seconds
111 return this->Update(std::chrono::duration<double>(_dt).count());
112 }
113
114 //////////////////////////////////////////////////
115 double GaussMarkovProcess::Update(double _dt)
116 {
117 this->dataPtr->value += this->dataPtr->theta *
118 (this->dataPtr->mu - this->dataPtr->value) * _dt +
119 this->dataPtr->sigma * Rand::DblNormal(0, 1);
120
121 // Output the new value.
122 return this->dataPtr->value;
123 }
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16
17 %module gaussMarkovProcess
18 %{
19 #include <ignition/math/GaussMarkovProcess.hh>
20 %}
21
22 namespace ignition
23 {
24 namespace math
25 {
26 class GaussMarkovProcess
27 {
28 public: GaussMarkovProcess();
29 public: GaussMarkovProcess(double _start, double _theta, double _mu,
30 double _sigma);
31 public: ~GaussMarkovProcess();
32 public: void Set(double _start, double _theta, double _mu, double _sigma);
33 public: double Start() const;
34 public: double Value() const;
35 public: double Theta() const;
36 public: double Mu() const;
37 public: double Sigma() const;
38 public: void Reset();
39 public: double Update(double _dt);
40 };
41 }
42 }
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16
17 #include <gtest/gtest.h>
18
19 #include "ignition/math/GaussMarkovProcess.hh"
20 #include "ignition/math/Helpers.hh"
21 #include "ignition/math/Rand.hh"
22
23 using namespace ignition;
24 using namespace math;
25
26 /////////////////////////////////////////////////
27 TEST(GaussMarkovProcessTest, DefaultConstructor)
28 {
29 GaussMarkovProcess gmp;
30 EXPECT_DOUBLE_EQ(0.0, gmp.Start());
31 EXPECT_DOUBLE_EQ(0.0, gmp.Value());
32 EXPECT_DOUBLE_EQ(0.0, gmp.Theta());
33 EXPECT_DOUBLE_EQ(0.0, gmp.Mu());
34 EXPECT_DOUBLE_EQ(0.0, gmp.Sigma());
35 // EXPECT_EQ(clock::time_point(), gmp.LastUpdate());
36 }
37
38 /////////////////////////////////////////////////
39 TEST(GaussMarkovProcessTest, Update)
40 {
41 // Start value of -1.2
42 // Theta (rate at which the process should approach the mean) of 1.0
43 // Mu (mean value) 2.5.
44 // Sigma (volatility) of 0.
45 GaussMarkovProcess gmp(-1.2, 1.0, 2.5, 0);
46 EXPECT_DOUBLE_EQ(-1.2, gmp.Start());
47 EXPECT_DOUBLE_EQ(-1.2, gmp.Value());
48 EXPECT_DOUBLE_EQ(1.0, gmp.Theta());
49 EXPECT_DOUBLE_EQ(2.5, gmp.Mu());
50 EXPECT_DOUBLE_EQ(0.0, gmp.Sigma());
51 // EXPECT_EQ(clock::time_point(), gmp.LastUpdate());
52
53 clock::duration dt = std::chrono::milliseconds(100);
54
55 // This process should steadily increase to the mean value of 2.5 since
56 // there is no noise.
57 for (int i = 0; i < 200; ++i)
58 {
59 double value = gmp.Update(dt);
60 EXPECT_GT(value, -1.2);
61 }
62
63 EXPECT_NEAR(2.5, gmp.Value(), 1e-4);
64
65 // The same should occur after a reset.
66 gmp.Reset();
67 for (int i = 0; i < 200; ++i)
68 {
69 double value = gmp.Update(dt);
70 EXPECT_GT(value, -1.2);
71 }
72
73 EXPECT_NEAR(2.5, gmp.Value(), 1e-4);
74 }
75
76 /////////////////////////////////////////////////
77 TEST(GaussMarkovProcessTest, Noise)
78 {
79 // Start value of 20.2
80 // Theta (rate at which the process should approach the mean) of 0.1
81 // Mu (mean value) 0.
82 // Sigma (volatility) of 0.5.
83 GaussMarkovProcess gmp(20.2, 0.1, 0, 0.5);
84 clock::duration dt = std::chrono::milliseconds(100);
85 Rand::Seed(1001);
86
87 // This process should decrease toward the mean value of 0. With noise,
88 // the process will walk.
89 for (int i = 0; i < 1000; ++i)
90 {
91 double value = gmp.Update(dt);
92 // Hand-tuned values that are repeatable given the seed set above.
93 EXPECT_GT(value, -11);
94 EXPECT_LT(value, 22);
95 }
96 // Hand-tuned values that are repeatable given the seed set above.
97 #ifdef __APPLE__
98 EXPECT_NEAR(-4.960893, gmp.Value(), 1e-4);
99 #elif _MSC_VER
100 EXPECT_NEAR(-4.960893, gmp.Value(), 1e-4);
101 #else
102 EXPECT_NEAR(-4.118732, gmp.Value(), 1e-4);
103 #endif
104 }
0 # Copyright (C) 2020 Open Source Robotics Foundation
1 #
2 # Licensed under the Apache License, Version 2.0 (the "License")
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
5 #
6 # http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 #!/usr/bin/env ruby
15
16 require 'test/unit/ui/console/testrunner'
17 require 'test/unit'
18 require 'math'
19
20 class GaussMarkovProcess_TEST < Test::Unit::TestCase
21 def test_construction
22 gmp = Ignition::Math::GaussMarkovProcess.new
23
24 assert(gmp.Start() == 0.0, "Start value should equal zero")
25 assert(gmp.Value() == 0.0, "Initial value should equal zero")
26 assert(gmp.Theta() == 0.0, "Theta should equal zero")
27 assert(gmp.Mu() == 0.0, "Mu should equal zero")
28 assert(gmp.Sigma() == 0.0, "Sigma should equal zero")
29 end
30
31 def test_no_noise
32 gmp = Ignition::Math::GaussMarkovProcess.new(-1.2, 1.0, 2.5, 0)
33 assert(gmp.Start() == -1.2, "Start value should equal zero")
34 assert(gmp.Value() == -1.2, "Initial value should equal zero")
35 assert(gmp.Theta() == 1.0, "Theta should equal zero")
36 assert(gmp.Mu() == 2.5, "Mu should equal zero")
37 assert(gmp.Sigma() == 0.0, "Sigma should equal zero")
38
39 for i in 0..200 do
40 value = gmp.Update(0.1);
41 assert(value > -1.2, "Value should be greater than -1.2")
42 end
43
44 assert(gmp.Value() >= 2.4999, "The final value should be near 2.5")
45 assert(gmp.Value() <= 2.5, "The final value should be near 2.5")
46 end
47
48 def test_noise
49 gmp = Ignition::Math::GaussMarkovProcess.new(20.2, 0.1, 0, 0.5)
50 assert(gmp.Start() == 20.2, "Start value should equal zero")
51 assert(gmp.Value() == 20.2, "Initial value should equal zero")
52 assert(gmp.Theta() == 0.1, "Theta should equal zero")
53 assert(gmp.Mu() == 0, "Mu should equal zero")
54 assert(gmp.Sigma() == 0.5, "Sigma should equal zero")
55 Ignition::Math::Rand::Seed(1001);
56
57 for i in 0..1000 do
58 value = gmp.Update(0.1);
59 assert(value > -11, "Value should be greater than -10")
60 assert(value < 22, "Value should be less than 25")
61 end
62 # Hand-tuned values that are repeatable given the seed set above.
63 assert((gmp.Value() + 3.99148).abs <= 1e-4);
64 end
65
66 end
67
68 exit Test::Unit::UI::Console::TestRunner.run(GaussMarkovProcess_TEST).passed? ? 0 : -1
101101 {
102102 EXPECT_DOUBLE_EQ(math::fixnan(1.0 / 0.0), 0.0);
103103 EXPECT_DOUBLE_EQ(math::fixnan(-1.0 / 0.0), 0.0);
104 EXPECT_DOUBLE_EQ(math::fixnan(0.0 / 0.0), 0.0);
104 EXPECT_DOUBLE_EQ(math::fixnan(1.0 / 0.0), 0.0);
105105
106106 EXPECT_DOUBLE_EQ(math::fixnan(42.0), 42.0);
107107 EXPECT_DOUBLE_EQ(math::fixnan(-42.0), -42.0);
108108
109109 EXPECT_FLOAT_EQ(math::fixnan(1.0f / 0.0f), 0.0f);
110110 EXPECT_FLOAT_EQ(math::fixnan(-1.0f / 0.0f), 0.0f);
111 EXPECT_FLOAT_EQ(math::fixnan(0.0f / 0.0f), 0.0f);
111 EXPECT_FLOAT_EQ(math::fixnan(1.0f / 0.0f), 0.0f);
112112
113113 EXPECT_FLOAT_EQ(math::fixnan(42.0f), 42.0f);
114114 EXPECT_FLOAT_EQ(math::fixnan(-42.0f), -42.0f);
518518 }
519519
520520 /////////////////////////////////////////////////
521 TEST(HelpersTest, timePointToSecNsec)
522 {
523 std::pair<int64_t, int64_t> parts = math::timePointToSecNsec(
524 math::secNsecToTimePoint(0, 0));
525 EXPECT_EQ(parts.first, 0);
526 EXPECT_EQ(parts.second, 0);
527
528 std::chrono::steady_clock::time_point point;
529 point += std::chrono::nanoseconds(1000);
530 parts = math::timePointToSecNsec(point);
531
532 EXPECT_EQ(parts.first, 0);
533 EXPECT_EQ(parts.second, 1000);
534
535 point = math::secNsecToTimePoint(0, 0);
536 point += std::chrono::seconds(60);
537 point += std::chrono::nanoseconds(57989);
538 parts = math::timePointToSecNsec(point);
539
540 EXPECT_EQ(parts.first, 60);
541 EXPECT_EQ(parts.second, 57989);
542 }
543
544 /////////////////////////////////////////////////
545 TEST(HelpersTest, secNsecToTimePoint)
546 {
547 using std::chrono::duration_cast;
548 using std::chrono::nanoseconds;
549 using std::chrono::steady_clock;
550
551 std::chrono::steady_clock::time_point point =
552 math::secNsecToTimePoint(0, 0);
553 point += std::chrono::hours(24);
554
555 std::chrono::steady_clock::time_point s =
556 math::secNsecToTimePoint(24*60*60, 0);
557 EXPECT_EQ(s, point);
558
559 point = math::secNsecToTimePoint(0, 0);
560 point += std::chrono::nanoseconds(1000);
561 s = math::secNsecToTimePoint(0, 1000);
562 EXPECT_EQ(s, point);
563 }
564
565 /////////////////////////////////////////////////
566 TEST(HelpersTest, timePointToString)
567 {
568 std::chrono::steady_clock::time_point time_clock =
569 math::secNsecToTimePoint(0, 0);
570 std::string s = math::timePointToString(time_clock);
571
572 EXPECT_STREQ(s.c_str(), std::string("00 00:00:00.000").c_str());
573
574 std::chrono::steady_clock::time_point point;
575 point += std::chrono::hours(24);
576
577 s = math::timePointToString(point);
578 EXPECT_STREQ(s.c_str(), std::string("01 00:00:00.000").c_str());
579
580 point = math::secNsecToTimePoint(0, 0);
581 point += std::chrono::minutes(1);
582 point += std::chrono::seconds(23);
583 point += std::chrono::milliseconds(125);
584 s = math::timePointToString(point);
585 EXPECT_STREQ(s.c_str(), std::string("00 00:01:23.125").c_str());
586 }
587
588 /////////////////////////////////////////////////
589 TEST(HelpersTest, durationToString)
590 {
591 std::chrono::steady_clock::duration duration =
592 std::chrono::steady_clock::duration::zero();
593 std::string s = math::durationToString(duration);
594
595 EXPECT_STREQ(s.c_str(), std::string("00 00:00:00.000").c_str());
596
597 std::chrono::steady_clock::duration duration1 =
598 std::chrono::steady_clock::duration::zero();
599 duration1 += std::chrono::hours(24);
600
601 s = math::durationToString(duration1);
602 EXPECT_STREQ(s.c_str(), std::string("01 00:00:00.000").c_str());
603
604 duration1 = std::chrono::steady_clock::duration::zero();;
605 duration1 += std::chrono::minutes(1);
606 duration1 += std::chrono::seconds(23);
607 duration1 += std::chrono::milliseconds(125);
608 s = math::durationToString(duration1);
609 EXPECT_STREQ(s.c_str(), std::string("00 00:01:23.125").c_str());
610 }
611
612 /////////////////////////////////////////////////
613 TEST(HelpersTest, stringToDuration)
614 {
615 std::string time = "0 00:00:00.000";
616 std::chrono::steady_clock::duration resultTime =
617 math::stringToDuration(time);
618 std::chrono::steady_clock::duration duration =
619 std::chrono::steady_clock::duration::zero();
620
621 EXPECT_EQ(resultTime, duration);
622
623 time = "10 0";
624 resultTime = math::stringToDuration(time);
625 duration = std::chrono::steady_clock::duration::zero();
626 duration += std::chrono::hours(10 * 24);
627
628 EXPECT_EQ(resultTime, duration);
629
630 time = "7";
631 resultTime = math::stringToDuration(time);
632 duration = std::chrono::steady_clock::duration::zero();
633 duration += std::chrono::seconds(7);
634
635 EXPECT_EQ(resultTime, duration);
636
637 time = "7:10";
638 resultTime = math::stringToDuration(time);
639 duration = std::chrono::steady_clock::duration::zero();
640 duration += std::chrono::minutes(7);
641 duration += std::chrono::seconds(10);
642
643 EXPECT_EQ(resultTime, duration);
644
645 time = "17:10";
646 resultTime = math::stringToDuration(time);
647 duration = std::chrono::steady_clock::duration::zero();
648 duration += std::chrono::minutes(17);
649 duration += std::chrono::seconds(10);
650
651 EXPECT_EQ(resultTime, duration);
652
653 time = "7:10.4";
654 resultTime = math::stringToDuration(time);
655 duration = std::chrono::steady_clock::duration::zero();
656 duration += std::chrono::minutes(7);
657 duration += std::chrono::seconds(10);
658 duration += std::chrono::milliseconds(400);
659
660 EXPECT_EQ(resultTime, duration);
661
662 time = "7:10.45";
663 resultTime = math::stringToDuration(time);
664 duration = std::chrono::steady_clock::duration::zero();
665 duration += std::chrono::minutes(7);
666 duration += std::chrono::seconds(10);
667 duration += std::chrono::milliseconds(450);
668
669 EXPECT_EQ(resultTime, duration);
670
671 time = "7:10.456";
672 resultTime = math::stringToDuration(time);
673 duration = std::chrono::steady_clock::duration::zero();
674 duration += std::chrono::minutes(7);
675 duration += std::chrono::seconds(10);
676 duration += std::chrono::milliseconds(456);
677
678 EXPECT_EQ(resultTime, duration);
679
680 time = "2 23:18:25.902";
681 resultTime = math::stringToDuration(time);
682 duration = std::chrono::steady_clock::duration::zero();
683 duration += std::chrono::hours(2 * 24);
684 duration += std::chrono::hours(23);
685 duration += std::chrono::minutes(18);
686 duration += std::chrono::seconds(25);
687 duration += std::chrono::milliseconds(902);
688
689 EXPECT_EQ(resultTime, duration);
690
691 time = ".9";
692 resultTime = math::stringToDuration(time);
693 duration = std::chrono::steady_clock::duration::zero();
694 duration += std::chrono::milliseconds(900);
695
696 EXPECT_EQ(resultTime, duration);
697
698 time = "bad time";
699 resultTime = math::stringToDuration(time);
700
701 EXPECT_EQ(resultTime, std::chrono::steady_clock::duration::zero());
702
703 time = "";
704 resultTime = math::stringToDuration(time);
705
706 EXPECT_EQ(resultTime, std::chrono::steady_clock::duration::zero());
707
708 time = "60";
709 resultTime = math::stringToDuration(time);
710
711 EXPECT_EQ(resultTime, std::chrono::steady_clock::duration::zero());
712
713 time = "60:12";
714 resultTime = math::stringToDuration(time);
715
716 EXPECT_EQ(resultTime, std::chrono::steady_clock::duration::zero());
717
718 time = "12:12.9999";
719 resultTime = math::stringToDuration(time);
720
721 EXPECT_EQ(resultTime, std::chrono::steady_clock::duration::zero());
722
723 time = "25:12:12.99";
724 resultTime = math::stringToDuration(time);
725
726 EXPECT_EQ(resultTime, std::chrono::steady_clock::duration::zero());
727
728 time = "999999999999999 5:12:12.5";
729 resultTime = math::stringToDuration(time);
730
731 EXPECT_EQ(resultTime, std::chrono::steady_clock::duration::zero());
732 }
733
734 /////////////////////////////////////////////////
735 TEST(HelpersTest, secNsecToDuration)
736 {
737 std::chrono::steady_clock::duration point =
738 std::chrono::steady_clock::duration::zero();
739 point += std::chrono::hours(24);
740
741 std::chrono::steady_clock::duration s =
742 math::secNsecToDuration(24*60*60, 0);
743 EXPECT_EQ(s, point);
744
745 point = std::chrono::steady_clock::duration::zero();
746 point += std::chrono::nanoseconds(1000);
747 s = math::secNsecToDuration(0, 1000);
748 EXPECT_EQ(s, point);
749 }
750
751 /////////////////////////////////////////////////
752 TEST(HelpersTest, stringToTimePoint)
753 {
754 using namespace std::chrono_literals;
755
756 std::chrono::steady_clock::time_point zeroTime{0s};
757 std::chrono::steady_clock::time_point negTime{-1s};
758
759 std::string time = "0 00:00:00.000";
760 std::chrono::steady_clock::time_point resultTime =
761 math::stringToTimePoint(time);
762 std::chrono::steady_clock::time_point point = zeroTime;
763
764 EXPECT_EQ(resultTime, point);
765
766 time = "10 0";
767 resultTime = math::stringToTimePoint(time);
768 point = zeroTime;
769 point += std::chrono::hours(10 * 24);
770
771 EXPECT_EQ(resultTime, point);
772
773 time = "7";
774 resultTime = math::stringToTimePoint(time);
775 point = zeroTime;
776 point += std::chrono::seconds(7);
777
778 EXPECT_EQ(resultTime, point);
779
780 time = "7:10";
781 resultTime = math::stringToTimePoint(time);
782 point = zeroTime;
783 point += std::chrono::minutes(7);
784 point += std::chrono::seconds(10);
785
786 EXPECT_EQ(resultTime, point);
787
788 time = "17:10";
789 resultTime = math::stringToTimePoint(time);
790 point = zeroTime;
791 point += std::chrono::minutes(17);
792 point += std::chrono::seconds(10);
793
794 EXPECT_EQ(resultTime, point);
795
796 time = "7:10.4";
797 resultTime = math::stringToTimePoint(time);
798 point = zeroTime;
799 point += std::chrono::minutes(7);
800 point += std::chrono::seconds(10);
801 point += std::chrono::milliseconds(400);
802
803 EXPECT_EQ(resultTime, point);
804
805 time = "7:10.45";
806 resultTime = math::stringToTimePoint(time);
807 point = zeroTime;
808 point += std::chrono::minutes(7);
809 point += std::chrono::seconds(10);
810 point += std::chrono::milliseconds(450);
811
812 EXPECT_EQ(resultTime, point);
813
814 time = "7:10.456";
815 resultTime = math::stringToTimePoint(time);
816 point = zeroTime;
817 point += std::chrono::minutes(7);
818 point += std::chrono::seconds(10);
819 point += std::chrono::milliseconds(456);
820
821 EXPECT_EQ(resultTime, point);
822
823 time = "2 23:18:25.902";
824 resultTime = math::stringToTimePoint(time);
825 point = zeroTime;
826 point += std::chrono::hours(2 * 24);
827 point += std::chrono::hours(23);
828 point += std::chrono::minutes(18);
829 point += std::chrono::seconds(25);
830 point += std::chrono::milliseconds(902);
831
832 EXPECT_EQ(resultTime, point);
833
834 time = ".9";
835 resultTime = math::stringToTimePoint(time);
836 point = zeroTime;
837 point += std::chrono::milliseconds(900);
838
839 EXPECT_EQ(resultTime, point);
840
841 time = "bad time";
842 resultTime = math::stringToTimePoint(time);
843
844 EXPECT_EQ(resultTime, negTime);
845
846 time = "";
847 resultTime = math::stringToTimePoint(time);
848
849 EXPECT_EQ(resultTime, negTime);
850
851 time = "60";
852 resultTime = math::stringToTimePoint(time);
853
854 EXPECT_EQ(resultTime, negTime);
855
856 time = "60:12";
857 resultTime = math::stringToTimePoint(time);
858
859 EXPECT_EQ(resultTime, negTime);
860
861 time = "12:12.9999";
862 resultTime = math::stringToTimePoint(time);
863
864 EXPECT_EQ(resultTime, negTime);
865
866 time = "25:12:12.99";
867 resultTime = math::stringToTimePoint(time);
868
869 EXPECT_EQ(resultTime, negTime);
870
871 time = "999999999999999 5:12:12.5";
872 resultTime = math::stringToTimePoint(time);
873
874 EXPECT_EQ(resultTime, negTime);
875 }
876
877 /////////////////////////////////////////////////
521878 TEST(HelpersTest, durationToSecNsec)
522879 {
523880 std::pair<int64_t, int64_t> parts;
475475 EXPECT_TRUE(trueCubeMM3.SetFromBox(8*mass, 2*size));
476476 EXPECT_EQ(addedCube, math::Inertiald(trueCubeMM3, math::Pose3d::Zero));
477477 }
478
479 // Add two cubes with diagonal corners touching at one point
480 // ┌---------┐
481 // | |
482 // | |
483 // | |
484 // | |
485 // ┌---------+---------┘
486 // | |
487 // | |
488 // | |
489 // | |
490 // └---------┘
491 {
492 // properties of each cube to be added
493 // side length: 1
494 // mass: 6
495 // diagonal moment of inertia values: 1
496 // off-diagonal moment of inertia values: 0
497 const double mass = 6.0;
498 const math::Vector3d size(1, 1, 1);
499 math::MassMatrix3d cubeMM3;
500 EXPECT_TRUE(cubeMM3.SetFromBox(mass, size));
501 EXPECT_EQ(
502 ignition::math::Vector3d::One,
503 cubeMM3.DiagonalMoments());
504 EXPECT_EQ(
505 ignition::math::Vector3d::Zero,
506 cubeMM3.OffDiagonalMoments());
507
508 const math::Inertiald diagonalCubes =
509 math::Inertiald(cubeMM3, math::Pose3d(-0.5, -0.5, -0.5, 0, 0, 0)) +
510 math::Inertiald(cubeMM3, math::Pose3d(0.5, 0.5, 0.5, 0, 0, 0));
511
512 // lumped mass = 6 + 6 = 12
513 // lumped center of mass at (0, 0, 0)
514 // lumped Moment of inertia:
515 // for each cube
516 // [ 1 0 0 ] [ 0.5^2 + 0.5^2 -0.5*0.5 -0.5*0.5 ]
517 // [ 0 1 0 ] + 6 * [ -0.5*0.5 0.5^2 + 0.5^2 -0.5*0.5 ]
518 // [ 0 0 1 ] [ -0.5*0.5 -0.5*0.5 0.5^2 + 0.5^2 ]
519 //
520 // [ 1 0 0 ] [ 0.5 -0.25 -0.25 ]
521 // [ 0 1 0 ] + 6 * [ -0.25 0.5 -0.25 ]
522 // [ 0 0 1 ] [ -0.25 -0.25 0.5 ]
523 //
524 // [ 1 0 0 ] [ 3.0 -1.5 -1.5 ]
525 // [ 0 1 0 ] + [ -1.5 3.0 -1.5 ]
526 // [ 0 0 1 ] [ -1.5 -1.5 3.0 ]
527 //
528 // [ 4.0 -1.5 -1.5 ]
529 // [ -1.5 4.0 -1.5 ]
530 // [ -1.5 -1.5 4.0 ]
531 //
532 // then double it to account for both cubes
533 EXPECT_EQ(ignition::math::Pose3d::Zero, diagonalCubes.Pose());
534 EXPECT_DOUBLE_EQ(mass * 2.0, diagonalCubes.MassMatrix().Mass());
535 EXPECT_EQ(
536 ignition::math::Vector3d(8, 8, 8),
537 diagonalCubes.MassMatrix().DiagonalMoments());
538 EXPECT_EQ(
539 ignition::math::Vector3d(-3, -3, -3),
540 diagonalCubes.MassMatrix().OffDiagonalMoments());
541 }
478542 }
479543
480544 /////////////////////////////////////////////////
1414 *
1515 */
1616
17 #include <ignition/math/Kmeans.hh>
18
1719 #include <iostream>
18 #include <ignition/math/Kmeans.hh>
20
1921 #include <ignition/math/Rand.hh>
2022 #include "KmeansPrivate.hh"
2123
146148 this->dataPtr->sums[i] / this->dataPtr->counters[i];
147149 }
148150 }
149 while (changed > (this->dataPtr->obs.size() >> 10));
151 while (changed > (this->dataPtr->obs.size() >> 10)); // NOLINT
150152
151153 _centroids = this->dataPtr->centroids;
152154 _labels = this->dataPtr->labels;
2020 #include "ignition/math/Pose3.hh"
2121
2222 using namespace ignition;
23
24 /////////////////////////////////////////////////
25 TEST(PoseTest, Construction)
26 {
27 math::Pose3d pose(1, 0, 0, 0, 0, 0);
28
29 // Copy constructor
30 math::Pose3d pose2(pose);
31 EXPECT_EQ(pose2, pose);
32
33 // Copy operator
34 math::Pose3d pose3;
35 pose3 = pose;
36 EXPECT_EQ(pose3, pose);
37
38 // Move constructor
39 math::Pose3d pose4(std::move(pose));
40 EXPECT_EQ(pose4, pose2);
41 pose = pose4;
42 EXPECT_EQ(pose, pose2);
43
44 // Move operator
45 math::Pose3d pose5;
46 pose5 = std::move(pose2);
47 EXPECT_EQ(pose5, pose3);
48 pose2 = pose5;
49 EXPECT_EQ(pose2, pose3);
50
51 // Inequality
52 math::Pose3d pose6;
53 EXPECT_NE(pose6, pose3);
54 }
2355
2456 /////////////////////////////////////////////////
2557 TEST(PoseTest, Pose)
139171 /////////////////////////////////////////////////
140172 TEST(PoseTest, ConstPose)
141173 {
142 const math::Pose3d pose(0, 1, 2, 0, 0, 0);
174 const math::Pose3d pose(0, 1, 2, 1, 0, 0);
143175
144176 EXPECT_TRUE(pose.Pos() == math::Vector3d(0, 1, 2));
145 EXPECT_TRUE(pose.Rot() == math::Quaterniond(0, 0, 0));
177 EXPECT_TRUE(pose.Rot() == math::Quaterniond(1, 0, 0));
146178 }
147179
148180 /////////////////////////////////////////////////
154186 EXPECT_EQ(stream.str(), "0.1 1.2 2.3 0 0.1 1");
155187 }
156188
189 /////////////////////////////////////////////////
190 TEST(PoseTest, MutablePose)
191 {
192 math::Pose3d pose(0, 1, 2, 0, 0, 0);
193
194 EXPECT_TRUE(pose.Pos() == math::Vector3d(0, 1, 2));
195 EXPECT_TRUE(pose.Rot() == math::Quaterniond(0, 0, 0));
196
197 pose.Pos() = math::Vector3d(10, 20, 30);
198 pose.Rot() = math::Quaterniond(1, 2, 1);
199
200 EXPECT_TRUE(pose.Pos() == math::Vector3d(10, 20, 30));
201 EXPECT_TRUE(pose.Rot() == math::Quaterniond(1, 2, 1));
202 }
203
204 /////////////////////////////////////////////////
205 TEST(PoseTest, ConstPoseElements)
206 {
207 const math::Pose3d pose(0, 1, 2, 1, 1, 2);
208 EXPECT_DOUBLE_EQ(pose.X(), 0);
209 EXPECT_DOUBLE_EQ(pose.Y(), 1);
210 EXPECT_DOUBLE_EQ(pose.Z(), 2);
211 EXPECT_DOUBLE_EQ(pose.Roll(), 1);
212 EXPECT_DOUBLE_EQ(pose.Pitch(), 1);
213 EXPECT_DOUBLE_EQ(pose.Yaw(), 2);
214 }
215
216 /////////////////////////////////////////////////
217 TEST(PoseTest, SetPoseElements)
218 {
219 math::Pose3d pose(1, 2, 3, 1.57, 1, 2);
220 EXPECT_DOUBLE_EQ(pose.X(), 1);
221 EXPECT_DOUBLE_EQ(pose.Y(), 2);
222 EXPECT_DOUBLE_EQ(pose.Z(), 3);
223
224 pose.SetX(10);
225 pose.SetY(12);
226 pose.SetZ(13);
227
228 EXPECT_DOUBLE_EQ(pose.X(), 10);
229 EXPECT_DOUBLE_EQ(pose.Y(), 12);
230 EXPECT_DOUBLE_EQ(pose.Z(), 13);
231 }
2626 using namespace ignition;
2727
2828 /////////////////////////////////////////////////
29 TEST(QuaternionTest, Construction)
30 {
31 math::Quaterniond q(0, 0, 0, 1);
32
33 // Copy constructor
34 math::Quaterniond q2(q);
35 EXPECT_EQ(q2, q);
36
37 // Copy operator
38 math::Quaterniond q3;
39 q3 = q;
40 EXPECT_EQ(q3, q);
41
42 // Move constructor
43 math::Quaterniond q4(std::move(q));
44 EXPECT_EQ(q4, q2);
45 q = q4;
46 EXPECT_EQ(q, q2);
47
48 // Move operator
49 math::Quaterniond q5;
50 q5 = std::move(q2);
51 EXPECT_EQ(q5, q3);
52 q2 = q5;
53 EXPECT_EQ(q2, q3);
54
55 // Inequality
56 math::Quaterniond q6;
57 EXPECT_NE(q6, q3);
58 }
59
60 /////////////////////////////////////////////////
2961 TEST(QuaternionTest, Unit)
3062 {
3163 math::Quaterniond q;
211243 }
212244
213245 /////////////////////////////////////////////////
214 TEST(QuaternionTest, Math)
246 TEST(QuaternionTest, MathLog)
215247 {
216248 math::Quaterniond q(IGN_PI*0.1, IGN_PI*0.5, IGN_PI);
217 EXPECT_TRUE(q == math::Quaterniond(0.110616, -0.698401, 0.110616, 0.698401));
218
219 EXPECT_TRUE(q.Log() ==
220 math::Quaterniond(0, -1.02593, 0.162491, 1.02593));
221
222 EXPECT_TRUE(q.Exp() ==
223 math::Quaterniond(0.545456, -0.588972, 0.093284, 0.588972));
249
250 EXPECT_EQ(q.Log(), math::Quaterniond(0, -1.02593, 0.162491, 1.02593));
224251
225252 math::Quaterniond q1 = q;
226253 q1.W(2.0);
227 EXPECT_TRUE(q1.Log() ==
228 math::Quaterniond(0, -0.698401, 0.110616, 0.698401));
229
254 EXPECT_EQ(q1.Log(), math::Quaterniond(0, -0.698401, 0.110616, 0.698401));
255 }
256
257 /////////////////////////////////////////////////
258 TEST(QuaternionTest, MathExp)
259 {
260 math::Quaterniond q(IGN_PI*0.1, IGN_PI*0.5, IGN_PI);
261
262 EXPECT_EQ(q.Exp(),
263 math::Quaterniond(0.545456, -0.588972, 0.093284, 0.588972));
264
265 math::Quaterniond q1 = q;
230266 q1.X(0.000000001);
231267 q1.Y(0.0);
232268 q1.Z(0.0);
233269 q1.W(0.0);
234 EXPECT_TRUE(q1.Exp() == math::Quaterniond(1, 0, 0, 0));
270 EXPECT_EQ(q1.Exp(), math::Quaterniond(1, 0, 0, 0));
271 }
272
273 /////////////////////////////////////////////////
274 TEST(QuaternionTest, MathInvert)
275 {
276 math::Quaterniond q(IGN_PI*0.1, IGN_PI*0.5, IGN_PI);
235277
236278 q.Invert();
237 EXPECT_TRUE(q == math::Quaterniond(0.110616, 0.698401, -0.110616, -0.698401));
279 EXPECT_EQ(q, math::Quaterniond(0.110616, 0.698401, -0.110616, -0.698401));
280 }
281
282 /////////////////////////////////////////////////
283 TEST(QuaternionTest, MathAxis)
284 {
285 math::Quaterniond q(IGN_PI*0.1, IGN_PI*0.5, IGN_PI);
238286
239287 q.Axis(0, 1, 0, IGN_PI);
240 EXPECT_TRUE(q == math::Quaterniond(6.12303e-17, 0, 1, 0));
288 EXPECT_EQ(q, math::Quaterniond(6.12303e-17, 0, 1, 0));
241289
242290 q.Axis(math::Vector3d(1, 0, 0), IGN_PI);
243 EXPECT_TRUE(q == math::Quaterniond(0, 1, 0, 0));
291 EXPECT_EQ(q, math::Quaterniond(0, 1, 0, 0));
292 }
293
294 /////////////////////////////////////////////////
295 TEST(QuaternionTest, MathSet)
296 {
297 math::Quaterniond q(IGN_PI*0.1, IGN_PI*0.5, IGN_PI);
244298
245299 q.Set(1, 2, 3, 4);
246300 EXPECT_TRUE(math::equal(q.W(), 1.0));
247301 EXPECT_TRUE(math::equal(q.X(), 2.0));
248302 EXPECT_TRUE(math::equal(q.Y(), 3.0));
249303 EXPECT_TRUE(math::equal(q.Z(), 4.0));
304 }
305
306 /////////////////////////////////////////////////
307 TEST(QuaternionTest, MathNormalized)
308 {
309 math::Quaterniond q(1, 2, 3, 4);
310
311 math::Quaterniond q2 = q.Normalized();
312 EXPECT_EQ(q2, math::Quaterniond(0.182574, 0.365148, 0.547723, 0.730297));
313 }
314
315 /////////////////////////////////////////////////
316 TEST(QuaternionTest, MathNormalize)
317 {
318 math::Quaterniond q(1, 2, 3, 4);
250319
251320 q.Normalize();
252 EXPECT_TRUE(q == math::Quaterniond(0.182574, 0.365148, 0.547723, 0.730297));
253
321 EXPECT_EQ(q, math::Quaterniond(0.182574, 0.365148, 0.547723, 0.730297));
322 }
323
324 /////////////////////////////////////////////////
325 TEST(QuaternionTest, Math)
326 {
327 math::Quaterniond q(IGN_PI*0.1, IGN_PI*0.5, IGN_PI);
328 EXPECT_TRUE(q == math::Quaterniond(0.110616, -0.698401, 0.110616, 0.698401));
329
330 q.Set(1, 2, 3, 4);
331
332 q.Normalize();
254333
255334 EXPECT_TRUE(math::equal(q.Roll(), 1.4289, 1e-3));
256335 EXPECT_TRUE(math::equal(q.Pitch(), -0.339837, 1e-3));
511590 }
512591
513592 /////////////////////////////////////////////////
514 TEST(QuaterniondTest, From2Axes)
593 TEST(QuaternionTest, From2Axes)
515594 {
516595 math::Vector3d v1(1.0, 0.0, 0.0);
517596 math::Vector3d v2(0.0, 1.0, 0.0);
0 /*
1 * Copyright (C) 2020 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16
17 %module rand
18 %{
19 #include <ignition/math/Rand.hh>
20 %}
21
22 namespace ignition
23 {
24 namespace math
25 {
26 class Rand
27 {
28 public: static void Seed(unsigned int _seed);
29 public: static unsigned int Seed();
30 public: static double DblUniform(double _min, double _max);
31 public: static double DblNormal(double _mean, double _sigma);
32 public: static int IntUniform(int _min, int _max);
33 public: static int IntNormal(int _mean, int _sigma);
34 };
35 }
36 }
0 # Copyright (C) 2020 Open Source Robotics Foundation
1 #
2 # Licensed under the Apache License, Version 2.0 (the "License")
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
5 #
6 # http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 #!/usr/bin/env ruby
15
16 require 'test/unit/ui/console/testrunner'
17 require 'test/unit'
18 require 'math'
19
20 class Rand_TEST < Test::Unit::TestCase
21 def test_rand
22 d = Ignition::Math::Rand::DblUniform(1, 2)
23 assert(d >= 1 && d <= 2, "The value should be 1 <= d <= 2")
24
25 i = Ignition::Math::Rand::IntUniform(1, 2)
26 assert(i >= 1 && i <= 2, "The value should be 1 <= i <= 2")
27
28 Ignition::Math::Rand::Seed(1001)
29
30 i = Ignition::Math::Rand::IntNormal(10, 5)
31 assert(i == 11, "The value should be 11")
32 end
33 end
34
35 exit Test::Unit::UI::Console::TestRunner.run(Rand_TEST).passed? ? 0 : -1
1515 */
1616
1717 #include <numeric>
18 #include <limits>
1819 #include <deque>
1920 #include "ignition/math/RollingMean.hh"
2021
9393 EXPECT_EQ(s.Interpolate(0, 0.5),
9494 math::Quaterniond(0.987225, 0.077057, 0.11624, 0.077057));
9595
96 math::Quaterniond q = s.Interpolate(1, 0.5);
9796 EXPECT_EQ(s.Interpolate(1, 0.5),
9897 math::Quaterniond(0.987225, 0.077057, 0.11624, 0.077057));
9998 }
6666 {
6767 // Workaround to compare the two vector of vectors in MSVC 2013
6868 // and MSVC 2015. See
69 // https://bitbucket.org/ignitionrobotics/ign-math/issues/70
69 // https://github.com/ignitionrobotics/ign-math/issues/70
7070 if (this->derivatives.size() != _other.derivatives.size())
7171 return false;
7272
4545 public: void Normalize();
4646 public: void Set(T _x, T _y);
4747 public: T Dot(const Vector2<T> &_v) const;
48 public: Vector2 Abs() const;
49 public: T AbsDot(const Vector2<T> &_v) const;
50 public: inline void Correct();
51 public: void Max(const Vector2<T> &_v);
52 public: void Min(const Vector2<T> &_v);
53 public: T Max() const;
54 public: T Min() const;
4855 public: Vector2 operator+(const Vector2 &_v) const;
4956 public: inline Vector2<T> operator+(const T _s) const;
5057 public: inline Vector2 operator-() const;
2323 using namespace ignition;
2424
2525 /////////////////////////////////////////////////
26 TEST(Vector2Test, Construction)
27 {
28 math::Vector2d vec(1, 0);
29
30 // Copy constructor
31 math::Vector2d vec2(vec);
32 EXPECT_EQ(vec2, vec);
33
34 // Copy operator
35 math::Vector2d vec3;
36 vec3 = vec;
37 EXPECT_EQ(vec3, vec);
38
39 // Move constructor
40 math::Vector2d vec4(std::move(vec));
41 EXPECT_EQ(vec4, vec2);
42 vec = vec4;
43 EXPECT_EQ(vec, vec2);
44
45 // Move operator
46 math::Vector2d vec5;
47 vec5 = std::move(vec2);
48 EXPECT_EQ(vec5, vec3);
49 vec2 = vec5;
50 EXPECT_EQ(vec2, vec3);
51
52 // Inequality
53 math::Vector2d vec6;
54 EXPECT_NE(vec6, vec3);
55 }
56
57 /////////////////////////////////////////////////
2658 TEST(Vector2Test, Vector2)
2759 {
2860 {
4375 v.Normalize();
4476 EXPECT_TRUE(v == math::Vector2d(0.447214, 0.894427));
4577
78 // ::Rounded
79 v.Set(3.55, 8.49);
80 EXPECT_TRUE(v.Rounded() == math::Vector2d(4, 8));
81
82 // ::Round
83 v.Round();
84 EXPECT_TRUE(v == math::Vector2d(4, 8));
85
4686 // ::Set
4787 v.Set(4, 5);
4888 EXPECT_TRUE(v == math::Vector2d(4, 5));
89
90 // operator GetAbs
91 v.Set(-1, -2);
92 EXPECT_TRUE(v.Abs() == math::Vector2d(1, 2));
4993
5094 // ::operator=
5195 v = math::Vector2d(6, 7);
111155 v.Set(10, 6);
112156 v *= math::Vector2d(2, 4);
113157 EXPECT_TRUE(v == math::Vector2d(20, 24));
114
115158
116159 // ::IsFinite
117160 EXPECT_TRUE(v.IsFinite());
124167 }
125168
126169 /////////////////////////////////////////////////
170 TEST(Vector2Test, TestSum)
171 {
172 math::Vector2 vec1(0, 0);
173 math::Vector2 vec2(1.0, 2.5);
174 math::Vector2 vec3(-2, -4);
175
176 int sum1 = vec1.Sum();
177 float sum2 = vec2.Sum();
178 int sum3 = vec3.Sum();
179
180 EXPECT_EQ(sum1, 0);
181 EXPECT_FLOAT_EQ(sum2, 3.5);
182 EXPECT_EQ(sum3, -6);
183 }
184
185 /////////////////////////////////////////////////
186 TEST(Vector2Test, TestNormalized)
187 {
188 math::Vector2d vec1(0, 0);
189 math::Vector2d vec2(1, 2);
190
191 math::Vector2d vec3 = vec1.Normalized();
192
193 // O zero vector should be equal to the normalized vector
194 EXPECT_EQ(vec1, vec3);
195 EXPECT_NE(vec2, vec3);
196
197 vec3 = vec2.Normalized();
198 EXPECT_EQ(vec3, math::Vector2d(0.447213, 0.894427));
199 }
200
201 /////////////////////////////////////////////////
202 TEST(Vector2Test, Max)
203 {
204 math::Vector2d vec1(0.1, 0.2);
205 math::Vector2d vec2(0.3, 0.5);
206 math::Vector2d vec3(0.4, 0.2);
207
208 EXPECT_DOUBLE_EQ(vec1.Max(), 0.2);
209 EXPECT_DOUBLE_EQ(vec3.Max(), 0.4);
210
211 vec1.Max(vec2);
212 EXPECT_EQ(vec1, math::Vector2d(0.3, 0.5));
213
214 vec1.Max(vec3);
215 EXPECT_EQ(vec1, math::Vector2d(0.4, 0.5));
216 }
217
218 /////////////////////////////////////////////////
219 TEST(Vector2Test, Min)
220 {
221 math::Vector2d vec1(0.3, 0.5);
222 math::Vector2d vec2(0.1, 0.2);
223 math::Vector2d vec3(0.05, 0.1);
224
225 EXPECT_DOUBLE_EQ(vec1.Min(), 0.3);
226 EXPECT_DOUBLE_EQ(vec3.Min(), 0.05);
227
228 vec1.Min(vec2);
229 EXPECT_EQ(vec1, math::Vector2d(0.1, 0.2));
230
231 vec1.Min(vec3);
232 EXPECT_EQ(vec1, math::Vector2d(0.05, 0.1));
233 }
234
235 /////////////////////////////////////////////////
127236 TEST(Vector2Test, NoException)
128237 {
129238 math::Vector2d v(1, 2);
156265 EXPECT_DOUBLE_EQ(v.Dot(math::Vector2d(0, 1)), 2.0);
157266 }
158267
268 //////////////////////////////////////////////
269 TEST(Vector2Test, Correct)
270 {
271 math::Vector2d vec1(0, NAN);
272 math::Vector2d vec2(INFINITY, -1);
273 math::Vector2d vec3(10, -2);
274
275 vec1.Correct();
276 vec2.Correct();
277 vec3.Correct();
278
279 EXPECT_EQ(vec1, math::Vector2d(0, 0));
280 EXPECT_EQ(vec2, math::Vector2d(0, -1));
281 EXPECT_EQ(vec3, math::Vector2d(10, -2));
282 }
283
284 /////////////////////////////////////////////////
285 TEST(Vector2Test, AbsDot)
286 {
287 math::Vector2d v(1, -2);
288
289 EXPECT_DOUBLE_EQ(v.AbsDot(math::Vector2d(3, 4)), 11.0);
290 EXPECT_DOUBLE_EQ(v.AbsDot(math::Vector2d(0, 0)), 0.0);
291 EXPECT_DOUBLE_EQ(v.AbsDot(math::Vector2d(1, 0)), 1.0);
292 EXPECT_DOUBLE_EQ(v.AbsDot(math::Vector2d(0, 1)), 2.0);
293 }
294
159295 /////////////////////////////////////////////////
160296 TEST(Vector2Test, OperatorStreamOut)
161297 {
166302 }
167303
168304 /////////////////////////////////////////////////
169 TEST(Vector2dTest, Add)
305 TEST(Vector2Test, Add)
170306 {
171307 math::Vector2d vec1(0.1, 0.2);
172308 math::Vector2d vec2(1.1, 2.2);
207343 }
208344
209345 /////////////////////////////////////////////////
210 TEST(Vector2dTest, Sub)
346 TEST(Vector2Test, Sub)
211347 {
212348 math::Vector2d vec1(0.1, 0.2);
213349 math::Vector2d vec2(1.1, 2.2);
285421 }
286422
287423 /////////////////////////////////////////////////
288 TEST(Vector2dTest, Length)
424 TEST(Vector2Test, Length)
289425 {
290426 // Zero vector
291427 EXPECT_DOUBLE_EQ(math::Vector2d::Zero.Length(), 0.0);
107107 "Zero should equal 1 with 1.1 tolerance")
108108 end
109109
110 def test_max
111 vec1 = Ignition::Math::Vector2d.new(0.1, 0.2)
112 vec2 = Ignition::Math::Vector2d.new(0.3, 0.5)
113 vec3 = Ignition::Math::Vector2d.new(0.4, 0.2)
114
115 assert((vec1.Max() - 0.2).abs() < 1e-10,
116 "Vector2 vec1.Max should equal 0.2")
117
118 vec1.Max(vec2)
119 assert(vec1 == Ignition::Math::Vector2d.new(0.3, 0.5),
120 "Vector2 vec1 should equal [0.3, 0.5]")
121
122 vec1.Max(vec3)
123 assert(vec1 == Ignition::Math::Vector2d.new(0.4, 0.5),
124 "Vector2 vec1 should equal [0.4, 0.5]")
125 end
126
127 def test_min
128 vec1 = Ignition::Math::Vector2d.new(0.3, 0.5)
129 vec2 = Ignition::Math::Vector2d.new(0.1, 0.2)
130 vec3 = Ignition::Math::Vector2d.new(0.05, 0.1)
131
132 assert((vec1.Min() - 0.3).abs() < 1e-10,
133 "Vector2 vec1.Min should equal 0.3")
134
135 vec1.Min(vec2)
136 assert(vec1 == Ignition::Math::Vector2d.new(0.1, 0.2),
137 "Vector2 vec1 should equal [0.1, 0.2]")
138
139 vec3.Max(vec2)
140 assert(vec3 == Ignition::Math::Vector2d.new(0.1, 0.2),
141 "Vector2 vec3 should equal [0.1, 0.2]")
142 end
143
110144 def test_dot
111145 v = Ignition::Math::Vector2d.new(1, 2)
112146
1616
1717 #include <gtest/gtest.h>
1818
19 #include <numeric>
20 #include <sstream>
21
1922 #include "ignition/math/Vector3.hh"
2023 #include "ignition/math/Helpers.hh"
2124
2225 using namespace ignition;
2326
2427 /////////////////////////////////////////////////
25 TEST(Vector3Test, Vector3d)
28 TEST(Vector3dTest, Construction)
29 {
30 math::Vector3d vec(1, 0, 0);
31
32 // Copy constructor
33 math::Vector3d vec2(vec);
34 EXPECT_EQ(vec2, vec);
35
36 // Copy operator
37 math::Vector3d vec3;
38 vec3 = vec;
39 EXPECT_EQ(vec3, vec);
40
41 // Move constructor
42 math::Vector3d vec4(std::move(vec));
43 EXPECT_EQ(vec4, vec2);
44 vec = vec4;
45 EXPECT_EQ(vec, vec2);
46
47 // Move operator
48 math::Vector3d vec5;
49 vec5 = std::move(vec2);
50 EXPECT_EQ(vec5, vec3);
51 vec2 = vec5;
52 EXPECT_EQ(vec2, vec3);
53
54 // Inequality
55 math::Vector3d vec6;
56 EXPECT_NE(vec6, vec3);
57 }
58
59 /////////////////////////////////////////////////
60 TEST(Vector3dTest, Vector3d)
2661 {
2762 math::Vector3d v;
2863
386421
387422 /////////////////////////////////////////////////
388423 // Test Equal function with specified tolerance
389 TEST(Vector2Test, EqualTolerance)
424 TEST(Vector3dTest, EqualTolerance)
390425 {
391426 EXPECT_FALSE(math::Vector3d::Zero.Equal(math::Vector3d::One, 1e-6));
392427 EXPECT_FALSE(math::Vector3d::Zero.Equal(math::Vector3d::One, 1e-3));
413448
414449 EXPECT_NO_THROW(math::equal(v[3], 4.0));
415450 EXPECT_DOUBLE_EQ(v[3], 3.0);
416 }
417
451
452 std::ostringstream ss;
453 math::Vector3d vInf(0, 0, std::numeric_limits<double>::infinity());
454 EXPECT_NO_THROW(ss << vInf);
455 }
456
0 /*
1 * Copyright (C) 2016 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16
17 #ifdef SWIGRUBY
18 %begin %{
19 #define HAVE_ISFINITE 1
20 %}
21 #endif
22
23 %module vector4
24 %{
25 #include <ignition/math/Vector4.hh>
26 %}
27
28 namespace ignition
29 {
30 namespace math
31 {
32 template<typename T>
33 class Vector4
34 {
35 public: static const Vector4 Zero;
36 public: static const Vector4 One;
37 public: Vector4();
38 public: Vector4(const T &_x, const T &_y, const T &_z, const T &_w);
39 public: Vector4(const Vector4<T> &_v);
40 public: virtual ~Vector4();
41 public: T Distance(const Vector4<T> &_pt) const;
42 public: T Length() const;
43 public: T SquaredLength() const;
44 public: void Normalize();
45 public: inline void Set(T _x = 0, T _y = 0, T _z = 0, T _w = 0);
46 public: Vector4 operator+(const Vector4<T> &_v) const;
47 public: inline Vector4<T> operator+(const T _s) const;
48 public: inline Vector4 operator-() const;
49 public: inline Vector4<T> operator-(const Vector4<T> &_pt) const;
50 public: inline Vector4<T> operator-(const T _s) const;
51 public: const Vector4<T> operator/(const Vector4<T> &_pt) const;
52 public: const Vector4<T> operator/(T _v) const;
53 public: Vector4<T> operator*(const Vector4<T> &_p) const;
54 public: inline Vector4<T> operator*(T _s) const;
55 public: bool operator==(const Vector4<T> &_v) const;
56 public: bool Equal(const Vector4 &_v, const T &_tol) const;
57 public: bool IsFinite() const;
58 public: inline T X() const;
59 public: inline T Y() const;
60 public: inline T Z() const;
61 public: inline T W() const;
62 public: inline void X(const T &_v);
63 public: inline void Y(const T &_v);
64 public: inline void Z(const T &_v);
65 public: inline void W(const T &_v);
66 };
67
68 %template(Vector4i) Vector4<int>;
69 %template(Vector4d) Vector4<double>;
70 %template(Vector4f) Vector4<float>;
71 }
72 }
2323 using namespace ignition;
2424
2525 /////////////////////////////////////////////////
26 TEST(Vector4dTest, Construction)
27 {
28 math::Vector4d vec(1, 0, 0, 0);
29
30 // Copy constructor
31 math::Vector4d vec2(vec);
32 EXPECT_EQ(vec2, vec);
33
34 // Copy operator
35 math::Vector4d vec3;
36 vec3 = vec;
37 EXPECT_EQ(vec3, vec);
38
39 // Move constructor
40 math::Vector4d vec4(std::move(vec));
41 EXPECT_EQ(vec4, vec2);
42 vec = vec4;
43 EXPECT_EQ(vec, vec2);
44
45 // Move operator
46 math::Vector4d vec5;
47 vec5 = std::move(vec2);
48 EXPECT_EQ(vec5, vec3);
49 vec2 = vec5;
50 EXPECT_EQ(vec2, vec3);
51
52 // Inequality
53 math::Vector4d vec6;
54 EXPECT_NE(vec6, vec3);
55 }
56
57 /////////////////////////////////////////////////
2658 TEST(Vector4dTest, Vector4d)
2759 {
2860 {
4274 math::Vector4d v(v1);
4375 EXPECT_EQ(v, v1);
4476
77 // ::Distance
4578 EXPECT_TRUE(math::equal(v.Distance(
4679 math::Vector4d(0, 0, 0, 0)), 5.4772, 1e-3));
80 EXPECT_TRUE(math::equal(v.Distance(1, 2, 3, 4), 0.0));
4781
4882 // ::Length()
4983 v.Set(1, 2, 3, 4);
5286 // ::SquaredLength()
5387 EXPECT_TRUE(math::equal(v.SquaredLength(), 30.0));
5488
89 // ::Rounded
90 v.Set(1.23, 2.34, 3.55, 8.49);
91 EXPECT_TRUE(v.Rounded() == math::Vector4d(1, 2, 4, 8));
92
93 // ::Round
94 v.Round();
95 EXPECT_TRUE(v == math::Vector4d(1, 2, 4, 8));
96
97 // ::Correct
98 v.Set(1, 1, std::nan("1"), 1);
99 v.Correct();
100 EXPECT_TRUE(v == math::Vector4d(1, 1, 0, 1));
101
55102 // ::Normalize
103 v.Set(1, 2, 3, 4);
56104 v.Normalize();
57105 EXPECT_EQ(v, math::Vector4d(0.182574, 0.365148, 0.547723, 0.730297));
106
107 // ::Normalized
108 v.Set(1, 2, 3, 4);
109 EXPECT_EQ(v.Normalized(),
110 math::Vector4d(0.182574, 0.365148, 0.547723, 0.730297));
58111
59112 // ::Set
60113 v.Set(2, 4, 6, 8);
61114 EXPECT_EQ(v, math::Vector4d(2, 4, 6, 8));
115
116 // ::DotProd
117 EXPECT_TRUE(math::equal(60.0, v.Dot(math::Vector4d(1, 2, 3, 4)), 1e-2));
118
119 // ::AbsDotProd
120 v1.Set(-1, -2, -3, -4);
121 EXPECT_TRUE(math::equal(60.0, v.AbsDot(v1), 1e-2));
122
123 // ::GetAbs
124 EXPECT_TRUE(v1.Abs() == math::Vector4d(1, 2, 3, 4));
125 EXPECT_TRUE(v.Abs() == math::Vector4d(2, 4, 6, 8));
62126
63127 // ::operator= vector4
64128 v = v1;
127191
128192 // ::operator != vector4
129193 EXPECT_NE(v, math::Vector4d());
194
195 // ::operator < vector4
196 v.Set(1, 2, 3, 4);
197 EXPECT_TRUE(v < math::Vector4d(4, 3, 2, 1));
130198
131199 // ::IsFinite
132200 EXPECT_TRUE(v.IsFinite());
156224 }
157225
158226 /////////////////////////////////////////////////
227 TEST(Vector4dTest, Max)
228 {
229 math::Vector4d vec1(0.1, 0.2, 0.3, 0.2);
230 math::Vector4d vec2(0.2, 0.3, 0.4, 0.3);
231 math::Vector4d vec3(0.1, 0.2, 0.3, 0.4);
232
233 EXPECT_DOUBLE_EQ(vec1.Max(), 0.3);
234
235 vec1.Max(vec2);
236 EXPECT_EQ(vec1, math::Vector4d(0.2, 0.3, 0.4, 0.3));
237
238 vec1.Max(vec3);
239 EXPECT_EQ(vec1, math::Vector4d(0.2, 0.3, 0.4, 0.4));
240 }
241
242 /////////////////////////////////////////////////
243 TEST(Vector4dTest, Min)
244 {
245 math::Vector4d vec1(0.1, 0.2, 0.3, 0.4);
246 math::Vector4d vec2(0.2, 0.3, 0.4, 0.3);
247 math::Vector4d vec3(0.05, 0.1, 0.2, 0.2);
248
249 EXPECT_DOUBLE_EQ(vec1.Min(), 0.1);
250
251 vec1.Min(vec2);
252 EXPECT_EQ(vec1, math::Vector4d(0.1, 0.2, 0.3, 0.3));
253
254 vec1.Min(vec3);
255 EXPECT_EQ(vec1, math::Vector4d(0.05, 0.1, 0.2, 0.2));
256 }
257
258 /////////////////////////////////////////////////
159259 // Test Equal function with specified tolerance
160 TEST(Vector2Test, EqualTolerance)
260 TEST(Vector4dTest, EqualTolerance)
161261 {
162262 EXPECT_FALSE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1e-6));
163263 EXPECT_FALSE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1e-3));
164264 EXPECT_FALSE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1e-1));
165265 EXPECT_TRUE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1));
166266 EXPECT_TRUE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1.1));
267 }
268
269 /////////////////////////////////////////////////
270 TEST(Vector4dTest, Sum)
271 {
272 math::Vector4d vec1(1.5, 2.5, 3.5, -4.5);
273
274 EXPECT_TRUE(math::equal(math::Vector4d::Zero.Sum(), 0.0, 1e-6));
275 EXPECT_TRUE(math::equal(math::Vector4d::One.Sum(), 4.0, 1e-6));
276 EXPECT_TRUE(math::equal(vec1.Sum(), 3.0, 1e-6));
167277 }
168278
169279 /////////////////////////////////////////////////
258368 }
259369
260370 /////////////////////////////////////////////////
261 TEST(Vector4Test, Multiply)
371 TEST(Vector4dTest, Multiply)
262372 {
263373 math::Vector4d v(0.1, -4.2, 11.1, 8.4);
264374
0 # Copyright (C) 2016 Open Source Robotics Foundation
1 #
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
5 #
6 # http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 #!/usr/bin/env ruby
15
16 require 'test/unit/ui/console/testrunner'
17 require 'test/unit'
18 require 'math'
19
20
21 class Vector4_TEST < Test::Unit::TestCase
22 def test_construction
23 v = Ignition::Math::Vector4d.new
24
25 # ::operator== vector4
26 assert(true,
27 "Vector4d::Zero should equal [0, 0, 0, 0]")
28
29 # ::Distance, ::Length()
30 v.Set(1, 2, 3, 4)
31 assert(v.Length() == v.Distance(Ignition::Math::Vector4d.Zero),
32 "Vector4d::Lenth() should equal Vector4d::Distance(zero)")
33
34 # ::operator/ vector4
35 v.Set(4, 4, 4, 4)
36 v = v / Ignition::Math::Vector4d.new(1, 2, 2, 4)
37 assert(v == Ignition::Math::Vector4d.new(4, 2, 2, 1),
38 "v / Vector4d(1, 2, 2, 4) should equal Vector4d(4, 2, 2, 1)")
39
40 # ::operator / double
41 v = v / 2
42 assert(v == Ignition::Math::Vector4d.new(2, 1, 1, 0.5),
43 "v / 2 should equal Vector4d(2, 1, 1, .5)")
44
45 # ::operator * vector4
46 v = v * Ignition::Math::Vector4d.new(2, 3, 3, 4)
47 assert(v == Ignition::Math::Vector4d.new(4, 3, 3, 2),
48 "v * Vector4d(2, 3, 3, 4) should equal Vector4d(4, 3, 3, 2)")
49
50 # operator /=
51 v.Set(1, 2, 2, 4)
52 v /= Ignition::Math::Vector4d.new(1, 4, 8, 4)
53 assert(v == Ignition::Math::Vector4d.new(1, 0.5, 0.25, 1))
54
55 # operator *=
56 v.Set(1, 2, 2, 4)
57 v *= Ignition::Math::Vector4d.new(2, 0.5, 0.25, 0.1)
58 assert(v == Ignition::Math::Vector4d.new(2, 1, 0.5, 0.4))
59
60 # Test the static defines.
61 assert(Ignition::Math::Vector4d.Zero ==
62 Ignition::Math::Vector4d.new(0, 0, 0, 0),
63 "Vector4d::Zero should equal [0, 0, 0, 0]")
64
65 assert(Ignition::Math::Vector4d.One ==
66 Ignition::Math::Vector4d.new(1, 1, 1, 1),
67 "Vector4d::One should equal [1, 1, 1, 1]")
68 end
69
70 def test_distance
71 vec1 = Ignition::Math::Vector4d.new(0, 0, 0, 0)
72 vec2 = Ignition::Math::Vector4d.new(1, 2, 3, 4)
73
74 dist = vec1.Distance(vec2)
75 assert((dist - 5.47722557505).abs() < 1e-6,
76 "Vector4 distance should be near 5,47722557505")
77 end
78
79 def test_squared_length
80 vec1 = Ignition::Math::Vector4d.new(0, 0, 0, 0)
81 vec2 = Ignition::Math::Vector4d.new(1, 2, 3, 4)
82
83 sum1 = vec1.SquaredLength()
84 sum2 = vec2.SquaredLength()
85
86 assert(sum1 == 0, "Vector4 sum1 should equal 0")
87 assert(sum2 == 30, "Vector4 sum2 should equal 30")
88 end
89
90 def test_length
91 # Zero vector
92 assert(Ignition::Math::Vector4d.Zero.Length() == 0.0,
93 "Vector4 length of [0, 0, 0, 0] should equal 0")
94 assert(Ignition::Math::Vector4d.Zero.SquaredLength() == 0.0,
95 "Vector4 squared length of [0, 0, 0, 0] should equal 0")
96
97 # One vector
98 assert((Ignition::Math::Vector4d.One.Length() -
99 Math.sqrt(4.0)).abs() < 1e-10,
100 "Vector4 length of [1, 1, 1, 1] should equal sqrt(4.0)")
101
102 assert(Ignition::Math::Vector4d.One.SquaredLength() == 4.0,
103 "Vector4 squared lenght of [1, 1, 1, 1] should equal 4.0")
104
105 # Arbitrary vector
106 v = Ignition::Math::Vector4d.new(0.1, -4.2, 2.5, -1.2)
107 assert((v.Length() - 5.03388517946).abs() < 1e-10,
108 "Vector4 v length should equal 5.03388517946")
109
110 assert((v.SquaredLength() - 25.34).abs() < 1e-10 ,
111 "Vector4 v squared length should equal 25.34")
112 end
113
114 def test_normalize
115 vec1 = Ignition::Math::Vector4d.new(0, 0, 0, 0)
116 vec2 = Ignition::Math::Vector4d.new(1, 2, 3, 4)
117
118 vec3 = vec1
119 vec3.Normalize()
120 assert(vec3 == vec1, "Vector4 vec3 should equal vec1")
121 assert(vec1 == Ignition::Math::Vector4d.Zero,
122 "Vector4 should equal [0, 0, 0, 0]")
123
124 vec3 = vec2
125 vec2.Normalize()
126 assert(vec2.Equal(Ignition::Math::Vector4d.new(0.182575, 0.365150, 0.547725, 0.730300), 1e-5),
127 "Vector4 vec3 should equal [0.182575, 0.365150, 0.547725, 0.730300]")
128 end
129
130 def test_add
131 vec1 = Ignition::Math::Vector4d.new(0.1, 0.2, 0.4, 0.8)
132 vec2 = Ignition::Math::Vector4d.new(1.1, 2.2, 3.4, 4.3)
133
134 vec3 = vec1
135 vec3 += vec2
136
137 assert(vec1 + vec2 == Ignition::Math::Vector4d.new(1.2, 2.4, 3.8, 5.1),
138 "Vector4 vec1 + vec2 should equal [1.2, 2.4, 3.8, 4.9]")
139 assert(vec3 == Ignition::Math::Vector4d.new(1.2, 2.4, 3.8, 5.1),
140 "Vector4 vec3 should equal [1.2, 2.4, 3.8, 4.9]")
141
142 # Addition with zeros
143
144 # Scalar left and right
145 assert(vec1 + 0 == vec1, "Vector4 vec1+0 should equal vec1")
146
147 # Vector left and right
148 assert(Ignition::Math::Vector4d.Zero + vec1 == vec1,
149 "Vector4 Zero + vec1 should equal vec1")
150 assert(vec1 + Ignition::Math::Vector4d.Zero == vec1,
151 "Vector4 vec1 + Zero should equal vec1")
152
153 # Addition assignment
154 vec4 = vec1
155 vec4 += 0
156 assert(vec4 == vec1, "Vector4 vec4 should equal vec1")
157 vec4 += Ignition::Math::Vector4d.Zero
158 assert(vec4 == vec1, "Vector4 vec4 should equal vec1")
159
160 # Add non-trivial scalar values left and right
161 assert(vec1 + 2.5 == Ignition::Math::Vector4d.new(2.6, 2.7, 2.9, 3.3),
162 "Vector4 vec1 + 2.5 should equal [2.6, 2.7, 2.9, 3.3]")
163
164 vec1 = vec4
165 vec4 += 2.5
166 assert(vec4 == Ignition::Math::Vector4d.new(2.6, 2.7, 2.9, 3.3),
167 "Vector4 vec4 should equal [2.6, 2.7, 2.9, 3.3]")
168 end
169
170 def test_sub
171 vec1 = Ignition::Math::Vector4d.new(0.1, 0.2, 0.4, 0.8)
172 vec2 = Ignition::Math::Vector4d.new(1.1, 2.2, 3.4, 4.3)
173
174 vec3 = vec2
175 vec3 -= vec1
176
177 assert(vec2 - vec1 === Ignition::Math::Vector4d.new(1.0, 2.0, 3.0, 3.5),
178 "Vector4 vec2 - vec1 should equal [1.0, 2.0, 3.0, 3.5]")
179 assert(vec3 == Ignition::Math::Vector4d.new(1.0, 2.0, 3.0, 3.5),
180 "Vector4 vec3 should equal [1.0, 2.0, 3.0, 3.5]")
181
182 # Subtraction with zeros
183
184 # Scalar left and right
185 assert(vec1 - 0 == vec1, "Vector4 vec1 - 0 should equal vec1")
186
187 # Vector left and right
188 assert(Ignition::Math::Vector4d.Zero - vec1 == -vec1,
189 "Vector4 Zero - vec1 should equal -vec1")
190 assert(vec1 - Ignition::Math::Vector4d.Zero == vec1,
191 "Vector4 vec1 - Zero should equal vec1")
192
193 # Subtraction assignment
194 vec4 = vec1
195 vec4 -= 0
196 assert(vec4 == vec1, "Vector4 vec4 should equal vec1")
197 vec4 -= Ignition::Math::Vector4d.Zero
198 assert(vec4 == vec1, "Vector4 vec4 should equal vec1")
199
200 # Subtract non-trivial scalar values left and right
201 assert(vec1 - 2.5 == -Ignition::Math::Vector4d.new(2.4, 2.3, 2.1, 1.7),
202 "Vecetor3 vec1 - 2.5 should equal [2.4, 2.3, 2.1, 1.7]")
203
204 vec4 = vec1
205 vec4 -= 2.5
206 assert(vec4 == -Ignition::Math::Vector4d.new(2.4, 2.3, 2.1, 1.7),
207 "Vector4 vec4 - 2.5 should equal [2.4, 2.3, 2.1, 1.7]")
208 end
209
210 def test_divide
211 vec1 = Ignition::Math::Vector4d.new(0.1, 0.2, 0.4, 0.8)
212
213 vec3 = vec1 / 2.0
214 assert(vec3 == Ignition::Math::Vector4d.new(0.05, 0.1, 0.2, 0.4),
215 "Vector4 vec3 should equal [0.05, 0.1, 0.2, 0.4]")
216
217 vec3 /= 4.0
218 assert(vec3 == Ignition::Math::Vector4d.new(0.0125, 0.025, 0.05, 0.1),
219 "Vector4 vec3 should qual [0.0125, 0.025, 0.05, 0.1]")
220 end
221
222 def test_multiply
223 v = Ignition::Math::Vector4d.new(0.1, 0.2, 0.3, 0.4)
224
225 vec3 = v * 2.0
226 assert(vec3 == Ignition::Math::Vector4d.new(0.2, 0.4, 0.6, 0.8),
227 "Vector4 vec3 should equal[0.2, 0.4, 0.6, 0.8]")
228
229 vec3 *= 4.0
230 assert(vec3 == Ignition::Math::Vector4d.new(0.8, 1.6, 2.4, 3.2),
231 "Vector4 vec3 should equal [0.8, 1.6, 2.4, 3.2]")
232
233 # Multiply by zero
234
235 # Scalar left and right
236 assert(v * 0 == Ignition::Math::Vector4d.Zero,
237 "Vector4 v * 0 should equal Zero")
238
239 # Element-wise vector multiplication
240 assert(v * Ignition::Math::Vector4d.Zero == Ignition::Math::Vector4d.Zero,
241 "Vector4 v * Zero should equal Zero")
242
243 # Multiply by one
244
245 # Scalar left and right
246 assert(v * 1 == v, "Vector4 v * 1 should equal v")
247
248 # Element-wise vector multiplication
249 assert(v * Ignition::Math::Vector4d.One == v,
250 "Vector4 v * One should equal v")
251
252 # Multiply by non-trivial scalar value
253
254 scalar = 2.5
255 expect = Ignition::Math::Vector4d.new(0.25, 0.5, 0.75, 1.0)
256 assert(v * scalar == expect,
257 "Vector4 v * scalar should equal [0.25, 0.5, 0.75, 1.0]")
258
259 # Multiply by itself element-wise
260 assert(v*v == Ignition::Math::Vector4d.new(0.01, 0.04, 0.09, 0.16),
261 "Vector4 v * v should euqal [0.01, 0.04, 0.09, 0.16]")
262 end
263
264 def test_not_equal
265 vec1 = Ignition::Math::Vector4d.new(0.1, 0.2, 0.3, 0.4)
266 vec2 = Ignition::Math::Vector4d.new(0.2, 0.2, 0.3, 0.4)
267 vec3 = Ignition::Math::Vector4d.new(0.1, 0.2, 0.3, 0.4)
268
269 assert(vec1 != vec2, "Vector4 vec1 should not equal vec2")
270 assert(!(vec1 != vec3), "Vector4 vec1 should equal vec3" )
271 end
272
273 def test_equal
274 assert(!Ignition::Math::Vector4d.Zero.Equal(
275 Ignition::Math::Vector4d.One, 1e-6),
276 "Vector4 Zero should not equal 1 with tolerance of 1e-6")
277 assert(!Ignition::Math::Vector4d.Zero.Equal(
278 Ignition::Math::Vector4d.One, 1e-3),
279 "Vector4 Zero should not equal 1 with tolerance of 1e-3")
280 assert(!Ignition::Math::Vector4d.Zero.Equal(
281 Ignition::Math::Vector4d.One, 1e-1),
282 "Vector4 Zero should not equal 1 with tolerance of 1e-1")
283
284 assert(Ignition::Math::Vector4d.Zero.Equal(
285 Ignition::Math::Vector4d.One, 1),
286 "Vector4 Zero should equal 1 with tolerance of 1")
287 assert(Ignition::Math::Vector4d.Zero.Equal(
288 Ignition::Math::Vector4d.One, 1.1),
289 "Vector4 Zero should equal 1 with tolerance of 1.1")
290 end
291
292 def test_finite
293 vec1 = Ignition::Math::Vector4d.new(0.1, 0.2, 0.3, 0.4)
294
295 assert(vec1.IsFinite(), "Vector4 vec1 should be be finite")
296 end
297 end
298
299 exit Test::Unit::UI::Console::TestRunner.run(Vector4_TEST).passed? ? 0 : -1
309309 }
310310 }
311311
312 /////////////////////////////////////////////////
313 TEST(GraphTestFixture, ToUndirectedGraph)
314 {
315 /// (6) |
316 /// 0------>1 |
317 /// | /|\ |
318 /// | / | \(5) |
319 /// | (2)/ | ┘ |
320 /// | / | 2 |
321 /// (1)| / (2)| / |
322 /// | / | /(5) |
323 /// VL VL |
324 /// 3------>4 |
325 /// (1) |
326 DirectedGraph<int, double> directed(
327 {
328 // Vertices.
329 {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}, {"3", 3, 3}, {"4", 4, 4}},
330 // Edges.
331 {{{0, 1}, 2.0, 6.0}, {{0, 3}, 3.0, 1.0},
332 {{1, 2}, 4.0, 5.0}, {{1, 3}, 4.0, 2.0}, {{1, 4}, 4.0, 2.0},
333 {{2, 4}, 2.0, 5.0},
334 {{3, 4}, 2.0, 1.0}}
335 });
336
337 // Convert to undirected graph.
338 auto undirected = ToUndirectedGraph(directed);
339 EXPECT_EQ(5u, undirected.Vertices().size());
340 EXPECT_EQ(7u, undirected.Edges().size());
341 EXPECT_EQ(directed.Vertices().size(), undirected.Vertices().size());
342 EXPECT_EQ(directed.Edges().size(), undirected.Edges().size());
343
344 // Compare vertices.
345 for (auto const &dvPair : directed.Vertices())
346 {
347 const VertexId dvId = dvPair.first;
348 auto const &uv = undirected.VertexFromId(dvId);
349 EXPECT_TRUE(uv.Valid());
350 EXPECT_TRUE(dvPair.second.get().Valid());
351 EXPECT_EQ(uv.Id(), dvId);
352 EXPECT_EQ(uv.Name(), dvPair.second.get().Name());
353 EXPECT_EQ(uv.Data(), dvPair.second.get().Data());
354 }
355
356 // Compare edges.
357 for (auto const &dePair : directed.Edges())
358 {
359 const EdgeId deId = dePair.first;
360 auto const &ue = undirected.EdgeFromId(deId);
361 EXPECT_TRUE(ue.Valid());
362 EXPECT_TRUE(dePair.second.get().Valid());
363 EXPECT_EQ(ue.Id(), deId);
364 EXPECT_DOUBLE_EQ(ue.Data(), dePair.second.get().Data());
365 EXPECT_DOUBLE_EQ(ue.Weight(), dePair.second.get().Weight());
366 }
367
368 // std::cerr << directed << std::endl;
369 // std::cerr << undirected << std::endl;
370 }
00 %include "Angle.i"
1 %include "GaussMarkovProcess.i"
2 %include "Rand.i"
13 %include "Vector2.i"
24 %include "Vector3.i"
5 %include "Vector4.i"
1919 execute_process(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/test_results)
2020 include_directories(${GTEST_INCLUDE_DIRS})
2121
22 #============================================================================
23 # Do a fake install of ign-math in order to test the examples.
24 #============================================================================
25 set(FAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/fake/install")
26
27 file(MAKE_DIRECTORY ${FAKE_INSTALL_PREFIX})
28
29 include(ExternalProject)
30 ExternalProject_Add(
31 FAKE_INSTALL
32
33 SOURCE_DIR "${CMAKE_SOURCE_DIR}"
34 EXCLUDE_FROM_ALL 1
35 LOG_CONFIGURE 1
36 LOG_BUILD 1
37 LOG_INSTALL 1
38 CMAKE_ARGS
39 "-DBUILD_TESTING=OFF"
40 "-DCMAKE_INSTALL_PREFIX=${FAKE_INSTALL_PREFIX}"
41 )
42
2243 add_subdirectory(integration)
2344 add_subdirectory(performance)
2445 add_subdirectory(regression)
00 set(TEST_TYPE "INTEGRATION")
11
2 set(tests
3 )
4
5 link_directories(${PROJECT_BINARY_DIR}/test)
2 ign_get_sources(tests)
63
74 # Test symbols having the right name on linux only
85 if (UNIX AND NOT APPLE)
129 endif()
1310
1411 ign_build_tests(TYPE INTEGRATION SOURCES ${tests})
12
13 if(TARGET INTEGRATION_ExamplesBuild_TEST)
14 add_dependencies(INTEGRATION_ExamplesBuild_TEST FAKE_INSTALL)
15
16 set(_env_vars)
17 list(APPEND _env_vars "CMAKE_PREFIX_PATH=${FAKE_INSTALL_PREFIX}:$ENV{CMAKE_PREFIX_PATH}")
18 set_tests_properties(INTEGRATION_ExamplesBuild_TEST PROPERTIES
19 ENVIRONMENT "${_env_vars}")
20 endif()
0 /*
1 * Copyright (C) 2019 Open Source Robotics Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16
17 #include <gtest/gtest.h>
18 #include <cstring>
19 #include <fstream>
20 #include <string>
21
22 #include "test_config.h" // NOLINT(build/include)
23
24 #ifdef _WIN32
25 # define IGN_PATH_MAX _MAX_PATH
26 #elif defined(PATH_MAX)
27 # define IGN_PATH_MAX PATH_MAX
28 #elif defined(_XOPEN_PATH_MAX)
29 # define IGN_PATH_MAX _XOPEN_PATH_MAX
30 #else
31 # define IGN_PATH_MAX _POSIX_PATH_MAX
32 #endif
33
34
35 // Helper functions copied from
36 // https://github.com/ignitionrobotics/ign-common/raw/master/src/Filesystem_TEST.cc
37
38 #ifndef _WIN32
39 #include <dirent.h> // NOLINT(build/include_order)
40 #include <fcntl.h> // NOLINT(build/include_order)
41 #include <limits.h> // NOLINT(build/include_order)
42 #include <stdlib.h> // NOLINT(build/include_order)
43 #include <sys/stat.h> // NOLINT(build/include_order)
44 #include <sys/types.h> // NOLINT(build/include_order)
45 #include <unistd.h> // NOLINT(build/include_order)
46
47 /////////////////////////////////////////////////
48 bool createAndSwitchToTempDir(std::string &_newTempPath)
49 {
50 std::string tmppath;
51 const char *tmp = std::getenv("TMPDIR");
52 if (tmp)
53 {
54 tmppath = std::string(tmp);
55 }
56 else
57 {
58 tmppath = std::string("/tmp");
59 }
60
61 tmppath += "/XXXXXX";
62
63 char *dtemp = mkdtemp(const_cast<char *>(tmppath.c_str()));
64 if (dtemp == nullptr)
65 {
66 return false;
67 }
68 if (chdir(dtemp) < 0)
69 {
70 return false;
71 }
72
73 // cppcheck-suppress *
74 char resolved[PATH_MAX];
75 if (realpath(dtemp, resolved) == nullptr)
76 {
77 return false;
78 }
79
80 _newTempPath = std::string(resolved);
81
82 return true;
83 }
84
85 #else
86 #include <io.h> // NOLINT(build/include_order)
87 #include <windows.h> // NOLINT(build/include_order)
88 #include <winioctl.h> // NOLINT(build/include_order)
89 #include <winnt.h> // NOLINT(build/include_order)
90 #include <cstdint>
91 #include "./win_dirent.h"
92
93 /////////////////////////////////////////////////
94 bool createAndSwitchToTempDir(std::string &_newTempPath)
95 {
96 char tempPath[MAX_PATH + 1];
97 DWORD pathLen = ::GetTempPathA(MAX_PATH, tempPath);
98 if (pathLen >= MAX_PATH || pathLen <= 0)
99 {
100 return false;
101 }
102 std::string pathToCreate(tempPath);
103 srand(static_cast<uint32_t>(time(nullptr)));
104
105 for (int count = 0; count < 50; ++count)
106 {
107 // Try creating a new temporary directory with a randomly generated name.
108 // If the one we chose exists, keep trying another path name until we reach
109 // some limit.
110 std::string newDirName;
111 newDirName.append(std::to_string(::GetCurrentProcessId()));
112 newDirName.push_back('_');
113 // On Windows, rand_r() doesn't exist as an alternative to rand(), so the
114 // cpplint warning is spurious. This program is not multi-threaded, so
115 // it is safe to suppress the threadsafe_fn warning here.
116 newDirName.append(
117 std::to_string(rand() // NOLINT(runtime/threadsafe_fn)
118 % ((int16_t)0x7fff)));
119
120 pathToCreate += newDirName;
121 if (::CreateDirectoryA(pathToCreate.c_str(), nullptr))
122 {
123 _newTempPath = pathToCreate;
124 return ::SetCurrentDirectoryA(_newTempPath.c_str()) != 0;
125 }
126 }
127
128 return false;
129 }
130
131 struct handle_wrapper
132 {
133 HANDLE handle;
134 explicit handle_wrapper(HANDLE h)
135 : handle(h) {}
136 ~handle_wrapper()
137 {
138 if (handle != INVALID_HANDLE_VALUE)
139 {
140 ::CloseHandle(handle);
141 }
142 }
143 };
144
145 //////////////////////////////////////////////////
146 HANDLE create_file_handle(const std::string &_path, DWORD _dwDesiredAccess,
147 DWORD _dwShareMode,
148 LPSECURITY_ATTRIBUTES _lpSecurityAttributes,
149 DWORD _dwCreationDisposition,
150 DWORD _dwFlagsAndAttributes,
151 HANDLE _hTemplateFile)
152 {
153 return ::CreateFileA(_path.c_str(), _dwDesiredAccess,
154 _dwShareMode, _lpSecurityAttributes,
155 _dwCreationDisposition, _dwFlagsAndAttributes,
156 _hTemplateFile);
157 }
158
159 //////////////////////////////////////////////////
160 bool not_found_error(int _errval)
161 {
162 return _errval == ERROR_FILE_NOT_FOUND
163 || _errval == ERROR_PATH_NOT_FOUND
164 || _errval == ERROR_INVALID_NAME // "tools/src/:sys:stat.h", "//foo"
165 || _errval == ERROR_INVALID_DRIVE // USB card reader with no card
166 || _errval == ERROR_NOT_READY // CD/DVD drive with no disc inserted
167 || _errval == ERROR_INVALID_PARAMETER // ":sys:stat.h"
168 || _errval == ERROR_BAD_PATHNAME // "//nosuch" on Win64
169 || _errval == ERROR_BAD_NETPATH; // "//nosuch" on Win32
170 }
171
172 #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
173 #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
174 #endif
175
176 typedef struct _REPARSE_DATA_BUFFER {
177 ULONG ReparseTag;
178 USHORT ReparseDataLength;
179 USHORT Reserved;
180 union {
181 struct {
182 USHORT SubstituteNameOffset;
183 USHORT SubstituteNameLength;
184 USHORT PrintNameOffset;
185 USHORT PrintNameLength;
186 ULONG Flags;
187 WCHAR PathBuffer[1];
188 /* Example of distinction between substitute and print names:
189 mklink /d ldrive c:\
190 SubstituteName: c:\\??\
191 PrintName: c:\
192 */
193 } SymbolicLinkReparseBuffer;
194 struct {
195 USHORT SubstituteNameOffset;
196 USHORT SubstituteNameLength;
197 USHORT PrintNameOffset;
198 USHORT PrintNameLength;
199 WCHAR PathBuffer[1];
200 } MountPointReparseBuffer;
201 struct {
202 UCHAR DataBuffer[1];
203 } GenericReparseBuffer;
204 };
205 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
206
207 //////////////////////////////////////////////////
208 bool is_reparse_point_a_symlink(const std::string &_path)
209 {
210 handle_wrapper h(create_file_handle(_path, FILE_READ_EA,
211 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
212 nullptr, OPEN_EXISTING,
213 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
214 nullptr));
215 if (h.handle == INVALID_HANDLE_VALUE)
216 {
217 return false;
218 }
219
220 std::vector<wchar_t> buf(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
221
222 // Query the reparse data
223 DWORD dwRetLen;
224 BOOL result = ::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT,
225 nullptr, 0, buf.data(), (DWORD)buf.size(), &dwRetLen, nullptr);
226 if (!result)
227 {
228 return false;
229 }
230
231 return reinterpret_cast<const REPARSE_DATA_BUFFER*>(&buf[0])->ReparseTag
232 == IO_REPARSE_TAG_SYMLINK
233 // Issue 9016 asked that NTFS directory junctions be recognized as
234 // directories. That is equivalent to recognizing them as symlinks, and
235 // then the normal symlink mechanism will recognize them as directories.
236 //
237 // Directory junctions are very similar to symlinks, but have some
238 // performance and other advantages over symlinks. They can be created
239 // from the command line with "mklink /j junction-name target-path".
240 || reinterpret_cast<const REPARSE_DATA_BUFFER*>(&buf[0])->ReparseTag
241 == IO_REPARSE_TAG_MOUNT_POINT; // "directory junction" or "junction"
242 }
243
244 //////////////////////////////////////////////////
245 bool process_status_failure()
246 {
247 int errval(::GetLastError());
248
249 if (not_found_error(errval))
250 {
251 return false;
252 }
253 else if ((errval == ERROR_SHARING_VIOLATION))
254 {
255 return true; // odd, but this is what boost does
256 }
257 return false;
258 }
259
260 //////////////////////////////////////////////////
261 bool internal_check_path(const std::string &_path, DWORD &attr)
262 {
263 attr = ::GetFileAttributesA(_path.c_str());
264 if (attr == 0xFFFFFFFF)
265 {
266 return process_status_failure();
267 }
268
269 // reparse point handling;
270 // since GetFileAttributesW does not resolve symlinks, try to open file
271 // handle to discover if the file exists
272 if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
273 {
274 handle_wrapper h(
275 create_file_handle(
276 _path,
277 0, // dwDesiredAccess; attributes only
278 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
279 0, // lpSecurityAttributes
280 OPEN_EXISTING,
281 FILE_FLAG_BACKUP_SEMANTICS,
282 0)); // hTemplateFile
283 if (h.handle == INVALID_HANDLE_VALUE)
284 {
285 return process_status_failure();
286 }
287
288 if (!is_reparse_point_a_symlink(_path))
289 {
290 return true;
291 }
292 }
293
294 return true;
295 }
296 #endif
297
298 //////////////////////////////////////////////////
299 bool isDirectory(const std::string &_path)
300 {
301 #ifndef _WIN32
302 struct stat path_stat;
303
304 if (::stat(_path.c_str(), &path_stat) != 0)
305 {
306 return false;
307 }
308
309 // cppcheck-suppress ConfigurationNotChecked
310 return S_ISDIR(path_stat.st_mode);
311 #else
312 DWORD attr;
313
314 if (internal_check_path(_path, attr))
315 {
316 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
317 }
318
319 return false;
320 #endif
321 }
322
323 //////////////////////////////////////////////////
324 bool isFile(const std::string &_path)
325 {
326 std::ifstream f(_path);
327 return (!isDirectory(_path)) && f.good();
328 }
329
330 //////////////////////////////////////////////////
331 void removeAll(const std::string &_path)
332 {
333 if (isDirectory(_path))
334 {
335 DIR *dir = opendir(_path.c_str());
336 if (dir)
337 {
338 struct dirent *p;
339 while ((p=readdir(dir)))
340 {
341 // Skip special files.
342 if (!std::strcmp(p->d_name, ".") || !std::strcmp(p->d_name, ".."))
343 continue;
344
345 removeAll(_path + "/" + p->d_name);
346 }
347 }
348 closedir(dir);
349
350 // Remove the directory
351 bool removed;
352 #ifdef _WIN32
353 removed = RemoveDirectory(_path.c_str());
354 #else
355 removed = (rmdir(_path.c_str()) == 0);
356 if (!removed)
357 {
358 // A sym link would end up here
359 removed = (std::remove(_path.c_str()) == 0);
360 }
361 #endif
362 ASSERT_TRUE(removed);
363 }
364 else if (isFile(_path))
365 {
366 const bool removed = (std::remove(_path.c_str()) == 0);
367 ASSERT_TRUE(removed);
368 }
369 }
370
371 //////////////////////////////////////////////////
372 TEST(ExamplesBuild, Build)
373 {
374 // \todo(nkoenig) Fix windows.
375 #ifndef _WIN32
376 // Path to examples of the given type
377 std::string examplesDir = std::string(PROJECT_SOURCE_PATH) + "/examples/";
378
379 // Create a temp build directory
380 std::string tmpBuildDir;
381 ASSERT_TRUE(createAndSwitchToTempDir(tmpBuildDir));
382 std::cout << "Build directory: " << tmpBuildDir<< std::endl;
383
384 char cmd[1024];
385
386 // cd build && cmake source
387 snprintf(cmd, sizeof(cmd), "cd %s && cmake %s && make",
388 tmpBuildDir.c_str(), examplesDir.c_str());
389 ASSERT_EQ(system(cmd), 0);
390
391 // Remove temp dir
392 removeAll(tmpBuildDir);
393 #endif
394 }
395
396 //////////////////////////////////////////////////
397 int main(int argc, char **argv)
398 {
399 ::testing::InitGoogleTest(&argc, argv);
400 return RUN_ALL_TESTS();
401 }
0 /*
1 * Dirent interface for Microsoft Visual Studio
2 * Version 1.21
3 *
4 * Copyright (C) 2006-2012 Toni Ronkko
5 * This file is part of dirent. Dirent may be freely distributed
6 * under the MIT license. For all details and documentation, see
7 * https://github.com/tronkko/dirent
8 */
9 #ifndef DIRENT_H
10 #define DIRENT_H
11
12 /*
13 * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
14 * Windows Sockets 2.0.
15 */
16 #ifndef WIN32_LEAN_AND_MEAN
17 # define WIN32_LEAN_AND_MEAN
18 #endif
19 #include <windows.h>
20
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <wchar.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <malloc.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <errno.h>
30
31 /* Indicates that d_type field is available in dirent structure */
32 #define _DIRENT_HAVE_D_TYPE
33
34 /* Indicates that d_namlen field is available in dirent structure */
35 #define _DIRENT_HAVE_D_NAMLEN
36
37 /* Entries missing from MSVC 6.0 */
38 #if !defined(FILE_ATTRIBUTE_DEVICE)
39 # define FILE_ATTRIBUTE_DEVICE 0x40
40 #endif
41
42 /* File type and permission flags for stat(), general mask */
43 #if !defined(S_IFMT)
44 # define S_IFMT _S_IFMT
45 #endif
46
47 /* Directory bit */
48 #if !defined(S_IFDIR)
49 # define S_IFDIR _S_IFDIR
50 #endif
51
52 /* Character device bit */
53 #if !defined(S_IFCHR)
54 # define S_IFCHR _S_IFCHR
55 #endif
56
57 /* Pipe bit */
58 #if !defined(S_IFFIFO)
59 # define S_IFFIFO _S_IFFIFO
60 #endif
61
62 /* Regular file bit */
63 #if !defined(S_IFREG)
64 # define S_IFREG _S_IFREG
65 #endif
66
67 /* Read permission */
68 #if !defined(S_IREAD)
69 # define S_IREAD _S_IREAD
70 #endif
71
72 /* Write permission */
73 #if !defined(S_IWRITE)
74 # define S_IWRITE _S_IWRITE
75 #endif
76
77 /* Execute permission */
78 #if !defined(S_IEXEC)
79 # define S_IEXEC _S_IEXEC
80 #endif
81
82 /* Pipe */
83 #if !defined(S_IFIFO)
84 # define S_IFIFO _S_IFIFO
85 #endif
86
87 /* Block device */
88 #if !defined(S_IFBLK)
89 # define S_IFBLK 0
90 #endif
91
92 /* Link */
93 #if !defined(S_IFLNK)
94 # define S_IFLNK 0
95 #endif
96
97 /* Socket */
98 #if !defined(S_IFSOCK)
99 # define S_IFSOCK 0
100 #endif
101
102 /* Read user permission */
103 #if !defined(S_IRUSR)
104 # define S_IRUSR S_IREAD
105 #endif
106
107 /* Write user permission */
108 #if !defined(S_IWUSR)
109 # define S_IWUSR S_IWRITE
110 #endif
111
112 /* Execute user permission */
113 #if !defined(S_IXUSR)
114 # define S_IXUSR 0
115 #endif
116
117 /* Read group permission */
118 #if !defined(S_IRGRP)
119 # define S_IRGRP 0
120 #endif
121
122 /* Write group permission */
123 #if !defined(S_IWGRP)
124 # define S_IWGRP 0
125 #endif
126
127 /* Execute group permission */
128 #if !defined(S_IXGRP)
129 # define S_IXGRP 0
130 #endif
131
132 /* Read others permission */
133 #if !defined(S_IROTH)
134 # define S_IROTH 0
135 #endif
136
137 /* Write others permission */
138 #if !defined(S_IWOTH)
139 # define S_IWOTH 0
140 #endif
141
142 /* Execute others permission */
143 #if !defined(S_IXOTH)
144 # define S_IXOTH 0
145 #endif
146
147 /* Maximum length of file name */
148 #if !defined(PATH_MAX)
149 # define PATH_MAX MAX_PATH
150 #endif
151 #if !defined(FILENAME_MAX)
152 # define FILENAME_MAX MAX_PATH
153 #endif
154 #if !defined(NAME_MAX)
155 # define NAME_MAX FILENAME_MAX
156 #endif
157
158 /* File type flags for d_type */
159 #define DT_UNKNOWN 0
160 #define DT_REG S_IFREG
161 #define DT_DIR S_IFDIR
162 #define DT_FIFO S_IFIFO
163 #define DT_SOCK S_IFSOCK
164 #define DT_CHR S_IFCHR
165 #define DT_BLK S_IFBLK
166 #define DT_LNK S_IFLNK
167
168 /* Macros for converting between st_mode and d_type */
169 #define IFTODT(mode) ((mode) & S_IFMT)
170 #define DTTOIF(type) (type)
171
172 /*
173 * File type macros. Note that block devices, sockets and links cannot be
174 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
175 * only defined for compatibility. These macros should always return false
176 * on Windows.
177 */
178 #if !defined(S_ISFIFO)
179 # define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
180 #endif
181 #if !defined(S_ISDIR)
182 # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
183 #endif
184 #if !defined(S_ISREG)
185 # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
186 #endif
187 #if !defined(S_ISLNK)
188 # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
189 #endif
190 #if !defined(S_ISSOCK)
191 # define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
192 #endif
193 #if !defined(S_ISCHR)
194 # define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
195 #endif
196 #if !defined(S_ISBLK)
197 # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
198 #endif
199
200 /* Return the exact length of d_namlen without zero terminator */
201 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
202
203 /* Return number of bytes needed to store d_namlen */
204 #define _D_ALLOC_NAMLEN(p) (PATH_MAX)
205
206
207 #ifdef __cplusplus
208 extern "C" {
209 #endif
210
211
212 /* Wide-character version */
213 struct _wdirent {
214 /* Always zero */
215 long d_ino;
216
217 /* Structure size */
218 unsigned short d_reclen;
219
220 /* Length of name without \0 */
221 size_t d_namlen;
222
223 /* File type */
224 int d_type;
225
226 /* File name */
227 // cppcheck-suppress *
228 wchar_t d_name[PATH_MAX];
229 };
230 typedef struct _wdirent _wdirent;
231
232 struct _WDIR {
233 /* Current directory entry */
234 struct _wdirent ent;
235
236 /* Private file data */
237 WIN32_FIND_DATAW data;
238
239 /* True if data is valid */
240 int cached;
241
242 /* Win32 search handle */
243 HANDLE handle;
244
245 /* Initial directory name */
246 wchar_t *patt;
247 };
248 typedef struct _WDIR _WDIR;
249
250 static _WDIR *_wopendir (const wchar_t *dirname);
251 static struct _wdirent *_wreaddir (_WDIR *dirp);
252 static int _wclosedir (_WDIR *dirp);
253 static void _wrewinddir (_WDIR* dirp);
254
255
256 /* For compatibility with Symbian */
257 #define wdirent _wdirent
258 #define WDIR _WDIR
259 #define wopendir _wopendir
260 #define wreaddir _wreaddir
261 #define wclosedir _wclosedir
262 #define wrewinddir _wrewinddir
263
264
265 /* Multi-byte character versions */
266 struct dirent {
267 /* Always zero */
268 long d_ino;
269
270 /* Structure size */
271 unsigned short d_reclen;
272
273 /* Length of name without \0 */
274 size_t d_namlen;
275
276 /* File type */
277 int d_type;
278
279 /* File name */
280 // cppcheck-suppress *
281 char d_name[PATH_MAX];
282 };
283 typedef struct dirent dirent;
284
285 struct DIR {
286 struct dirent ent;
287 struct _WDIR *wdirp;
288 };
289 typedef struct DIR DIR;
290
291 static DIR *opendir (const char *dirname);
292 static struct dirent *readdir (DIR *dirp);
293 static int closedir (DIR *dirp);
294 static void rewinddir (DIR* dirp);
295
296
297 /* Internal utility functions */
298 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
299 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
300
301 static int dirent_mbstowcs_s(
302 size_t *pReturnValue,
303 wchar_t *wcstr,
304 size_t sizeInWords,
305 const char *mbstr,
306 size_t count);
307
308 static int dirent_wcstombs_s(
309 size_t *pReturnValue,
310 char *mbstr,
311 size_t sizeInBytes,
312 const wchar_t *wcstr,
313 size_t count);
314
315 static void dirent_set_errno (int error);
316
317 /*
318 * Open directory stream DIRNAME for read and return a pointer to the
319 * internal working area that is used to retrieve individual directory
320 * entries.
321 */
322 static _WDIR*
323 _wopendir(
324 const wchar_t *dirname)
325 {
326 _WDIR *dirp = NULL;
327 int error;
328
329 /* Must have directory name */
330 if (dirname == NULL || dirname[0] == '\0') {
331 dirent_set_errno (ENOENT);
332 return NULL;
333 }
334
335 /* Allocate new _WDIR structure */
336 dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
337 if (dirp != NULL) {
338 DWORD n;
339
340 /* Reset _WDIR structure */
341 dirp->handle = INVALID_HANDLE_VALUE;
342 dirp->patt = NULL;
343 dirp->cached = 0;
344
345 /* Compute the length of full path plus zero terminator
346 *
347 * Note that on WinRT there's no way to convert relative paths
348 * into absolute paths, so just assume its an absolute path.
349 */
350 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
351 n = wcslen(dirname);
352 # else
353 n = GetFullPathNameW (dirname, 0, NULL, NULL);
354 # endif
355
356 /* Allocate room for absolute directory name and search pattern */
357 dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
358 if (dirp->patt) {
359
360 /*
361 * Convert relative directory name to an absolute one. This
362 * allows rewinddir() to function correctly even when current
363 * working directory is changed between opendir() and rewinddir().
364 *
365 * Note that on WinRT there's no way to convert relative paths
366 * into absolute paths, so just assume its an absolute path.
367 */
368 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
369 wcsncpy_s(dirp->patt, n+1, dirname, n);
370 # else
371 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
372 # endif
373 if (n > 0) {
374 wchar_t *p;
375
376 /* Append search pattern \* to the directory name */
377 p = dirp->patt + n;
378 if (dirp->patt < p) {
379 switch (p[-1]) {
380 case '\\':
381 case '/':
382 case ':':
383 /* Directory ends in path separator, e.g. c:\temp\ */
384 /*NOP*/;
385 break;
386
387 default:
388 /* Directory name doesn't end in path separator */
389 *p++ = '\\';
390 }
391 }
392 *p++ = '*';
393 *p = '\0';
394
395 /* Open directory stream and retrieve the first entry */
396 if (dirent_first (dirp)) {
397 /* Directory stream opened successfully */
398 error = 0;
399 } else {
400 /* Cannot retrieve first entry */
401 error = 1;
402 dirent_set_errno (ENOENT);
403 }
404
405 } else {
406 /* Cannot retrieve full path name */
407 dirent_set_errno (ENOENT);
408 error = 1;
409 }
410
411 } else {
412 /* Cannot allocate memory for search pattern */
413 error = 1;
414 }
415
416 } else {
417 /* Cannot allocate _WDIR structure */
418 error = 1;
419 }
420
421 /* Clean up in case of error */
422 if (error && dirp) {
423 _wclosedir (dirp);
424 dirp = NULL;
425 }
426
427 return dirp;
428 }
429
430 /*
431 * Read next directory entry. The directory entry is returned in dirent
432 * structure in the d_name field. Individual directory entries returned by
433 * this function include regular files, sub-directories, pseudo-directories
434 * "." and ".." as well as volume labels, hidden files and system files.
435 */
436 static struct _wdirent*
437 _wreaddir(
438 _WDIR *dirp)
439 {
440 WIN32_FIND_DATAW *datap;
441 struct _wdirent *entp;
442
443 /* Read next directory entry */
444 datap = dirent_next (dirp);
445 if (datap) {
446 size_t n;
447 DWORD attr;
448
449 /* Pointer to directory entry to return */
450 entp = &dirp->ent;
451
452 /*
453 * Copy file name as wide-character string. If the file name is too
454 * long to fit in to the destination buffer, then truncate file name
455 * to PATH_MAX characters and zero-terminate the buffer.
456 */
457 n = 0;
458 // cppcheck-suppress *
459 while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
460 entp->d_name[n] = datap->cFileName[n];
461 n++;
462 }
463 dirp->ent.d_name[n] = 0;
464
465 /* Length of file name excluding zero terminator */
466 entp->d_namlen = n;
467
468 /* File type */
469 attr = datap->dwFileAttributes;
470 // cppcheck-suppress *
471 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
472 // cppcheck-suppress *
473 entp->d_type = DT_CHR;
474 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
475 // cppcheck-suppress *
476 entp->d_type = DT_DIR;
477 } else {
478 // cppcheck-suppress *
479 entp->d_type = DT_REG;
480 }
481
482 /* Reset dummy fields */
483 entp->d_ino = 0;
484 entp->d_reclen = sizeof (struct _wdirent);
485
486 } else {
487
488 /* Last directory entry read */
489 entp = NULL;
490
491 }
492
493 return entp;
494 }
495
496 /*
497 * Close directory stream opened by opendir() function. This invalidates the
498 * DIR structure as well as any directory entry read previously by
499 * _wreaddir().
500 */
501 static int
502 _wclosedir(
503 _WDIR *dirp)
504 {
505 int ok;
506 if (dirp) {
507
508 /* Release search handle */
509 if (dirp->handle != INVALID_HANDLE_VALUE) {
510 FindClose (dirp->handle);
511 dirp->handle = INVALID_HANDLE_VALUE;
512 }
513
514 /* Release search pattern */
515 if (dirp->patt) {
516 free (dirp->patt);
517 dirp->patt = NULL;
518 }
519
520 /* Release directory structure */
521 free (dirp);
522 ok = /*success*/0;
523
524 } else {
525 /* Invalid directory stream */
526 dirent_set_errno (EBADF);
527 ok = /*failure*/-1;
528 }
529 return ok;
530 }
531
532 /*
533 * Rewind directory stream such that _wreaddir() returns the very first
534 * file name again.
535 */
536 static void
537 _wrewinddir(
538 _WDIR* dirp)
539 {
540 if (dirp) {
541 /* Release existing search handle */
542 if (dirp->handle != INVALID_HANDLE_VALUE) {
543 FindClose (dirp->handle);
544 }
545
546 /* Open new search handle */
547 dirent_first (dirp);
548 }
549 }
550
551 /* Get first directory entry (internal) */
552 static WIN32_FIND_DATAW*
553 dirent_first(
554 _WDIR *dirp)
555 {
556 WIN32_FIND_DATAW *datap;
557
558 /* Open directory and retrieve the first entry */
559 dirp->handle = FindFirstFileExW(
560 dirp->patt, FindExInfoStandard, &dirp->data,
561 FindExSearchNameMatch, NULL, 0);
562 if (dirp->handle != INVALID_HANDLE_VALUE) {
563
564 /* a directory entry is now waiting in memory */
565 datap = &dirp->data;
566 dirp->cached = 1;
567
568 } else {
569
570 /* Failed to re-open directory: no directory entry in memory */
571 dirp->cached = 0;
572 datap = NULL;
573
574 }
575 return datap;
576 }
577
578 /* Get next directory entry (internal) */
579 static WIN32_FIND_DATAW*
580 dirent_next(
581 _WDIR *dirp)
582 {
583 WIN32_FIND_DATAW *p;
584
585 /* Get next directory entry */
586 if (dirp->cached != 0) {
587
588 /* A valid directory entry already in memory */
589 p = &dirp->data;
590 dirp->cached = 0;
591
592 } else if (dirp->handle != INVALID_HANDLE_VALUE) {
593
594 /* Get the next directory entry from stream */
595 if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
596 /* Got a file */
597 p = &dirp->data;
598 } else {
599 /* The very last entry has been processed or an error occured */
600 FindClose (dirp->handle);
601 dirp->handle = INVALID_HANDLE_VALUE;
602 p = NULL;
603 }
604
605 } else {
606
607 /* End of directory stream reached */
608 p = NULL;
609
610 }
611
612 return p;
613 }
614
615 /*
616 * Open directory stream using plain old C-string.
617 */
618 static DIR*
619 opendir(
620 const char *dirname)
621 {
622 struct DIR *dirp;
623 int error;
624
625 /* Must have directory name */
626 if (dirname == NULL || dirname[0] == '\0') {
627 dirent_set_errno (ENOENT);
628 return NULL;
629 }
630
631 /* Allocate memory for DIR structure */
632 dirp = (DIR*) malloc (sizeof (struct DIR));
633 if (dirp) {
634 // cppcheck-suppress *
635 wchar_t wname[PATH_MAX];
636 size_t n;
637
638 /* Convert directory name to wide-character string */
639 // cppcheck-suppress *
640 error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
641 if (!error) {
642
643 /* Open directory stream using wide-character name */
644 dirp->wdirp = _wopendir (wname);
645 if (dirp->wdirp) {
646 /* Directory stream opened */
647 error = 0;
648 } else {
649 /* Failed to open directory stream */
650 error = 1;
651 }
652
653 } else {
654 /*
655 * Cannot convert file name to wide-character string. This
656 * occurs if the string contains invalid multi-byte sequences or
657 * the output buffer is too small to contain the resulting
658 * string.
659 */
660 error = 1;
661 }
662
663 } else {
664 /* Cannot allocate DIR structure */
665 error = 1;
666 }
667
668 /* Clean up in case of error */
669 if (error && dirp) {
670 free (dirp);
671 dirp = NULL;
672 }
673
674 return dirp;
675 }
676
677 /*
678 * Read next directory entry.
679 *
680 * When working with text consoles, please note that file names returned by
681 * readdir() are represented in the default ANSI code page while any output to
682 * console is typically formatted on another code page. Thus, non-ASCII
683 * characters in file names will not usually display correctly on console. The
684 * problem can be fixed in two ways: (1) change the character set of console
685 * to 1252 using chcp utility and use Lucida Console font, or (2) use
686 * _cprintf function when writing to console. The _cprinf() will re-encode
687 * ANSI strings to the console code page so many non-ASCII characters will
688 * display correcly.
689 */
690 static struct dirent*
691 readdir(
692 DIR *dirp)
693 {
694 WIN32_FIND_DATAW *datap;
695 struct dirent *entp;
696
697 /* Read next directory entry */
698 datap = dirent_next (dirp->wdirp);
699 if (datap) {
700 size_t n;
701 int error;
702
703 /* Attempt to convert file name to multi-byte string */
704 error = dirent_wcstombs_s(
705 // cppcheck-suppress *
706 &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
707
708 /*
709 * If the file name cannot be represented by a multi-byte string,
710 * then attempt to use old 8+3 file name. This allows traditional
711 * Unix-code to access some file names despite of unicode
712 * characters, although file names may seem unfamiliar to the user.
713 *
714 * Be ware that the code below cannot come up with a short file
715 * name unless the file system provides one. At least
716 * VirtualBox shared folders fail to do this.
717 */
718 if (error && datap->cAlternateFileName[0] != '\0') {
719 error = dirent_wcstombs_s(
720 // cppcheck-suppress *
721 &n, dirp->ent.d_name, PATH_MAX,
722 // cppcheck-suppress *
723 datap->cAlternateFileName, PATH_MAX);
724 }
725
726 if (!error) {
727 DWORD attr;
728
729 /* Initialize directory entry for return */
730 entp = &dirp->ent;
731
732 /* Length of file name excluding zero terminator */
733 entp->d_namlen = n - 1;
734
735 /* File attributes */
736 attr = datap->dwFileAttributes;
737 // cppcheck-suppress *
738 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
739 // cppcheck-suppress *
740 entp->d_type = DT_CHR;
741 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
742 // cppcheck-suppress *
743 entp->d_type = DT_DIR;
744 } else {
745 // cppcheck-suppress *
746 entp->d_type = DT_REG;
747 }
748
749 /* Reset dummy fields */
750 entp->d_ino = 0;
751 entp->d_reclen = sizeof (struct dirent);
752
753 } else {
754 /*
755 * Cannot convert file name to multi-byte string so construct
756 * an errornous directory entry and return that. Note that
757 * we cannot return NULL as that would stop the processing
758 * of directory entries completely.
759 */
760 entp = &dirp->ent;
761 entp->d_name[0] = '?';
762 entp->d_name[1] = '\0';
763 entp->d_namlen = 1;
764 entp->d_type = DT_UNKNOWN;
765 entp->d_ino = 0;
766 entp->d_reclen = 0;
767 }
768
769 } else {
770 /* No more directory entries */
771 entp = NULL;
772 }
773
774 return entp;
775 }
776
777 /*
778 * Close directory stream.
779 */
780 static int
781 closedir(
782 DIR *dirp)
783 {
784 int ok;
785 if (dirp) {
786
787 /* Close wide-character directory stream */
788 ok = _wclosedir (dirp->wdirp);
789 dirp->wdirp = NULL;
790
791 /* Release multi-byte character version */
792 free (dirp);
793
794 } else {
795
796 /* Invalid directory stream */
797 dirent_set_errno (EBADF);
798 ok = /*failure*/-1;
799
800 }
801 return ok;
802 }
803
804 /*
805 * Rewind directory stream to beginning.
806 */
807 static void
808 rewinddir(
809 DIR* dirp)
810 {
811 /* Rewind wide-character string directory stream */
812 _wrewinddir (dirp->wdirp);
813 }
814
815 /* Convert multi-byte string to wide character string */
816 static int
817 dirent_mbstowcs_s(
818 size_t *pReturnValue,
819 wchar_t *wcstr,
820 size_t sizeInWords,
821 const char *mbstr,
822 size_t count)
823 {
824 int error;
825
826 #if defined(_MSC_VER) && _MSC_VER >= 1400
827
828 /* Microsoft Visual Studio 2005 or later */
829 error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
830
831 #else
832
833 /* Older Visual Studio or non-Microsoft compiler */
834 size_t n;
835
836 /* Convert to wide-character string (or count characters) */
837 n = mbstowcs (wcstr, mbstr, sizeInWords);
838 if (!wcstr || n < count) {
839
840 /* Zero-terminate output buffer */
841 if (wcstr && sizeInWords) {
842 if (n >= sizeInWords) {
843 n = sizeInWords - 1;
844 }
845 wcstr[n] = 0;
846 }
847
848 /* Length of resuting multi-byte string WITH zero terminator */
849 if (pReturnValue) {
850 *pReturnValue = n + 1;
851 }
852
853 /* Success */
854 error = 0;
855
856 } else {
857
858 /* Could not convert string */
859 error = 1;
860
861 }
862
863 #endif
864
865 return error;
866 }
867
868 /* Convert wide-character string to multi-byte string */
869 static int
870 dirent_wcstombs_s(
871 size_t *pReturnValue,
872 char *mbstr,
873 size_t sizeInBytes, /* max size of mbstr */
874 const wchar_t *wcstr,
875 size_t count)
876 {
877 int error;
878
879 #if defined(_MSC_VER) && _MSC_VER >= 1400
880
881 /* Microsoft Visual Studio 2005 or later */
882 error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
883
884 #else
885
886 /* Older Visual Studio or non-Microsoft compiler */
887 size_t n;
888
889 /* Convert to multi-byte string (or count the number of bytes needed) */
890 n = wcstombs (mbstr, wcstr, sizeInBytes);
891 if (!mbstr || n < count) {
892
893 /* Zero-terminate output buffer */
894 if (mbstr && sizeInBytes) {
895 if (n >= sizeInBytes) {
896 n = sizeInBytes - 1;
897 }
898 mbstr[n] = '\0';
899 }
900
901 /* Length of resulting multi-bytes string WITH zero-terminator */
902 if (pReturnValue) {
903 *pReturnValue = n + 1;
904 }
905
906 /* Success */
907 error = 0;
908
909 } else {
910
911 /* Cannot convert string */
912 error = 1;
913
914 }
915
916 #endif
917
918 return error;
919 }
920
921 /* Set errno variable */
922 static void
923 dirent_set_errno(
924 int error)
925 {
926 #if defined(_MSC_VER) && _MSC_VER >= 1400
927
928 /* Microsoft Visual Studio 2005 and later */
929 _set_errno (error);
930
931 #else
932
933 /* Non-Microsoft compiler or older Microsoft compiler */
934 errno = error;
935
936 #endif
937 }
938
939
940 #ifdef __cplusplus
941 }
942 #endif
943 #endif /*DIRENT_H*/
944
5252 CPPCHECK_FILES=`find $CHECK_DIRS -name "*.cc" -o -name "*.hh"`
5353 fi
5454 CPPLINT_FILES=`\
55 find $CHECK_DIRS -name "*.cc" -o -name "*.hh" -o -name "*.c" -o -name "*.h"`
55 find $CHECK_DIRS -name "*.cc" -o -name "*.hh"`
5656 fi
5757
5858 SUPPRESS=/tmp/cpp_check.suppress
6767 touch $SUPPRESS
6868
6969 #cppcheck
70 CPPCHECK_BASE="cppcheck -q --suppressions-list=$SUPPRESS --inline-suppr"
70 CPPCHECK_BASE="cppcheck --force -q --suppressions-list=$SUPPRESS --inline-suppr"
7171 if [ $CPPCHECK_LT_157 -eq 0 ]; then
7272 # use --language argument if 1.57 or greater (issue #907)
7373 CPPCHECK_BASE="$CPPCHECK_BASE --language=c++"
302302 'random',
303303 'ratio',
304304 'regex',
305 'scoped_allocator',
305306 'set',
306307 'sstream',
307308 'stack',
320321 'utility',
321322 'valarray',
322323 'vector',
324 # 17.6.1.2 C++14 headers
325 'shared_mutex',
326 # 17.6.1.2 C++17 headers
327 'any',
328 'charconv',
329 'codecvt',
330 'execution',
331 'filesystem',
332 'memory_resource',
333 'optional',
334 'string_view',
335 'variant',
323336 # 17.6.1.2 C++ headers for C library facilities
324337 'cassert',
325338 'ccomplex',
11
22 Next Tutorial: \ref cppgetstarted
33
4 ## Overview
4 # Overview
55
66 This tutorial describes how to install Ignition Math on Linux, Mac OS X and
77 Windows via either a binary distribution or from source.
88
9 ## Ubuntu Linux
9 [Install](#install)
10
11 * [Binary Install](#binary-install)
12
13 * [Source Install](#source-install)
14
15 * [Prerequisites](#prerequisites)
16
17 * [Building from Source](#building-from-source)
18
19 # Install
20
21 We recommend following the [Binary Install](#binary-install) instructions to get up and running as quickly and painlessly as possible.
22
23 The [Source Install](#source-install) instructions should be used if you need the very latest software improvements, you need to modify the code, or you plan to make a contribution.
24
25 ## Binary Install
26
27 ### Ubuntu Linux
1028
1129 Setup your computer to accept software from
1230 *packages.osrfoundation.org*:
2442 Install Ignition Math:
2543
2644 ```
27 sudo apt-get update
28 sudo apt-get install libignition-math6-dev
45 sudo apt install libignition-math<#>-dev
2946 ```
47
48 Be sure to replace `<#>` with a number value, such as 1 or 2, depending on
49 which version you need.
50
51 ## Source Install
52
53 Source installation can be performed in UNIX systems by first installing the
54 necessary prerequisites followed by building from source.
55
56 ### Prerequisites
57
58 The optional Eigen component of Ignition Math requires:
59
60 * [Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page). Refer to the [Eigen Documentation](http://eigen.tuxfamily.org/index.php?title=Main_Page#Documentation) for installation instructions. On Ubuntu systems, `apt-get` can be used to install Eigen:
61
62 ```
63 sudo apt-get install libeigen3-dev
64 ```
65
66 The optional Ruby tests of Ignition Math require:
67
68 * [Ruby](https://www.ruby-lang.org/). Refer to the [Ruby Documentation](https://www.ruby-lang.org/downloads/) for installation instructions. On Ubuntu systems `apt-get` can be used to install Ubuntu Package `ruby-dev`:
69
70 ```
71 sudo apt-get install ruby-dev
72 ```
73
74 * [Swig](http://www.swig.org/). Refer to the [Swig Documentation](http://www.swig.org/download.html) for installation instructions. On Ubuntu systems `apt-get` can be used to install Swig:
75
76 ```
77 sudo apt-get install swig
78 ```
79
80 ### Building from source
81
82 1. Clone the repository
83
84 ```
85 git clone https://github.com/ignitionrobotics/ign-math -b ign-math<#>
86 ```
87 Be sure to replace `<#>` with a number value, such as 1 or 2, depending on
88 which version you need.
89
90 2. Install dependencies
91
92 ```
93 export SYSTEM_VERSION=bionic
94 sudo apt -y install \
95 $(sort -u $(find . -iname 'packages-'$SYSTEM_VERSION'.apt' -o -iname 'packages.apt') | tr '\n' ' ')
96 ```
97
98 3. Configure and build
99
100 ```
101 cd ign-math; mkdir build; cd build; cmake ..; make
102 ```
103
104 4. Optionally, install Ignition Math
105
106 ```
107 sudo make install
108 ```