10 #include <mrpt/core/lock_helper.h>
11 #include <mrpt/opengl/COpenGLScene.h>
12 #include <mrpt/opengl/stock_objects.h>
13 #include <mrpt/random.h>
14 #include <mrpt/version.h>
22 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
23 #include <mvsim/mvsim-msgs/ObservationLidar2D.pb.h>
26 using namespace mvsim;
52 params[
"fov_degrees"] =
TParamEntry(
"%lf", &fov_deg);
86 const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
87 [[maybe_unused]]
const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical,
88 [[maybe_unused]]
bool childrenOnly)
90 using namespace std::string_literals;
92 mrpt::opengl::CSetOfObjects::Ptr glVizSensors;
95 glVizSensors = std::dynamic_pointer_cast<mrpt::opengl::CSetOfObjects>(
96 viz->get().getByName(
"group_sensors_viz"));
97 if (!glVizSensors)
return;
103 gl_scan_ = mrpt::opengl::CPlanarLaserScan::Create();
108 gl_scan_->setPointsColor(ptsCol.R, ptsCol.G, ptsCol.B, ptsCol.A);
112 gl_scan_->setSurfaceColor(planeCol.R, planeCol.G, planeCol.B, planeCol.A);
116 gl_scan_->setLocalRepresentativePoint({0, 0, 0.10f});
124 #if MRPT_VERSION >= 0x270
138 #if MRPT_VERSION >= 0x270
142 auto fovScan = mrpt::opengl::CPlanarLaserScan::Create();
143 fovScan->enablePoints(
false);
144 fovScan->enableSurface(
true);
147 const float f = 0.30f;
148 for (
size_t i = 0; i <
s.getScanSize(); i++)
150 s.setScanRange(i,
f);
151 s.setScanRangeValidity(i,
true);
180 const double z_incrs = 1e-3;
181 const double z_offset = 1e-3;
186 p2.z_incr(z_offset + z_incrs *
z_order_);
212 mrpt::system::LVL_WARN,
213 "Time for a new sample came without still simulating the "
214 "last one (!) for simul_time=%.03f s.",
230 const auto globalSensorPose = p +
scan_model_.sensorPose.asTPose();
239 scan_model_.sensorPose = mrpt::poses::CPose3D(newPose - p);
244 using mrpt::maps::COccupancyGridMap2D;
245 using mrpt::obs::CObservation2DRangeScan;
252 std::list<CObservation2DRangeScan> lstScans;
266 for (
const auto& element : elements)
271 const COccupancyGridMap2D& occGrid = grid->
getOccGrid();
275 CObservation2DRangeScan& scan = lstScans.back();
278 occGrid.laserScanSimulator(
288 lstScans.push_back(CObservation2DRangeScan(
scan_model_));
289 CObservation2DRangeScan& scan = lstScans.back();
292 std::map<b2Fixture*, uintptr_t> orgUserData;
297 orgUserData[
f] =
f->GetUserData().pointer;
300 auto undoInvisibleFixtures = [&]()
302 for (
auto& kv : orgUserData) kv.first->GetUserData().pointer = kv.second;
307 makeFixtureInvisible(v->get_fixture_chassis());
308 for (
auto&
f : v->get_fixture_wheels()) makeFixtureInvisible(
f);
321 float fraction)
override
349 const mrpt::poses::CPose2D sensorPose = vehPose + mrpt::poses::CPose2D(scan.sensorPose);
350 const b2Vec2 sensorPt =
b2Vec2(sensorPose.x(), sensorPose.y());
357 scan.resizeScanAndAssign(nRays, maxRange,
false);
358 double A = sensorPose.phi() + (scan.rightToLeft ? -0.5 : +0.5) * scan.aperture;
359 const double AA = (scan.rightToLeft ? 1.0 : -1.0) * (scan.aperture / (nRays - 1));
362 thread_local mrpt::random::CRandomGenerator rnd;
364 for (
size_t i = 0; i < nRays; i++,
A += AA)
367 b2Vec2(sensorPt.
x + cos(
A) * maxRange, sensorPt.
y + sin(
A) * maxRange);
369 callback.hit_ =
false;
371 scan.setScanRangeValidity(i, callback.hit_);
378 mrpt::square(callback.point_.x - sensorPt.
x) +
379 mrpt::square(callback.point_.y - sensorPt.
y));
387 scan.setScanRange(i, range);
390 undoInvisibleFixtures();
398 auto lastScan = CObservation2DRangeScan::Create(
scan_model_);
401 lastScan->sensorLabel =
name_;
403 lastScan->resizeScanAndAssign(nRays, maxRange,
false);
405 for (
const auto& scan : lstScans)
407 for (
size_t i = 0; i < nRays; i++)
409 if (scan.getScanRangeValidity(i))
411 lastScan->setScanRange(
412 i, std::min(lastScan->getScanRange(i), scan.getScanRange(i)));
413 lastScan->setScanRangeValidity(i,
true);
442 using namespace mrpt;
451 auto tle1 = mrpt::system::CTimeLoggerEntry(
world_->
getTimeLogger(),
"sensor.2Dlidar.acqGuiMtx");
458 auto curObs = mrpt::obs::CObservation2DRangeScan::Create(
scan_model_);
464 curObs->sensorLabel =
name_;
466 curObs->resizeScanAndAssign(nRays, maxRange,
false);
469 constexpr
int FBO_NROWS = 1;
470 constexpr
int FBO_NCOLS = 500;
471 constexpr
double camModel_FOV = 150.0_deg;
472 mrpt::img::TCamera camModel;
473 camModel.ncols = FBO_NCOLS;
474 camModel.nrows = FBO_NROWS;
475 camModel.cx(camModel.ncols / 2.0);
476 camModel.cy(camModel.nrows / 2.0);
477 camModel.fx(camModel.cx() / tan(camModel_FOV * 0.5));
478 camModel.fy(camModel.fx());
482 mrpt::opengl::CFBORender::Parameters p;
484 p.height = FBO_NROWS;
490 auto viewport = world3DScene.getViewport();
494 const auto fixedAxisConventionRot =
495 mrpt::poses::CPose3D(0, 0, 0, -90.0_deg, 0.0_deg, -90.0_deg);
503 const auto firstAngle = curObs->getScanAngle(0);
504 const auto lastAngle = curObs->getScanAngle(curObs->getScanSize() - 1);
505 const bool scanIsCW = (lastAngle > firstAngle);
506 ASSERT_NEAR_(std::abs(lastAngle - firstAngle), curObs->aperture, 1e-3);
508 const unsigned int numRenders = std::ceil((curObs->aperture / camModel_FOV) - 1e-3);
509 const auto numRaysPerRender =
510 mrpt::round(nRays * std::min<double>(1.0, (camModel_FOV / curObs->aperture)));
512 ASSERT_(numRaysPerRender > 0);
524 for (
int i = 0; i < numRaysPerRender; i++)
526 const auto ang = (scanIsCW ? -1 : 1) *
527 (camModel_FOV * 0.5 - i * camModel_FOV / (numRaysPerRender - 1));
529 const auto pixelIdx = mrpt::saturate_val<int>(
530 mrpt::round(camModel.cx() - camModel.fx() * std::tan(ang)), 0, camModel.ncols - 1);
546 cam.set6DOFMode(
true);
547 cam.setProjectiveFromPinhole(camModel);
550 #if MRPT_VERSION >= 0x270
551 const bool wasShadowEnabled = viewport->isShadowCastingEnabled();
552 viewport->enableShadowCasting(
false);
555 viewport->setViewportClipDistances(0.01, curObs->maxRange);
556 mrpt::math::CMatrixFloat depthImage;
561 bool formerVisVehState =
true;
567 visVeh->customVisualVisible(
false);
569 if (veh) veh->chassisAndWheelsVisible(
false);
572 for (
size_t renderIdx = 0; renderIdx < numRenders; renderIdx++)
574 const double thisRenderMidAngle =
575 firstAngle + (camModel_FOV / 2.0 + camModel_FOV * renderIdx) * (scanIsCW ? 1 : -1);
577 const auto depthSensorPose =
578 vehiclePose + curObs->sensorPose +
579 mrpt::poses::CPose3D::FromYawPitchRoll(thisRenderMidAngle, 0.0, 0.0) +
580 fixedAxisConventionRot;
585 cam.setPose(
world()->applyWorldRenderOffset(depthSensorPose));
601 thread_local mrpt::random::CRandomGenerator rng;
603 float*
d = depthImage.data();
604 const size_t N = depthImage.size();
605 for (
size_t i = 0; i < N; i++)
607 if (
d[i] == 0)
continue;
611 if (dNoisy < 0 || dNoisy > curObs->maxRange)
continue;
621 for (
int i = 0; i < numRaysPerRender; i++)
623 const auto scanRayIdx = numRaysPerRender * renderIdx + i;
625 if (scanRayIdx >= curObs->getScanSize())
break;
629 const float d = depthImage(0, u);
632 if (range <= 0 || range >= curObs->maxRange)
continue;
634 curObs->setScanRange(scanRayIdx, range);
635 curObs->setScanRangeValidity(scanRayIdx,
true);
642 if (visVeh) visVeh->customVisualVisible(formerVisVehState);
643 if (veh) veh->chassisAndWheelsVisible(formerVisVehState);
646 #if MRPT_VERSION >= 0x270
647 viewport->enableShadowCasting(wasShadowEnabled);
684 using namespace std::string_literals;
688 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)