10 #include <mrpt/core/bits_math.h>
11 #include <mrpt/core/format.h>
12 #include <mrpt/core/lock_helper.h>
13 #include <mrpt/math/TPose2D.h>
14 #include <mrpt/opengl/CBox.h>
15 #include <mrpt/opengl/CCylinder.h>
16 #include <mrpt/opengl/CPolyhedron.h>
17 #include <mrpt/opengl/CSetOfTriangles.h>
18 #include <mrpt/opengl/CSphere.h>
19 #include <mrpt/poses/CPose2D.h>
20 #include <mrpt/version.h>
32 using namespace mvsim;
53 if (!xml_node)
throw runtime_error(
"[Block::register_vehicle_class] XML node is nullptr");
54 if (0 != strcmp(xml_node->name(),
"block:class"))
55 throw runtime_error(mrpt::format(
56 "[Block::register_block_class] XML element is '%s' "
57 "('block:class' expected)",
69 if (!
root)
throw runtime_error(
"[Block::factory] XML node is nullptr");
70 if (0 != strcmp(
root->name(),
"block"))
71 throw runtime_error(mrpt::format(
72 "[Block::factory] XML root element is '%s' ('block' expected)",
root->name()));
84 const string sClassName = block_class->value();
87 "[Block::factory] Block class '%s' undefined", sClassName.c_str());
89 nodes.
add(class_root);
102 if (attrib_name && attrib_name->value())
104 block->name_ = attrib_name->value();
110 block->name_ = mrpt::format(
"block%03i", ++cnt);
124 block->parseVisual(nodes);
127 if (
const auto* xml_shape = nodes.
first_node(
"shape"); xml_shape)
130 block->updateMaxRadiusFromPoly();
132 else if (
const auto* xml_geom = nodes.
first_node(
"geometry"); xml_geom)
134 block->internal_parseGeometry(*xml_geom);
141 const auto& bbVis = block->collisionShape();
142 if (!bbVis.has_value())
145 "Error: Tag <shape_from_visual/> found but neither <visual> "
146 "nor <geometry> entries, while parsing <block>");
148 const auto& bb = bbVis.value();
150 if (bb.volume() == 0)
153 "Error: Tag <shape_from_visual/> found but bounding box of "
154 "visual object seems incorrect, while parsing <block>");
158 block->block_poly_ = bb.getContour();
159 block->block_z_min(bb.zMin());
160 block->block_z_max(bb.zMax());
166 if (block->default_block_z_min_max())
168 block->block_z_min(0.0);
169 block->block_z_max(1.0);
173 block->updateMaxRadiusFromPoly();
177 block->parseSimulable(nodes);
187 const auto dq = block->getTwist();
189 block->b2dBody_->SetTransform(
b2Vec2(q.x, q.y), q.yaw);
191 block->b2dBody_->SetLinearVelocity(
b2Vec2(dq.vx, dq.vy));
192 block->b2dBody_->SetAngularVelocity(dq.omega);
204 char* input_str =
const_cast<char*
>(xml_text.c_str());
208 xml.
parse<0>(input_str);
212 unsigned int line =
static_cast<long>(std::count(input_str, e.
where<
char>(),
'\n') + 1);
213 throw std::runtime_error(mrpt::format(
214 "[Block::factory] XML parse error (Line %u): %s",
static_cast<unsigned>(line),
233 const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
234 const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical,
bool childrenOnly)
242 gl_block_ = mrpt::opengl::CSetOfObjects::Create();
246 auto gl_poly = mrpt::opengl::CPolyhedron::CreateCustomPrism(
252 #if MRPT_VERSION >= 0x240
274 gl_forces_ = mrpt::opengl::CSetOfLines::Create();
278 gl_forces_->setPose(
parent()->applyWorldRenderOffset(mrpt::poses::CPose3D::Identity()));
288 [[maybe_unused]] mrpt::opengl::COpenGLScene& scene)
310 const float n = segment.norm();
341 std::vector<b2Vec2> pts(nPts);
345 blockPoly.
Set(&pts[0], nPts);
352 fixtureDef.
shape = &blockPoly;
378 const size_t nContactPoints = 2;
381 const double max_friction = mu * weight_per_contact_point;
384 const mrpt::math::TPoint2D pt_loc[nContactPoints] = {
390 fjd.
bodyB = b2dBody_;
392 for (
size_t i = 0; i < nContactPoints; i++)
394 const b2Vec2 local_pt =
b2Vec2(pt_loc[i].x, pt_loc[i].y);
412 const b2Vec2 wPt = b2dBody_->GetWorldPoint(
b2Vec2(applyPoint.x, applyPoint.y));
413 b2dBody_->ApplyForce(
b2Vec2(force.x, force.y), wPt,
true );
434 const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
435 const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical,
436 [[maybe_unused]]
bool childrenOnly)
438 if (!viz || !physical)
return;
440 for (
auto&
s :
sensors_)
s->guiUpdate(viz, physical);
445 using namespace mrpt::literals;
451 "[Block::internal_parseGeometry]");
453 if (_.typeStr.empty())
456 "Geometry type attribute is missing, i.e. <geometry type='...' ... "
460 _.type = mrpt::typemeta::str2enum<GeometryType>(_.typeStr);
466 ASSERTMSG_(_.radius > 0,
"Missing 'radius' attribute for cylinder geometry");
467 ASSERTMSG_(_.length > 0,
"Missing 'length' attribute for cylinder geometry");
469 if (_.vertex_count == 0) _.vertex_count = 10;
471 auto glCyl = mrpt::opengl::CCylinder::Create();
472 glCyl->setHeight(_.length);
473 glCyl->setRadius(_.radius);
474 glCyl->setSlicesCount(_.vertex_count);
482 ASSERTMSG_(_.radius > 0,
"Missing 'radius' attribute for cylinder geometry");
484 if (_.vertex_count == 0) _.vertex_count = 10;
486 auto glSph = mrpt::opengl::CSphere::Create(_.radius, _.vertex_count);
494 ASSERTMSG_(_.lx > 0,
"Missing 'lx' attribute for box geometry");
495 ASSERTMSG_(_.ly > 0,
"Missing 'ly' attribute for box geometry");
496 ASSERTMSG_(_.lz > 0,
"Missing 'lz' attribute for box geometry");
498 auto glBox = mrpt::opengl::CBox::Create();
499 glBox->setBoxCorners({0, 0, 0}, {_.lx, _.ly, _.lz});
507 ASSERTMSG_(_.lx > 0,
"Missing 'lx' attribute for semi_cylinder_bump geometry");
508 ASSERTMSG_(_.ly > 0,
"Missing 'ly' attribute for semi_cylinder_bump geometry");
509 ASSERTMSG_(_.lz > 0,
"Missing 'lz' attribute for semi_cylinder_bump geometry");
511 if (_.vertex_count == 0) _.vertex_count = 10;
513 auto glCyl = mrpt::opengl::CCylinder::Create();
514 glCyl->setHeight(_.lx);
515 glCyl->setRadius(_.ly * 0.5);
516 glCyl->setScale(2 * _.lz / _.ly, 1.0, 1.0);
518 glCyl->setSlicesCount(_.vertex_count);
522 glCyl, mrpt::poses::CPose3D::FromXYZYawPitchRoll(
523 -0.5 * _.lx, .0, .0, .0_deg, 90.0_deg, .0_deg));
529 ASSERTMSG_(_.lx > 0,
"Missing 'lx' attribute for ramp geometry");
530 ASSERTMSG_(_.ly > 0,
"Missing 'ly' attribute for ramp geometry");
531 ASSERTMSG_(_.lz > 0,
"Missing 'lz' attribute for ramp geometry");
533 auto glRamp = mrpt::opengl::CSetOfTriangles::Create();
535 const auto p0 = mrpt::math::TPoint3Df(0, -_.ly * 0.5, 0);
536 const auto p1 = mrpt::math::TPoint3Df(_.lx, -_.ly * 0.5, _.lz);
537 const auto p2 = mrpt::math::TPoint3Df(0, _.ly * 0.5, 0);
538 const auto p3 = mrpt::math::TPoint3Df(_.lx, _.ly * 0.5, _.lz);
539 const auto p4 = mrpt::math::TPoint3Df(_.lx, -_.ly * 0.5, 0);
540 const auto p5 = mrpt::math::TPoint3Df(_.lx, _.ly * 0.5, 0);
542 mrpt::opengl::TTriangle
t;
549 glRamp->insertTriangle(
t);
555 glRamp->insertTriangle(
t);
561 glRamp->insertTriangle(
t);
567 glRamp->insertTriangle(
t);
573 glRamp->insertTriangle(
t);
579 glRamp->insertTriangle(
t);
587 THROW_EXCEPTION_FMT(
"Unknown type in <geometry type='%s'...>", _.typeStr.c_str());
602 const auto localPt = myPose.inverseComposePoint(mrpt::math::TPoint3D(worldXY.x, worldXY.y, .0));
608 if (!
blockShape().contains({localPt.x, localPt.y}))
return {};
623 return myPose.z() + _.lz * localPt.x / _.lx;
628 std::sqrt(std::max<double>(.0, 1.0 - mrpt::square(2.0 * localPt.y / _.ly)));
629 return myPose.z() + _.lz *
f;