World_walls.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2020 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 
10 #include <mrpt/core/exceptions.h>
11 #include <mrpt/maps/CSimplePointsMap.h>
13 #include <mrpt/system/filesystem.h>
14 #include <mvsim/World.h>
15 
16 #include <rapidxml.hpp>
17 #include <rapidxml_print.hpp>
18 #include <rapidxml_utils.hpp>
19 
20 #include "xml_utils.h"
21 
22 using namespace mvsim;
23 using namespace std;
24 
26 {
27  double height = 2.0;
28  double thickness = 0.10;
29 };
30 
32  World* parent, const mrpt::math::TPoint3D& rawEnd1,
33  const mrpt::math::TPoint3D& rawEnd2, const WallProperties& wp,
35 {
36  Block::Ptr b = std::make_shared<Block>(parent);
37 
38  {
39  static int cnt = 0;
40  b->setName(mrpt::format("wall_%04i", ++cnt));
41  }
42 
43  float pt1Dist = std::numeric_limits<float>::max(),
44  pt2Dist = std::numeric_limits<float>::max();
45 
46  if (!allPts.empty())
47  {
48  allPts.kdTreeClosestPoint2D(rawEnd1.x, rawEnd1.y, pt1Dist);
49  allPts.kdTreeClosestPoint2D(rawEnd2.x, rawEnd2.y, pt2Dist);
50  }
51 
52  // Do we need to move these points due to former points already there, to
53  // avoid "collisions"?
54  const bool end1move = pt1Dist < mrpt::square(1.1 * wp.thickness);
55  const bool end2move = pt2Dist < mrpt::square(1.1 * wp.thickness);
56 
57  const auto vec12 = rawEnd2 - rawEnd1;
58  ASSERT_(vec12.norm() > 0);
59  const auto u12 = vec12.unitarize();
60 
61  const double t_hf = 0.5 * wp.thickness;
62  const double t = 1.01 * wp.thickness;
63 
64  const auto end1 = end1move ? (rawEnd1 + u12 * t) : rawEnd1;
65  const auto end2 = end2move ? (rawEnd2 + u12 * (-t)) : rawEnd2;
66 
67  const auto ptCenter = (end1 + end2) * 0.5;
68  const double wallLineAngle = std::atan2(vec12.y, vec12.x);
69 
70  allPts.insertPoint(rawEnd1);
71  allPts.insertPoint(rawEnd2);
72 
73  // initial pose:
74  b->setPose({ptCenter.x, ptCenter.y, 0, wallLineAngle, 0, 0});
75 
76  // Shape:
77  {
78  const double l_hf = 0.5 * (end2 - end1).norm();
79 
80  ASSERT_(l_hf > 0);
81  ASSERT_(t_hf > 0);
82 
83  auto bbmin = mrpt::math::TPoint3D(-l_hf, -t_hf, 0);
84  auto bbmax = mrpt::math::TPoint3D(+l_hf, +t_hf, 0);
85 
87  p.emplace_back(bbmin.x, bbmin.y);
88  p.emplace_back(bbmin.x, bbmax.y);
89  p.emplace_back(bbmax.x, bbmax.y);
90  p.emplace_back(bbmax.x, bbmin.y);
91 
92  b->blockShape(p);
93 
94  b->block_z_min(.0);
95  b->block_z_max(wp.height);
96  }
97 
98  // make the walls non-movable:
99  b->ground_friction(1e5);
100  b->mass(1e5);
101 
102  // Register bodies, fixtures, etc. in Box2D simulator:
103  // ----------------------------------------------------
104  b->create_multibody_system(*parent->getBox2DWorld());
105  // This makes the walls non-mobile:
106  b->setIsStatic(true);
107 
108  if (auto bb = b->b2d_body(); bb != nullptr)
109  {
110  // Init pos:
111  const auto q = b->getPose();
112 
113  bb->SetTransform(b2Vec2(q.x, q.y), q.yaw);
114  // Init vel:
115  bb->SetLinearVelocity({0, 0});
116  bb->SetAngularVelocity(0);
117  }
118 
119  return b;
120 }
121 
123 {
124  MRPT_START
125 
126  // Sanity checks:
127  ASSERT_(0 == strcmp(node.name(), "walls"));
128 
129  std::string wallModelFileName;
130  std::string sTransformation;
131  double scale = 1.0;
132  mrpt::img::TColor wallColor{0xff323232};
133  WallProperties wp;
134 
136  params["model_uri"] = TParamEntry("%s", &wallModelFileName);
137  params["transformation"] = TParamEntry("%s", &sTransformation);
138  params["wallThickness"] = TParamEntry("%lf", &wp.thickness);
139  params["wallHeight"] = TParamEntry("%lf", &wp.height);
140  params["scale"] = TParamEntry("%lf", &scale);
141  params["color"] = TParamEntry("%color", &wallColor);
142 
143  // Parse XML params:
144  parse_xmlnode_children_as_param(node, params);
145 
146  ASSERT_(!wallModelFileName.empty());
147  const std::string localFileName = xmlPathToActualPath(wallModelFileName);
148  ASSERT_FILE_EXISTS_(localFileName);
149 
150  // Optional transformation:
151  auto HM = mrpt::math::CMatrixDouble44::Identity();
152  if (!sTransformation.empty())
153  {
154  std::stringstream ssError;
155  bool ok = HM.fromMatlabStringFormat(sTransformation, ssError);
156  if (!ok)
158  "Error parsing 'transformation=\"%s\"' parameter of walls:\n%s",
159  sTransformation.c_str(), ssError.str().c_str());
160  MRPT_LOG_DEBUG_STREAM("Walls: using transformation: " << HM.asString());
161  }
162  const auto tf = mrpt::poses::CPose3D(HM);
163 
165  "Loading walls definition model from: " << localFileName);
166 
167  auto glModel = mrpt::opengl::CAssimpModel::Create();
168  glModel->loadScene(localFileName);
169 
170  const auto& points = glModel->shaderWireframeVertexPointBuffer();
171  MRPT_LOG_DEBUG_STREAM("Walls loaded, " << points.size() << " segments.");
172 
173  // Transform them:
174  std::vector<mrpt::math::TPoint3Df> tfPts;
175  tfPts.reserve(points.size());
176  for (const auto& pt : points) tfPts.emplace_back(tf.composePoint(pt));
177 
178  // Insert all points for KD-tree lookup:
180 
181  // Create walls themselves:
182  ASSERT_(tfPts.size() % 2 == 0);
183  for (size_t i = 0; i < tfPts.size() / 2; i++)
184  {
185  const auto& pt1 = tfPts[i * 2 + 0];
186  const auto& pt2 = tfPts[i * 2 + 1];
187  auto block = create_wall_segment(this, pt1, pt2, wp, ptsMap);
188  block->block_color(wallColor);
189  insertBlock(block);
190  }
191 
192  MRPT_END
193 }
This file contains rapidxml parser and DOM implementation.
GLenum GLenum GLenum GLenum GLenum scale
std::map< std::string, TParamEntry > TParameterDefinitions
void parse_xmlnode_children_as_param(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions &params, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="")
Definition: xml_utils.cpp:179
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
GLdouble GLdouble t
std::unique_ptr< b2World > & getBox2DWorld()
Definition: World.h:189
A 2D column vector.
Definition: b2Math.h:52
std::shared_ptr< Block > Ptr
Definition: Block.h:36
#define MRPT_LOG_DEBUG_STREAM(__CONTENTS)
GLuint GLenum GLsizei GLsizei GLboolean void * points
#define MRPT_END
static Block::Ptr create_wall_segment(World *parent, const mrpt::math::TPoint3D &rawEnd1, const mrpt::math::TPoint3D &rawEnd2, const WallProperties &wp, mrpt::maps::CSimplePointsMap &allPts)
Definition: World_walls.cpp:31
Ch * name() const
Definition: rapidxml.hpp:673
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
GLfloat GLfloat p
GLint GLint GLint GLint GLint GLint GLsizei GLsizei height
size_t kdTreeClosestPoint2D(float x0, float y0, float &out_x, float &out_y, float &out_dist_sqr) const
#define MRPT_START
void insertPoint(float x, float y, float z=0)
#define ASSERT_(f)
GLfloat * params
#define ASSERT_FILE_EXISTS_(FIL)
This file contains rapidxml printer implementation.
GLdouble GLdouble GLdouble b
GLdouble GLdouble GLdouble GLdouble q
void process_load_walls(const rapidxml::xml_node< char > &node)
CONTAINER::Scalar norm(const CONTAINER &v)


mvsim
Author(s):
autogenerated on Fri May 7 2021 03:05:51