MVSim
Lightweight simulator for 2.5D vehicles and robots
Block.h
1 /*+-------------------------------------------------------------------------+
2  | Multiblock simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2026 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 #pragma once
11 
12 #include <box2d/b2_fixture.h>
13 #include <box2d/b2_friction_joint.h>
14 #include <box2d/b2_polygon_shape.h>
15 #include <box2d/b2_world.h>
16 #include <mrpt/img/TColor.h>
17 #include <mrpt/math/TPolygon2D.h>
18 #include <mrpt/opengl/CSetOfLines.h>
19 #include <mrpt/opengl/CSetOfObjects.h>
20 #include <mrpt/poses/CPose2D.h>
21 #include <mrpt/typemeta/TEnumType.h>
22 #include <mvsim/ClassFactory.h>
23 #include <mvsim/Sensors/SensorBase.h>
24 #include <mvsim/Simulable.h>
25 #include <mvsim/TParameterDefinitions.h>
26 #include <mvsim/VisualObject.h>
27 #include <mvsim/basic_types.h>
28 
29 #include <mutex>
30 
31 namespace mvsim
32 {
36 enum class GeometryType : int32_t
37 {
38  Invalid = -1,
39  // ----------------
40  Cylinder = 0,
41  Sphere,
42  Box,
43  Ramp,
44  SemiCylinderBump,
45 };
46 
50 class Block : public VisualObject, public Simulable
51 {
52  public:
53  using Ptr = std::shared_ptr<Block>;
54 
57  static Ptr factory(World* parent, const rapidxml::xml_node<char>* xml_node);
59  static Ptr factory(World* parent, const std::string& xml_text);
60 
63  static void register_block_class(const World& parent, const rapidxml::xml_node<char>* xml_node);
64 
65  // ------- Interface with "World" ------
66  virtual void simul_pre_timestep(const TSimulContext& context) override;
67  virtual void simul_post_timestep(const TSimulContext& context) override;
68  virtual void apply_force(
69  const mrpt::math::TVector2D& force,
70  const mrpt::math::TPoint2D& applyPoint = mrpt::math::TPoint2D(0, 0)) override;
71 
74  virtual void create_multibody_system(b2World& world);
75 
78  virtual double getMaxBlockRadius() const { return maxRadius_; }
79 
81  virtual double getMass() const { return mass_; }
82  b2Body* getBox2DBlockBody() { return b2dBody_; }
83  mrpt::math::TPoint2D getBlockCenterOfMass() const
84  {
85  return block_com_;
86  }
87 
90  const mrpt::math::TPolygon2D& blockShape() const { return block_poly_; }
91 
92  void blockShape(const mrpt::math::TPolygon2D& p)
93  {
94  block_poly_ = p;
95  updateMaxRadiusFromPoly();
96  gl_block_.reset(); // regenerate 3D view
97  }
98 
100  void setBlockIndex(size_t idx) { blockIndex_ = idx; }
102  size_t getBlockIndex() const { return blockIndex_; }
103 
104  Block(World* parent);
105 
106  double ground_friction() const { return groundFriction_; }
107  void ground_friction(double newValue) { groundFriction_ = newValue; }
108 
109  double mass() const { return mass_; }
110  void mass(double newValue) { mass_ = newValue; }
111 
112  bool isStatic() const;
113  void setIsStatic(bool b);
114 
115  const mrpt::img::TColor block_color() const { return block_color_; }
116  void block_color(const mrpt::img::TColor& c)
117  {
118  block_color_ = c;
119  gl_block_.reset(); // regenerate 3D view
120  }
121 
122  double block_z_min() const { return block_z_min_; }
123  double block_z_max() const { return block_z_max_; }
124  void block_z_min(double v)
125  {
126  block_z_min_ = v;
127  gl_block_.reset(); // regenerate 3D view
128  }
129  void block_z_max(double v)
130  {
131  block_z_max_ = v;
132  gl_block_.reset(); // regenerate 3D view
133  }
134 
135  double visual_scale() const { return visual_scale_; }
136  void visual_scale(double v)
137  {
138  visual_scale_ = v;
139  gl_block_.reset(); // regenerate 3D view
140  }
141 
145 
146  VisualObject* meAsVisualObject() override { return this; }
147 
148  std::optional<float> getElevationAt(const mrpt::math::TPoint2D& worldXY) const override;
149 
150  protected:
151  virtual void internalGuiUpdate(
152  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
153  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical, bool childrenOnly) override;
154 
157  size_t blockIndex_ = 0;
158 
159  std::vector<b2FrictionJoint*> friction_joints_;
160 
161  // Block info:
162  double mass_ = 30.0;
163  bool isStatic_ = false;
164  mrpt::math::TPolygon2D block_poly_;
165 
168  double maxRadius_;
169 
170  double block_z_min_ = std::numeric_limits<double>::quiet_NaN(),
171  block_z_max_ = std::numeric_limits<double>::quiet_NaN();
172 
173  mrpt::img::TColor block_color_{0x00, 0x00, 0xff};
174  mrpt::math::TPoint2D block_com_{.0, .0};
175 
176  double lateral_friction_ = 0.5;
177  double groundFriction_ = 0.5;
178  double restitution_ = 0.01;
179 
181  float linear_damping_ = 0.1;
182 
184  float angular_damping_ = 0.1;
185 
188  bool intangible_ = false;
189 
192  double visual_scale_ = std::numeric_limits<double>::quiet_NaN();
193 
194  const TParameterDefinitions params_ = {
195  {"mass", {"%lf", &mass_}},
196  {"zmin", {"%lf", &block_z_min_}},
197  {"zmax", {"%lf", &block_z_max_}},
198  {"ground_friction", {"%lf", &groundFriction_}},
199  {"lateral_friction", {"%lf", &lateral_friction_}},
200  {"restitution", {"%lf", &restitution_}},
201  {"color", {"%color", &block_color_}},
202  {"intangible", {"%bool", &intangible_}},
203  {"static", {"%bool", &isStatic_}},
204  {"visual_scale", {"%lf", &visual_scale_}},
205  {"linear_damping", {"%f", &linear_damping_}},
206  {"angular_damping", {"%f", &angular_damping_}}
207  //
208  };
209 
210  void updateMaxRadiusFromPoly();
211 
212  // Box2D elements:
213  b2Fixture* fixture_block_;
214 
215  private:
216  void internal_internalGuiUpdate_forces(mrpt::opengl::COpenGLScene& scene);
217 
218  void internal_parseGeometry(const rapidxml::xml_node<char>& xml_geom_node);
219 
221  struct GeometryParams
222  {
223  GeometryParams() = default;
224 
225  std::string typeStr; // cylinder, sphere, etc.
226  GeometryType type = GeometryType::Invalid;
227 
228  float radius = 0;
229  float length = 0, lx = 0, ly = 0, lz = 0;
230  int vertex_count = 0;
231 
232  const TParameterDefinitions params = {
233  {"type", {"%s", &typeStr}},
234  {"radius", {"%f", &radius}},
235  {"length", {"%f", &length}},
236  {"lx", {"%f", &lx}},
237  {"ly", {"%f", &ly}},
238  {"lz", {"%f", &lz}},
239  {"vertex_count", {"%i", &vertex_count}},
240  };
241  };
242 
243  GeometryParams geomParams_;
244 
245  mrpt::opengl::CSetOfObjects::Ptr gl_block_;
246  mrpt::opengl::CSetOfLines::Ptr gl_forces_;
247  std::mutex force_segments_for_rendering_cs_;
248  std::vector<mrpt::math::TSegment3D> force_segments_for_rendering_;
249 
250 }; // end Block
251 
257 {
258  public:
259  using Ptr = std::shared_ptr<DummyInvisibleBlock>;
260 
261  DummyInvisibleBlock(World* parent);
262 
265  static Ptr factory(World* parent, const rapidxml::xml_node<char>* xml_node);
267  static Ptr factory(World* parent, const std::string& xml_text);
268 
269  // ------- Interface with "World" ------
270  virtual void simul_pre_timestep(const TSimulContext& context) override
271  {
273  for (auto& s : sensors_)
274  {
275  s->simul_pre_timestep(context);
276  }
277  }
278  virtual void simul_post_timestep(const TSimulContext& context) override
279  {
281  for (auto& s : sensors_)
282  {
283  s->simul_post_timestep(context);
284  }
285  }
286 
287  virtual void apply_force(
288  [[maybe_unused]] const mrpt::math::TVector2D& force,
289  [[maybe_unused]] const mrpt::math::TPoint2D& applyPoint) override
290  {
291  }
292 
293  virtual void create_multibody_system(b2World&) {}
294 
295  virtual double getMaxBlockRadius() const { return 0; }
296 
298  virtual double getMass() const { return 0; }
299 
300  void add_sensor(const SensorBase::Ptr& sensor) { sensors_.push_back(sensor); }
301 
302  protected:
303  void internalGuiUpdate(
304  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
305  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical,
306  [[maybe_unused]] bool childrenOnly) override;
307 
308  void registerOnServer(mvsim::Client& c) override
309  {
310  // register myself, and my children objects:
311  Simulable::registerOnServer(c);
312  for (auto& sensor : sensors_)
313  {
314  sensor->registerOnServer(c);
315  }
316  }
317 
318  private:
319  TListSensors sensors_;
320 
321 }; // end Block
322 
323 } // namespace mvsim
324 
325 // TTypeEnum macros:
326 MRPT_ENUM_TYPE_BEGIN_NAMESPACE(mvsim, mvsim::GeometryType)
327 MRPT_FILL_ENUM_CUSTOM_NAME(GeometryType::Cylinder, "cylinder");
328 MRPT_FILL_ENUM_CUSTOM_NAME(GeometryType::Sphere, "sphere");
329 MRPT_FILL_ENUM_CUSTOM_NAME(GeometryType::Box, "box");
330 MRPT_FILL_ENUM_CUSTOM_NAME(GeometryType::Ramp, "ramp");
331 MRPT_FILL_ENUM_CUSTOM_NAME(GeometryType::SemiCylinderBump, "semi_cylinder_bump");
332 MRPT_ENUM_TYPE_END()
Definition: Block.h:51
double lateral_friction_
Default: 0.5.
Definition: Block.h:176
void setBlockIndex(size_t idx)
Definition: Block.h:100
virtual void simul_post_timestep(const TSimulContext &context) override
double restitution_
Default: 0.01.
Definition: Block.h:178
static void register_block_class(const World &parent, const rapidxml::xml_node< char > *xml_node)
size_t blockIndex_
Definition: Block.h:157
double visual_scale_
Definition: Block.h:192
virtual void simul_pre_timestep(const TSimulContext &context) override
double maxRadius_
Definition: Block.h:168
float linear_damping_
Definition: Block.h:181
size_t getBlockIndex() const
Definition: Block.h:102
static Ptr factory(World *parent, const std::string &xml_text)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool default_block_z_min_max() const
virtual void apply_force(const mrpt::math::TVector2D &force, const mrpt::math::TPoint2D &applyPoint=mrpt::math::TPoint2D(0, 0)) override
double groundFriction_
Default: 0.5.
Definition: Block.h:177
bool intangible_
Definition: Block.h:188
static Ptr factory(World *parent, const rapidxml::xml_node< char > *xml_node)
mrpt::math::TPoint2D getBlockCenterOfMass() const
In local coordinates.
Definition: Block.h:83
virtual double getMass() const
Definition: Block.h:81
mrpt::math::TPoint2D block_com_
In local coordinates.
Definition: Block.h:174
virtual void create_multibody_system(b2World &world)
float angular_damping_
Definition: Block.h:184
const mrpt::math::TPolygon2D & blockShape() const
Definition: Block.h:90
virtual double getMaxBlockRadius() const
Definition: Block.h:78
Definition: Client.h:49
Definition: Block.h:257
static Ptr factory(World *parent, const rapidxml::xml_node< char > *xml_node)
virtual double getMass() const
Definition: Block.h:298
static Ptr factory(World *parent, const std::string &xml_text)
This is an overloaded member function, provided for convenience. It differs from the above function o...
virtual void simul_post_timestep(const TSimulContext &context) override
Definition: Block.h:278
virtual void simul_pre_timestep(const TSimulContext &context) override
Definition: Block.h:270
Definition: Simulable.h:40
virtual void simul_pre_timestep(const TSimulContext &context)
virtual void simul_post_timestep(const TSimulContext &context)
Definition: VisualObject.h:36
Definition: World.h:132
GeometryType
Definition: Block.h:37
Definition: basic_types.h:58