Main MRPT website > C++ reference for MRPT 1.9.9
test.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
11 #include <mrpt/system/CTicTac.h>
12 #include <mrpt/random.h>
13 #include <mrpt/system/os.h>
15 #include <mrpt/opengl/CSphere.h>
16 #include <iostream>
17 
18 using namespace mrpt;
19 using namespace std;
20 using namespace mrpt::gui;
21 using namespace mrpt::random;
22 using namespace mrpt::opengl;
23 
24 const size_t N_MASSES = 750;
25 
26 const double BOX = 500;
27 const double V0 = 100;
28 const double MASS_MIN = log(40.0), MASS_MAX = log(100.0);
29 const double M2R = 2.0;
30 const double LARGEST_STEP = 0.001;
31 const double G = 300;
32 const double COLLIS_LOSS = 0.98;
33 
34 struct TMass
35 {
36  TMass() : x(0), y(0), z(0), vx(0), vy(0), vz(0), mass(1), obj3d() {}
37  double x, y, z;
38  double vx, vy, vz;
39  double mass;
40  double radius;
42 };
43 
44 void simulateGravity(vector<TMass>& objs, double At);
45 
46 // ------------------------------------------------------
47 // GravityDemo
48 // ------------------------------------------------------
49 void GravityDemo()
50 {
52  "MRPT example: 3D gravity simulator- JLBC 2008", 1000, 700);
53 
55 
56  win.setCameraElevationDeg(50.0f);
57  win.setCameraZoom(1000);
58 
59  COpenGLScene::Ptr& theScene = win.get3DSceneAndLock();
60 
61  // Modify the scene:
62  // ------------------------------------------------------
63  {
65  mrpt::make_aligned_shared<opengl::CGridPlaneXY>(
66  -2000, 2000, -2000, 2000, 0, 100);
67  obj->setColor(0.3, 0.3, 0.3);
68  theScene->insert(obj);
69  }
70 
71  // Create the masses:
72  // ----------------------------------------------------
73 
74  vector<TMass> masses(N_MASSES);
75 
76  // Init at random poses & create opengl objects:
77  for (size_t i = 0; i < N_MASSES; i++)
78  {
79  masses[i].x = getRandomGenerator().drawUniform(-BOX, BOX);
80  masses[i].y = getRandomGenerator().drawUniform(-BOX, BOX);
81  masses[i].z = getRandomGenerator().drawUniform(-BOX, BOX) / 10;
82 
83  double a = atan2(masses[i].y, masses[i].x);
84 
85  masses[i].vx = -V0 * sin(a) +
86  getRandomGenerator().drawUniform(-V0 * 0.01, V0 * 0.01);
87  masses[i].vy = V0 * cos(a) +
88  getRandomGenerator().drawUniform(-V0 * 0.01, V0 * 0.01);
89  masses[i].vz = 0; // getRandomGenerator().drawUniform(-V0,V0);
90 
91  masses[i].mass =
92  exp(getRandomGenerator().drawUniform(MASS_MIN, MASS_MAX));
93  opengl::CSphere::Ptr& obj = masses[i].obj3d =
94  mrpt::make_aligned_shared<opengl::CSphere>();
95 
96  obj->setColor(
97  getRandomGenerator().drawUniform(0.1, 0.9),
98  getRandomGenerator().drawUniform(0.1, 0.9),
99  getRandomGenerator().drawUniform(0.1, 0.9));
100 
101  masses[i].radius = M2R * pow(masses[i].mass, 1.0 / 3.0);
102  obj->setRadius(masses[i].radius); // Guess why ^(1/3) ;-)
103 
104  obj->setLocation(masses[i].x, masses[i].y, masses[i].z);
105  theScene->insert(obj);
106  }
107 
108  // IMPORTANT!!! IF NOT UNLOCKED, THE WINDOW WILL NOT BE UPDATED!
109  win.unlockAccess3DScene();
110 
111  mrpt::system::CTicTac tictac;
112  tictac.Tic();
113 
114  double t0 = tictac.Tac();
115 
116  while (!mrpt::system::os::kbhit() && win.isOpen())
117  {
118  // Move the scene:
119  double t1 = tictac.Tac();
120  double At = t1 - t0;
121  t0 = t1;
122 
123  // Simulate a At, possibly in several small steps:
124  // Update the 3D scene:
125  win.get3DSceneAndLock();
126 
127  size_t n_steps = ceil(At / LARGEST_STEP) + 1;
128  double At_steps = At / n_steps;
129  n_steps = min(n_steps, size_t(3));
130  for (size_t j = 0; j < n_steps; j++) simulateGravity(masses, At_steps);
131 
132  for (size_t i = 0; i < masses.size(); i++)
133  {
134  opengl::CSphere::Ptr& obj = masses[i].obj3d;
135  obj->setLocation(masses[i].x, masses[i].y, masses[i].z);
136  }
137  // IMPORTANT!!! IF NOT UNLOCKED, THE WINDOW WILL NOT BE UPDATED!
138  win.unlockAccess3DScene();
139 
140  // Update window:
141  win.forceRepaint();
142  std::this_thread::sleep_for(1ms);
143  };
144 }
145 
146 struct TForce
147 {
148  TForce() { f[0] = f[1] = f[2] = 0; }
149  double f[3];
150 };
151 
152 void simulateGravity(vector<TMass>& objs, double At)
153 {
154  const size_t N = objs.size();
155 
156  vector<TForce> forces(N);
157 
158  // Index in the array must be larger than its content!!
159  vector<pair<size_t, double>> lstMass_i_joins_j(
160  N, pair<size_t, double>(string::npos, 10000.0));
161 
162  for (size_t i = 0; i < (N - 1); i++)
163  {
164  const double Ri = objs[i].radius;
165 
166  // Compute overall gravity force:
167  for (size_t j = i + 1; j < N; j++)
168  {
169  double Ax = objs[j].x - objs[i].x;
170  double Ay = objs[j].y - objs[i].y;
171  double Az = objs[j].z - objs[i].z;
172  double D2 = square(Ax) + square(Ay) + square(Az);
173 
174  double D = sqrt(D2);
175  if (D == 0) continue;
176 
177  const double Rj = objs[j].radius;
178 
179  if (D < (Ri + Rj)) // Collission!!
180  {
181  // Index in the array must be larger than its content!!
182  if (D < lstMass_i_joins_j[j].second)
183  {
184  lstMass_i_joins_j[j].first = i;
185  lstMass_i_joins_j[j].second = D;
186  }
187  }
188  else
189  {
190  double K =
191  G * objs[i].mass * objs[j].mass / square(max(D, 1.0));
192  double D_1 = 1.0 / D;
193  Ax *= D_1;
194  Ay *= D_1;
195  Az *= D_1;
196 
197  const double fx = Ax * K;
198  const double fy = Ay * K;
199  const double fz = Az * K;
200 
201  forces[i].f[0] += fx;
202  forces[i].f[1] += fy;
203  forces[i].f[2] += fz;
204 
205  forces[j].f[0] -= fx;
206  forces[j].f[1] -= fy;
207  forces[j].f[2] -= fz;
208  }
209  }
210  }
211 
212  // F = m a
213  for (size_t i = 0; i < N; i++)
214  {
215  const double M_1 = 1.0 / objs[i].mass;
216 
217  forces[i].f[0] *= M_1;
218  forces[i].f[1] *= M_1;
219  forces[i].f[2] *= M_1;
220 
221  objs[i].vx += forces[i].f[0] * At;
222  objs[i].vy += forces[i].f[1] * At;
223  objs[i].vz += forces[i].f[2] * At;
224 
225  objs[i].x += objs[i].vx * At;
226  objs[i].y += objs[i].vy * At;
227  objs[i].z += objs[i].vz * At;
228  }
229 
230  // return;
231  // Join masses that collided:
232  for (int i = N - 1; i >= 0; i--)
233  {
234  const size_t newObj = lstMass_i_joins_j[i].first;
235  if (newObj == string::npos) continue;
236 
237  const double Mi = objs[i].mass;
238  const double Mj = objs[newObj].mass;
239  const double newMass = Mi + Mj;
240  const double newMass_1 = 1.0 / newMass;
241 
242  objs[newObj].vx =
243  COLLIS_LOSS * newMass_1 * (Mj * objs[newObj].vx + Mi * objs[i].vx);
244  objs[newObj].vy =
245  COLLIS_LOSS * newMass_1 * (Mj * objs[newObj].vy + Mi * objs[i].vy);
246  objs[newObj].vz =
247  COLLIS_LOSS * newMass_1 * (Mj * objs[newObj].vz + Mi * objs[i].vz);
248 
249  objs[newObj].x = newMass_1 * (Mj * objs[newObj].x + Mi * objs[i].x);
250  objs[newObj].y = newMass_1 * (Mj * objs[newObj].y + Mi * objs[i].y);
251  objs[newObj].z = newMass_1 * (Mj * objs[newObj].z + Mi * objs[i].z);
252 
253  objs[newObj].mass = newMass;
254  objs[newObj].radius = M2R * pow(newMass, 1.0 / 3.0);
255  objs[newObj].obj3d->setRadius(objs[newObj].radius);
256 
257  objs[i].obj3d->setVisibility(false); // Hide sphere
258  objs.erase(objs.begin() + i);
259  }
260 }
261 
262 // ------------------------------------------------------
263 // MAIN
264 // ------------------------------------------------------
265 int main()
266 {
267  try
268  {
269  GravityDemo();
270  return 0;
271  }
272  catch (std::exception& e)
273  {
274  std::cout << "MRPT exception caught: " << e.what() << std::endl;
275  return -1;
276  }
277  catch (...)
278  {
279  printf("Untyped exception!!");
280  return -1;
281  }
282 }
MASS_MIN
const double MASS_MIN
Definition: vision_stereo_rectify/test.cpp:28
mrpt::system::os::kbhit
bool kbhit() noexcept
An OS-independent version of kbhit, which returns true if a key has been pushed.
Definition: os.cpp:390
os.h
mrpt::opengl::CGridPlaneXY::Ptr
std::shared_ptr< CGridPlaneXY > Ptr
Definition: CGridPlaneXY.h:34
GravityDemo
void GravityDemo()
Definition: vision_stereo_rectify/test.cpp:49
G
const double G
Definition: vision_stereo_rectify/test.cpp:31
mrpt::system::CTicTac
A high-performance stopwatch, with typical resolution of nanoseconds.
Definition: system/CTicTac.h:19
CSphere.h
mrpt::opengl::CSphere::Ptr
std::shared_ptr< CSphere > Ptr
Definition: CSphere.h:33
V0
const double V0
Definition: vision_stereo_rectify/test.cpp:27
obj
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
mrpt
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Definition: CKalmanFilterCapable.h:30
mrpt::square
T square(const T x)
Inline function for the square of a number.
Definition: core/include/mrpt/core/bits_math.h:18
CDisplayWindow3D.h
random.h
mrpt::random::CRandomGenerator::randomize
void randomize(const uint32_t seed)
Initialize the PRNG from the given random seed.
Definition: RandomGenerator.cpp:32
mrpt::system::CTicTac::Tac
double Tac() noexcept
Stops the stopwatch.
Definition: CTicTac.cpp:90
main
int main()
Definition: vision_stereo_rectify/test.cpp:78
TForce
Definition: vision_stereo_rectify/test.cpp:146
mrpt::random::CRandomGenerator::drawUniform
double drawUniform(const double Min, const double Max)
Generate a uniformly distributed pseudo-random number using the MT19937 algorithm,...
Definition: RandomGenerators.h:111
TMass
Definition: vision_stereo_rectify/test.cpp:34
win
mrpt::gui::CDisplayWindow3D::Ptr win
Definition: vision_stereo_rectify/test.cpp:31
mrpt::system::CTicTac::Tic
void Tic() noexcept
Starts the stopwatch.
Definition: CTicTac.cpp:79
N_MASSES
const size_t N_MASSES
Definition: vision_stereo_rectify/test.cpp:24
mrpt::gui
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:16
min
#define min(a, b)
Definition: rplidar_driver.cpp:42
mrpt::random::getRandomGenerator
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
Definition: RandomGenerator.cpp:19
CTicTac.h
simulateGravity
void simulateGravity(vector< TMass > &objs, double At)
Definition: vision_stereo_rectify/test.cpp:152
z
GLdouble GLdouble z
Definition: glext.h:3872
mrpt::opengl::COpenGLScene::Ptr
std::shared_ptr< COpenGLScene > Ptr
Definition: COpenGLScene.h:61
COLLIS_LOSS
const double COLLIS_LOSS
Definition: vision_stereo_rectify/test.cpp:32
mrpt::random
A namespace of pseudo-random numbers generators of diferent distributions.
Definition: random_shuffle.h:17
CGridPlaneXY.h
mrpt::opengl
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:15
y
GLenum GLint GLint y
Definition: glext.h:3538
mrpt::gui::CDisplayWindow3D
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.
Definition: CDisplayWindow3D.h:117
MASS_MAX
const double MASS_MAX
Definition: vision_stereo_rectify/test.cpp:28
BOX
const double BOX
Definition: vision_stereo_rectify/test.cpp:26
x
GLenum GLint x
Definition: glext.h:3538
a
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
LARGEST_STEP
const double LARGEST_STEP
Definition: vision_stereo_rectify/test.cpp:30
M2R
const double M2R
Definition: vision_stereo_rectify/test.cpp:29



Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at miƩ 12 jul 2023 10:03:34 CEST