Skip to content

mrpt3: 3.1.4-1 in 'jazzy/distribution.yaml' [bloom] - #53767

Open
jlblancoc wants to merge 1 commit into
ros:masterfrom
jlblancoc:bloom-mrpt3-21
Open

mrpt3: 3.1.4-1 in 'jazzy/distribution.yaml' [bloom]#53767
jlblancoc wants to merge 1 commit into
ros:masterfrom
jlblancoc:bloom-mrpt3-21

Conversation

@jlblancoc

Copy link
Copy Markdown
Contributor

Increasing version of package(s) in repository mrpt3 to 3.1.4-1:

mrpt_apps_cli

* fix(mrpt_apps_cli): add missing <iostream> include in carmen2rawlog, gps2rawlog and carmen2simplemap, fixing the MSVC build.
* Contributors: Jose Luis Blanco-Claraco

mrpt_apps_gui

  • No changes

mrpt_bayes

  • No changes

mrpt_common

  • No changes

mrpt_comms

* test(mrpt_comms): raise unit test coverage of the TCP, HTTP, serial-port and pub/sub code (26%->76% lines) (#1391 <https://github.com/MRPT/mrpt/issues/1391>).
* fix(mrpt_comms): http_request() returned the payload padded with unused buffer tail instead of trimming to the bytes actually received.
* fix(mrpt_comms): CClientTCPSocket::connect() leaked the socket descriptor and misreported isConnected() when a later step in connect() failed.
* Contributors: Jose Luis Blanco-Claraco

mrpt_config

  • No changes

mrpt_containers

* fix(mrpt_containers): yaml double round-trip precision loss, %.16g -> %.17g (#1396 <https://github.com/MRPT/mrpt/issues/1396>).
* fix(mrpt_containers): yaml_ref/yaml_cref: add missing asSequenceRange() and yaml_cref::getOrDefault() (#1397 <https://github.com/MRPT/mrpt/issues/1397>, #1398 <https://github.com/MRPT/mrpt/issues/1398>).
* fix(mrpt_containers): yaml: fix a TOP comment corrupting the document on serialize+reparse (#1400 <https://github.com/MRPT/mrpt/issues/1400>).
* fix(mrpt_containers): yaml: keep an unquoted leading-zero digit run (e.g. "00") as a string instead of parsing it as a number (#1401 <https://github.com/MRPT/mrpt/issues/1401>).
* Contributors: Jose Luis Blanco-Claraco

mrpt_core

* fix(mrpt_core): fix precision loss in Clock::toDouble() (up to ~1 us) by doing the epoch shift in the integer domain instead of floating point.
* test(mrpt_core): add regression test for Clock::toDouble unsigned wraparound on pre-epoch timestamps (#1386 <https://github.com/MRPT/mrpt/issues/1386>).
* Contributors: Jose Luis Blanco-Claraco

mrpt_data

  • No changes

mrpt_examples_cpp

  • No changes

mrpt_expr

  • No changes

mrpt_graphs

  • No changes

mrpt_graphslam

* test(mrpt_graphslam): raise unit test coverage of TSlidingWindow and CEdgeCounter, previously untested (41%->72% lines) (#1389 <https://github.com/MRPT/mrpt/issues/1389>).
* fix(mrpt_graphslam): TSlidingWindow::getMean()/getStdDev() gave NaN/wrong results on a partially-filled window; resizeWindow() left the std-dev cache stale.
* fix(mrpt_graphslam): CEdgeCounter::clearAllEdges() left m_unique_edges stale.
* Contributors: Jose Luis Blanco-Claraco

mrpt_gui

  • No changes

mrpt_hwdrivers

  • No changes

mrpt_img

* fix(mrpt_img): fix CImage grayscale deserialization of legacy rawlogs storing PixelDepth as 0 (#1399 <https://github.com/MRPT/mrpt/issues/1399>).
* Contributors: Jose Luis Blanco-Claraco

mrpt_imgui

  • No changes

mrpt_io

* test(mrpt_io): raise unit test coverage of streams, compression and path helpers (63%->82% lines) (#1392 <https://github.com/MRPT/mrpt/issues/1392>).
* fix(mrpt_io): duplicate mrpt::io::CompressionType definition broke including both detect_compression.h and compression_options.h in the same translation unit.
* fix(mrpt_io): zip::decompress()'s std::vector overload passed zlib an uninitialized output-buffer capacity.
* fix(mrpt_io): CMemoryStream::Seek() from-end offsets were ignored and could underflow on an empty stream.
* fix(mrpt_io): CStream::getline() left a stray unwritten byte at end-of-stream.
* fix(mrpt_io): vectorNumericFromTextFile() discarded fscanf() failures, never cleared its output vector, and leaked the FILE handle.
* Contributors: Jose Luis Blanco-Claraco

mrpt_kinematics

* test(mrpt_kinematics): add a unit test suite (module had none), raising coverage to 97% (#1388 <https://github.com/MRPT/mrpt/issues/1388>).
* fix(mrpt_kinematics): CVehicleVelCmd's copy constructor delegated to operator=(), dispatching pure virtual methods during construction and aborting the process.
* docs(mrpt_kinematics): CKinematicChain::recomputeAllPoses()'s documented pose0 argument is actually ignored in favor of setOriginPose(); doc corrected to match.
* Contributors: Jose Luis Blanco-Claraco

mrpt_libapps_cli

  • No changes

mrpt_libapps_gui

  • No changes

mrpt_maps

* Merge pull request #1402 <https://github.com/MRPT/mrpt/issues/1402> from MRPT/fix/restore-cpointsmapxyzirt-serialization-compat
  Restore CPointsMapXYZIRT as a deserialization-only compat shim
* tests: cover the CPointsMapXYZIRT deserialization compat stub
  Also silence the expected deprecation warning at the class registration
  site.
* Restore CPointsMapXYZIRT as a deserialization-only compat shim
  Removing the class from the RTTI registry (during the mrpt_maps module
  port) broke loading of any pre-existing .simplemap/.rawlog file that
  has a CPointsMapXYZIRT point layer: CArchive::ReadObject() throws
  "Stored object has class 'mrpt::maps::CPointsMapXYZIRT' which is not
  registered!" for any such file, since the class name is still what was
  written to disk regardless of the deprecation.
  This class carries no functionality beyond decoding the old binary
  layout (X,Y,Z + optional intensity/ring/time buffers, unchanged from
  the original implementation) into a CGenericPointsMap, so anything
  downstream that reads points via the generic field interface keeps
  working transparently. New code should use CGenericPointsMap directly;
  this class is not meant to be constructed for anything but loading old
  data.
  Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
  Claude-Session: https://claude.ai/code/session_015w31kEa1kRfKA3rcqDRXyZ
* Merge pull request #1395 <https://github.com/MRPT/mrpt/issues/1395> from MRPT/test/coverage-2026-08-31
  test(slam): raise mrpt_slam coverage to 90% and fix the bugs it uncovered
* fix(slam): report stds_Q_no_odo's heading in degrees, as it is read
  Addresses review feedback on the new TOptions dumps: CRangeBearingKFSLAM2D
  loads the third component of stds_Q_no_odo in degrees, so the dump must not
  print it in radians. Also documents that TMetricMapInitializer::saveToConfigFile()
  only round-trips the generic map params, since there is no saving counterpart
  to loadFromConfigFile_map_specific().
* test(slam): raise mrpt_slam coverage to 90% and fix the bugs it uncovered
  Adds unit tests for the parts of mrpt_slam that had none, all driven by
  synthetic data (a simulated closed room for 2D scans, a small landmark map
  for range-bearing readings) so no dataset files are needed:
  * observations_overlap and CLandmarksMap, both previously at 0%
  * CIncrementalMapPartitioner beyond the dataset test: options I/O, the three
  similarity methods, node removal, origin changes, 3D scene, serialization
  * CMetricMapBuilderICP and its CMetricMapBuilder base
  * CMetricMapBuilderRBPF / CMultiMetricMapPDF, including range-only SLAM
  * CRangeBearingKFSLAM and CRangeBearingKFSLAM2D
  * CMonteCarloLocalization2D/3D over the four particle filter algorithms
  * TSetOfMetricMapInitializers config-file round trip (in mrpt_maps)
  mrpt_slam goes from 67.9%/45.4% to 90.2%/62.3% lines/branches; the repo-wide
  figure goes from 72.5%/53.2% to 73.6%/54.4%.
  Bugs found and fixed along the way:
  * observationsOverlap()'s CSensoryFrame overload ignored its relative-pose
  argument, so the observation-overlap similarity compared keyframes as if
  co-located.
  * CIncrementalMapPartitioner::addMapFrame() passed the same relative pose for
  both directions of its symmetrized similarity; the swapped evaluation needs
  the inverse. This moves one keyframe between partitions in the existing
  dataset test, whose expectations are updated.
  * removeSetOfNodes(..., changeCoordsRef=true) composed +p instead of -p,
  doubling the first node's coordinates instead of moving it to the origin.
  * Two options were loaded with a quoted name passed to
  MRPT_LOAD_HERE_CONFIG_VAR, which stringifies it again, so they could never
  be read from a config file.
  * CLandmarksMap was never registered for RTTI and could not be deserialized.
  * TSetOfMetricMapInitializers::saveToConfigFile() wrote a format that
  loadFromConfigFile() cannot read back.
  * CMultiMetricMapPDF::getLastPose() left its is_valid_pose output untouched
  on the success path.
  * CMetricMapBuilderICP::saveCurrentEstimationToImage() dereferenced a null
  gridmap pointer right after null-checking it.
  * The range-only branch of the RBPF optimal proposal never initialized
  firstEstimateRobotHeading when odometry was present, so it always tripped
  the assert guarding it; it also printed to std::cout per particle.
  Both KF-SLAM TOptions::dumpToTextStream() now report the noise parameters
  they load instead of silently omitting them.
* Contributors: Jose Luis Blanco-Claraco

mrpt_math

  • No changes

mrpt_nav

* Merge pull request #1388 <https://github.com/MRPT/mrpt/issues/1388> from MRPT/test/coverage-nav-kinematics
  test(mrpt_nav, mrpt_kinematics): raise coverage to 90%/97% and fix 10 bugs found on the way
* test(mrpt_nav): make two timing-sensitive navigator tests platform-independent
  The MSVC CI job failed on not_approaching_the_target_times_out: the test
  set alarm_seems_not_approaching_target_timeout to 0 and relied on two
  consecutive Clock::now() calls differing, which the Windows clock
  resolution does not guarantee. Both this test and the waypoint-alignment
  one now drive a simulated clock instead of depending on how fast the loop
  happens to run.
* fix(mrpt_nav): drop all cached expression state when a formula fails to compile
  Addresses review feedback: clearing only the map that failed left score
  names already registered as variables behind, so a first score that
  compiles followed by one that does not made the *next* decide() throw
  "Expression name already exists as an input variable". Both failure
  paths now go through clear(), and a regression test covers the case.
  Also replaces the hard-coded /tmp PTG cache directory in the new planner
  test with a portable temporary path.
* test(mrpt_nav): simulator robot interfaces, manual-sequence navigator and 3D reactive nav
  Covers the last sizeable gaps in the module: the ready-made
  CRobot2NavInterfaceForSimulator_{Holo,DiffDriven} adapters, the
  pre-programmed velocity-sequence navigator (config parsing for both
  kinematic models, the malformed-input rejections and the
  failed-command emergency stop), a CReactiveNavigationSystem3D run from
  an in-memory config, and the PTG collision-grid cache-file save/reload
  path.
  Also applies clang-format-14 to the new test files.
  Two more bugs found and fixed:
  * CReactiveNavigationSystem3D::saveConfigFile() never called the
  CAbstractPTGBasedReactive implementation, unlike its 2D sibling and
  contrary to the documented contract, so saving a 3D navigator's
  configuration produced a stub with only HEIGHT_LEVELS and PTG_COUNT
  that could not be loaded back.
  * PlannerSimple2D::computePath()'s "are the endpoints inside the grid?"
  guard read !(originInside || !targetInside), which flags exactly the
  wrong case: it only reported notFound when the origin was outside *and*
  the target inside, and let an out-of-grid target (or both endpoints out
  of grid) fall through into the search, contrary to its own documented
  behavior.
* test(mrpt_nav): holonomic method configuration and reactive-navigation variants
  Round-trips the config files and serialization of CHolonomicVFF/ND/FullEval
  and their log records, and adds reactive-navigation runs driven by fully
  in-memory configurations (so they never silently skip when the shared
  config files are missing) covering the optional features of
  CAbstractPTGBasedReactive: the delays model, clearance evaluation,
  velocity filtering, disabled obstacle filtering, log-record keeping and
  file writing, PTG restriction, runtime holonomic-method switching,
  robot-shape changes and the obstacle-sensor failure path.
  The runs use a CPTG_Holo_Blend so the "NOP cmdvel" PTG-continuation
  branches are exercised too, which the differential-drive PTGs of the
  existing rnav tests cannot reach.
* test(mrpt_nav): cover the clearance diagram, planners, log records and motion optimizers
  Adds unit tests for the pieces of mrpt_nav that no existing test
  touched: ClearanceDiagram (index mapping, serialization, 3D rendering),
  the arc-vs-circular-robot collision helper, the default
  CRobot2NavInterface callbacks, NavigationLogger, VelocityFilter, the
  multi-objective motion optimizers, the RRT move-tree 3D renderer and a
  fully-populated CLogFileRecord round-trip.
  Bugs found and fixed along the way:
  * CMultiObjectiveMotionOptimizerBase::decide() returned -1 from a
  function returning std::optional<size_t> when a user formula failed to
  compile. That is an *engaged* optional holding SIZE_MAX, so instead of
  the documented "no valid candidate", callers indexed the candidate
  vector out of bounds.
  * CMultiObjectiveMotionOptimizerBase::clear() dropped the compiled score
  expressions but kept the variable table, so the next decide() threw
  "Expression name already exists as an input variable" -- i.e. the
  documented way to re-apply changed parameters was unusable.
  * CLogFileRecord's legacy (pre-v15) deserialization wrote every velocity
  command component into the wrong slot: one loop indexed with the outer
  loop variable, and the oldest format wrote both v and w into element 0.
* test(mrpt_kinematics,mrpt_nav): unit tests for the kinematics and navigation stack
  mrpt_kinematics had no C++ unit tests at all; mrpt_nav's were limited to
  the reactive-navigation integration tests plus a few data structures.
  New tests cover CVehicleVelCmd (both kinematic models), the vehicle
  simulators, CKinematicChain, TWaypoint/TWaypointSequence, the whole PTG
  family (including CPTG_DiffDrive_CC/CS/CCS, previously never
  instantiated) and the CAbstractNavigator/CWaypointsNavigator state
  machine.
  Bugs found and fixed along the way:
  * CVehicleVelCmd's copy constructor delegated to operator=(), which
  dispatches pure virtual methods while the derived object is still under
  construction: copy-constructing any velocity command aborted the
  process.
  * CAbstractNavigator::internal_onStartNewNavigation() cleared the cached
  pose history but left the last-query timestamp untouched, so the
  updateCurrentPoseAndSpeeds() call right after it could be skipped by
  its minimum-period throttle and leave the cache empty. The following
  ASSERT_(!m_latestPoses.empty()) then threw on the first navigation step
  of every waypoint mission and of every relative-target navigation.
  * CAbstractNavigator::performNavigationStepNavigating() restored
  m_navigationState from its entry value on exit, undoing the very
  transitions it had just decided: neither an exception nor
  doEmergencyStop() could leave the navigator in NAV_ERROR. The
  assignment was meant for m_lastNavigationState, mirroring
  navigationStep().
  * CWaypointsNavigator::checkHasReachedTarget() dereferenced a possibly
  null waypoint pointer whenever the robot was farther than the allowed
  distance and the waypoint list was empty or its index out of range.
  * CParameterizedTrajectoryGenerator::Alpha2index() discarded the result
  of wrapToPi(), so directions outside [-pi,pi] were clamped to the first
  or last path instead of wrapping around.
* Contributors: Jose Luis Blanco-Claraco

mrpt_obs

* Merge pull request #1395 <https://github.com/MRPT/mrpt/issues/1395> from MRPT/test/coverage-2026-08-31
  test(slam): raise mrpt_slam coverage to 90% and fix the bugs it uncovered
* fix(slam): report stds_Q_no_odo's heading in degrees, as it is read
  Addresses review feedback on the new TOptions dumps: CRangeBearingKFSLAM2D
  loads the third component of stds_Q_no_odo in degrees, so the dump must not
  print it in radians. Also documents that TMetricMapInitializer::saveToConfigFile()
  only round-trips the generic map params, since there is no saving counterpart
  to loadFromConfigFile_map_specific().
* test(slam): raise mrpt_slam coverage to 90% and fix the bugs it uncovered
  Adds unit tests for the parts of mrpt_slam that had none, all driven by
  synthetic data (a simulated closed room for 2D scans, a small landmark map
  for range-bearing readings) so no dataset files are needed:
  * observations_overlap and CLandmarksMap, both previously at 0%
  * CIncrementalMapPartitioner beyond the dataset test: options I/O, the three
  similarity methods, node removal, origin changes, 3D scene, serialization
  * CMetricMapBuilderICP and its CMetricMapBuilder base
  * CMetricMapBuilderRBPF / CMultiMetricMapPDF, including range-only SLAM
  * CRangeBearingKFSLAM and CRangeBearingKFSLAM2D
  * CMonteCarloLocalization2D/3D over the four particle filter algorithms
  * TSetOfMetricMapInitializers config-file round trip (in mrpt_maps)
  mrpt_slam goes from 67.9%/45.4% to 90.2%/62.3% lines/branches; the repo-wide
  figure goes from 72.5%/53.2% to 73.6%/54.4%.
  Bugs found and fixed along the way:
  * observationsOverlap()'s CSensoryFrame overload ignored its relative-pose
  argument, so the observation-overlap similarity compared keyframes as if
  co-located.
  * CIncrementalMapPartitioner::addMapFrame() passed the same relative pose for
  both directions of its symmetrized similarity; the swapped evaluation needs
  the inverse. This moves one keyframe between partitions in the existing
  dataset test, whose expectations are updated.
  * removeSetOfNodes(..., changeCoordsRef=true) composed +p instead of -p,
  doubling the first node's coordinates instead of moving it to the origin.
  * Two options were loaded with a quoted name passed to
  MRPT_LOAD_HERE_CONFIG_VAR, which stringifies it again, so they could never
  be read from a config file.
  * CLandmarksMap was never registered for RTTI and could not be deserialized.
  * TSetOfMetricMapInitializers::saveToConfigFile() wrote a format that
  loadFromConfigFile() cannot read back.
  * CMultiMetricMapPDF::getLastPose() left its is_valid_pose output untouched
  on the success path.
  * CMetricMapBuilderICP::saveCurrentEstimationToImage() dereferenced a null
  gridmap pointer right after null-checking it.
  * The range-only branch of the RBPF optimal proposal never initialized
  firstEstimateRobotHeading when odometry was present, so it always tripped
  the assert guarding it; it also printed to std::cout per particle.
  Both KF-SLAM TOptions::dumpToTextStream() now report the noise parameters
  they load instead of silently omitting them.
* Contributors: Jose Luis Blanco-Claraco

mrpt_opengl

  • No changes

mrpt_poses

  • No changes

mrpt_random

  • No changes

mrpt_rtti

* test(mrpt_rtti): add unit tests for the class registry, derivedFrom(), cloning of non-copy-constructible classes and CListOfClasses (#1390 <https://github.com/MRPT/mrpt/issues/1390>).
* fix(mrpt_rtti): internal_ReadObjectHeader()'s error message passed the archive description and class name in the wrong order.
* Contributors: Jose Luis Blanco-Claraco

mrpt_serialization

* test(mrpt_serialization): add a unit test suite (module had none) covering CArchive, CMessage, and STL/std::optional serialization (#1390 <https://github.com/MRPT/mrpt/issues/1390>).
* fix(mrpt_serialization): CMessage::sendMessage()/receiveMessage() used mismatched byte order for the payload length (no message >= 256 bytes could be received) and misread an empty payload as a framing error; sendMessage() now also rejects payloads too large for the 16-bit length field instead of overflowing the frame buffer.
* fix(mrpt_serialization): operator<<(std::monostate) writes no version byte, but the reader only skipped it for "nullptr", so an empty std::variant failed to deserialize.
* Contributors: Jose Luis Blanco-Claraco

mrpt_slam

* Merge pull request #1395 <https://github.com/MRPT/mrpt/issues/1395> from MRPT/test/coverage-2026-08-31
  test(slam): raise mrpt_slam coverage to 90% and fix the bugs it uncovered
* test(slam): give simulated SLAM steps explicit, increasing timestamps
  Clock::now() has a ~15 ms resolution on Windows, so calling it once per
  simulated step returned the same timestamp for consecutive odometry actions.
  CRobot2DPoseEstimator drops updates whose timestamp does not advance, so the
  ICP map builder's pose estimate never moved and the test failed there.
  Timestamps now come from a helper that hands out values 100 ms apart, with the
  action and the observation of each step sharing the same one.
* test(slam): do not depend on the order of the spectral partitions
  The two clusters returned by RecursiveSpectralPartition() are stable, but
  which one comes first depends on the sign of the eigenvector and differs
  between platforms (the macOS CI job returned them swapped). Compare them in a
  canonical order instead.
* fix(slam): report stds_Q_no_odo's heading in degrees, as it is read
  Addresses review feedback on the new TOptions dumps: CRangeBearingKFSLAM2D
  loads the third component of stds_Q_no_odo in degrees, so the dump must not
  print it in radians. Also documents that TMetricMapInitializer::saveToConfigFile()
  only round-trips the generic map params, since there is no saving counterpart
  to loadFromConfigFile_map_specific().
* test(slam): raise mrpt_slam coverage to 90% and fix the bugs it uncovered
  Adds unit tests for the parts of mrpt_slam that had none, all driven by
  synthetic data (a simulated closed room for 2D scans, a small landmark map
  for range-bearing readings) so no dataset files are needed:
  * observations_overlap and CLandmarksMap, both previously at 0%
  * CIncrementalMapPartitioner beyond the dataset test: options I/O, the three
  similarity methods, node removal, origin changes, 3D scene, serialization
  * CMetricMapBuilderICP and its CMetricMapBuilder base
  * CMetricMapBuilderRBPF / CMultiMetricMapPDF, including range-only SLAM
  * CRangeBearingKFSLAM and CRangeBearingKFSLAM2D
  * CMonteCarloLocalization2D/3D over the four particle filter algorithms
  * TSetOfMetricMapInitializers config-file round trip (in mrpt_maps)
  mrpt_slam goes from 67.9%/45.4% to 90.2%/62.3% lines/branches; the repo-wide
  figure goes from 72.5%/53.2% to 73.6%/54.4%.
  Bugs found and fixed along the way:
  * observationsOverlap()'s CSensoryFrame overload ignored its relative-pose
  argument, so the observation-overlap similarity compared keyframes as if
  co-located.
  * CIncrementalMapPartitioner::addMapFrame() passed the same relative pose for
  both directions of its symmetrized similarity; the swapped evaluation needs
  the inverse. This moves one keyframe between partitions in the existing
  dataset test, whose expectations are updated.
  * removeSetOfNodes(..., changeCoordsRef=true) composed +p instead of -p,
  doubling the first node's coordinates instead of moving it to the origin.
  * Two options were loaded with a quoted name passed to
  MRPT_LOAD_HERE_CONFIG_VAR, which stringifies it again, so they could never
  be read from a config file.
  * CLandmarksMap was never registered for RTTI and could not be deserialized.
  * TSetOfMetricMapInitializers::saveToConfigFile() wrote a format that
  loadFromConfigFile() cannot read back.
  * CMultiMetricMapPDF::getLastPose() left its is_valid_pose output untouched
  on the success path.
  * CMetricMapBuilderICP::saveCurrentEstimationToImage() dereferenced a null
  gridmap pointer right after null-checking it.
  * The range-only branch of the RBPF optimal proposal never initialized
  firstEstimateRobotHeading when odometry was present, so it always tripped
  the assert guarding it; it also printed to std::cout per particle.
  Both KF-SLAM TOptions::dumpToTextStream() now report the noise parameters
  they load instead of silently omitting them.
* Merge pull request #1389 <https://github.com/MRPT/mrpt/issues/1389> from MRPT/test/coverage-graphslam-system-io
  test(graphslam, system, io, slam): cover the largest untested pure-logic files, fix 8 bugs
* test(graphslam,system,io,slam): cover the largest untested pure-logic files
  Second coverage pass, on the four biggest pure-logic gaps left after
  mrpt_nav/mrpt_kinematics:
  mrpt_graphslam  41.0% -> 72.5% lines (33.0% -> 59.6% branches)
  mrpt_slam       64.1% -> 67.5%       (43.1% -> 44.9%)
  mrpt_io         57.0% -> 63.6%       (40.2% -> 46.4%)
  mrpt_system     54.4% -> 61.7%       (40.5% -> 41.9%)
  Five files that had never had a single assertion run against them are now
  covered: TSlidingWindow.cpp, CEdgeCounter.cpp, md5.cpp,
  CRejectionSamplingRangeOnlyLocalization.cpp (all 0%) and
  vector_loadsave.cpp (16%).
  Bugs found and fixed, each reproduced by a failing test first:
  * TSlidingWindow::getMean() divided by zero on an empty window and
  returned NaN. Since every comparison against a NaN is false,
  evaluateMeasurementAbove() was then stuck at false for any input.
  * TSlidingWindow::getStdDev() normalized by the window capacity instead
  of the number of measurements held, so a partially-filled window
  systematically under-reported sigma -- and disagreed with getMean(),
  which uses the sample count.
  * TSlidingWindow::resizeWindow() invalidated the mean and median caches
  but never the std-dev one: stale after a shrink, and on a grow it
  invalidated nothing at all even though the value depends on the window
  size.
  * CEdgeCounter::clearAllEdges() reset every counter except
  m_unique_edges, so a cleared instance still reported a stale
  unique-edge total.
  * mrpt::system::md5(const std::vector<uint8_t>&) used &str[0], an
  out-of-bounds access for an empty vector whose resulting pointer then
  tripped the ASSERT_(data) of the overload it delegates to: md5() of an
  empty vector threw, while md5() of an empty string returned the
  correct digest. The algorithm itself passes every RFC 1321 vector.
  * mrpt::io::vectorNumericFromTextFile() had three defects: it discarded
  fscanf()'s return value in its default byRows==false path (the
  (!byRows) || short-circuits), so a failed read still pushed the stale
  value and an empty file yielded {0.0}; it never cleared its output
  vector, unlike loadTextFile()/loadBinaryFile(); and it leaked the FILE
  handle that every sibling function in the same file closes.
  CRejectionSamplingRangeOnlyLocalization was the largest 0% file in the
  repo but its 10 new tests all passed first time: it was untested, not
  broken.
  agents.md records the new numbers, the two behaviors left documented
  rather than changed, and a gotcha about the reproduce recipe: it excludes
  apps/, so mrpt_libapps_cli's ~40 CLI tests silently skip and the module
  measures ~8% instead of ~59%.
* Contributors: Jose Luis Blanco-Claraco

mrpt_system

* Merge pull request #1393 <https://github.com/MRPT/mrpt/issues/1393> from MRPT/test/coverage-system
  test(mrpt_system): cover the untested helpers and the file system watcher
* Merge remote-tracking branch 'origin/develop' into test/coverage-comms
* Merge remote-tracking branch 'origin/develop' into test/coverage-system
* fix(mrpt_system): don't use CancelIoEx in the watcher destructor
  It is not declared with the SDK settings this build uses. Closing the
  notification handle already makes the watch thread's pending
  ReadDirectoryChangesW() return, which is what the join needs.
* fix(mrpt_system): join CFileSystemWatcher's watch thread on destruction
  On Windows the constructor starts a std::thread and the destructor only
  closed the notification handle, so destroying a successfully-constructed
  watcher hit std::thread's destructor with a joinable thread and called
  std::terminate(). The new unit tests are the first code to ever destroy one,
  and they took the whole test binary down with them.
  The pending ReadDirectoryChangesW() is now cancelled before the handle is
  closed, the thread is joined, and whatever it had queued but nobody read is
  freed instead of leaked.
  Also fixes the POSIX branch, which called inotify_rm_watch() with a
  descriptor it had already closed and reset to -1.
* Merge pull request #1392 <https://github.com/MRPT/mrpt/issues/1392> from MRPT/test/coverage-io
  test(mrpt_io): cover the stream, compression and path helpers
* test(mrpt_system): skip the missing-directory watcher test where unsupported
  Without inotify (macOS, and any other platform with no notification
  backend) CFileSystemWatcher's constructor is a no-op, so it never notices
  that the watched directory does not exist. Skip that expectation there, and
  pin the empty-path assertion, which does hold everywhere.
* test(mrpt_system): cover the untested helpers and the file system watcher
  Four files in this module had never had an assertion run against them
  (CFileSystemWatcher.cpp, CObserver.cpp, progress.cpp,
  hyperlink.cpp), and several others were only covered incidentally by other
  modules' tests.
  New test files:
  * CFileSystemWatcher_unittest.cpp watches a temporary directory and checks
  that file creation, deletion and sub-directory creation are all reported,
  skipping itself where the platform provides no notification support
  (0% -> 91%).
  * CObserver_unittest.cpp covers the observer/observable pair: publishing to
  several subscribers, unsubscribing, and the two destruction orders --
  observer first and observable first, the latter of which publishes
  mrptEventOnDestroy before dropping everyone.
  * misc_system_unittest.cpp covers progress(), hyperlink(), the CRC
  helpers, every thread and process priority level, and CRateTimer.
  * os_unittest.cpp covers the os:: C-library wrappers, getMRPTLicense(),
  executeCommand() (including its working-directory form), launchProcess()
  and the plug-in loader's failure paths.
  * datetime_format_unittest.cpp covers the timestamp formatters, the
  parts/timestamp round trip in both UTC and local time, and every unit
  branch of intervalFormat() (16.7% -> 97.0% for datetime.cpp).
  Bugs found and fixed:
  * mrpt::system::consoleColorAndStyle() had its stream selection inverted:
  applyToStdErr = true emitted the escape sequence on **stdout** and vice
  versa. COutputLogger passes that flag for its error-level messages, so the
  color codes landed on the opposite stream from the text they were meant to
  color. Its memo of the last colors applied was also shared between the two
  streams, which would suppress a needed escape sequence when alternating
  between them; it is now kept per stream.
  Module coverage: 66.0% -> 82.5% lines, 48.2% -> 62.3% branches.
* test(mrpt_io): cover the stream, compression and path helpers
  New test files for the parts of the module that had never been exercised
  directly: CStream's printf/printf_vector/getline, CMemoryStream's cursor and
  buffer management, the file input/output streams (including every error
  path), the compressed streams (a parameterized round-trip over None/Gzip/Zstd
  plus the CFileGZ* pair), the zip:: helpers, detect_compression, the lazy-load
  path helpers and CTextFileLinesParser.
  Bugs found and fixed:
  * mrpt::io::CompressionType was defined twice, identically, in
  detect_compression.h and in compression_options.h, both in namespace
  mrpt::io: including both headers in the same translation unit did not
  compile. detect_compression.h now includes the other one.
  * zip::decompress()'s std::vector overload passed an *uninitialized*
  length to zlib's uncompress(), which takes it as the capacity of the
  output buffer, so zlib was free to write past the end of the vector and
  the returned size was garbage. The three sibling overloads all initialize
  it correctly.
  * mrpt::system::getFileSize() is documented to return size_t(-1) when
  the file cannot be accessed, but used the throwing overload of
  std::filesystem::file_size. Every caller testing for -1 --
  CFileGZInputStream::open() and, through it, zip::decompress_gz_file(),
  both documented to report failure by returning false -- threw instead.
  * CMemoryStream::Seek() used the Origin enumerator in place of Offset
  in its "from the end" case, so the requested offset was ignored entirely;
  it also clamped to the *allocated* size minus one, which underflowed to a
  huge value on an empty stream and made the end-of-data position
  unreachable. It now behaves like the file streams: offsets are relative to
  the chosen origin and clamped to [0, bytesWritten].
  * CStream::getline() left an unwritten byte in the output string when it
  hit the end of the stream, so the last line of a file without a trailing
  newline came back with a stray trailing null character.
  Left documented rather than changed: CFileGZInputStream and
  CCompressedInputStream's single-argument constructors both document an
  exception on failure but ignore open()'s result, so they silently yield a
  closed stream, while their output counterparts do throw. Changing that would
  alter the contract of zip::decompress_gz_file(), which relies on the
  non-throwing behavior.
  Module coverage: 63.5% -> 82.5% lines, 43.5% -> 62.2% branches.
* Merge pull request #1389 <https://github.com/MRPT/mrpt/issues/1389> from MRPT/test/coverage-graphslam-system-io
  test(graphslam, system, io, slam): cover the largest untested pure-logic files, fix 8 bugs
* test(mrpt_system): drop a rate-dependent CControlledRateTimer assertion
  The "larger a0 keeps the estimate nearer the set-point" test only holds
  while the achieved rate is far from the set-point. On a machine that hits
  the target accurately the raw rate *is* the set-point, both filter
  settings converge on it, and the comparison is decided by noise -- which
  is how it failed on the ubuntu-clang runner.
  The two remaining tests pin the filter's weighting without depending on
  the rate actually achieved: with a0 == 1 the estimate must ignore the
  measurement entirely, and with a0 ~ 0 it must equal it. A comment records
  why the third test is deliberately absent.
* docs(mrpt_system): correct CControlledRateTimer's documented filter and defaults
  The header described the rate estimator's low-pass filter as
  estimation = a0*input + (1-a0)*former_estimation, but the
  implementation applies those weights the other way round, so the meaning
  of a0 was inverted in the docs: larger values smooth *more*, not less.
  Two documented default values were also stale: Ti is 0.1 (documented
  as 0.0194) and a0 is 0.99 (documented as 0.9).
  Only the documentation changed. The control law is the sensible reading
  for a low-pass filter and the PI gains were presumably tuned against it.
  A new CControlledRateTimer_unittest.cpp pins both halves so they cannot
  drift apart again: it asserts the documented defaults, and asserts that
  with a0 == 1 the estimate ignores the measurement entirely and stays on
  the set-point (under the previously-documented formula it would instead
  equal the raw measured rate). Parameter validation and setRate() are
  covered too.
* test(graphslam,system,io,slam): cover the largest untested pure-logic files
  Second coverage pass, on the four biggest pure-logic gaps left after
  mrpt_nav/mrpt_kinematics:
  mrpt_graphslam  41.0% -> 72.5% lines (33.0% -> 59.6% branches)
  mrpt_slam       64.1% -> 67.5%       (43.1% -> 44.9%)
  mrpt_io         57.0% -> 63.6%       (40.2% -> 46.4%)
  mrpt_system     54.4% -> 61.7%       (40.5% -> 41.9%)
  Five files that had never had a single assertion run against them are now
  covered: TSlidingWindow.cpp, CEdgeCounter.cpp, md5.cpp,
  CRejectionSamplingRangeOnlyLocalization.cpp (all 0%) and
  vector_loadsave.cpp (16%).
  Bugs found and fixed, each reproduced by a failing test first:
  * TSlidingWindow::getMean() divided by zero on an empty window and
  returned NaN. Since every comparison against a NaN is false,
  evaluateMeasurementAbove() was then stuck at false for any input.
  * TSlidingWindow::getStdDev() normalized by the window capacity instead
  of the number of measurements held, so a partially-filled window
  systematically under-reported sigma -- and disagreed with getMean(),
  which uses the sample count.
  * TSlidingWindow::resizeWindow() invalidated the mean and median caches
  but never the std-dev one: stale after a shrink, and on a grow it
  invalidated nothing at all even though the value depends on the window
  size.
  * CEdgeCounter::clearAllEdges() reset every counter except
  m_unique_edges, so a cleared instance still reported a stale
  unique-edge total.
  * mrpt::system::md5(const std::vector<uint8_t>&) used &str[0], an
  out-of-bounds access for an empty vector whose resulting pointer then
  tripped the ASSERT_(data) of the overload it delegates to: md5() of an
  empty vector threw, while md5() of an empty string returned the
  correct digest. The algorithm itself passes every RFC 1321 vector.
  * mrpt::io::vectorNumericFromTextFile() had three defects: it discarded
  fscanf()'s return value in its default byRows==false path (the
  (!byRows) || short-circuits), so a failed read still pushed the stale
  value and an empty file yielded {0.0}; it never cleared its output
  vector, unlike loadTextFile()/loadBinaryFile(); and it leaked the FILE
  handle that every sibling function in the same file closes.
  CRejectionSamplingRangeOnlyLocalization was the largest 0% file in the
  repo but its 10 new tests all passed first time: it was untested, not
  broken.
  agents.md records the new numbers, the two behaviors left documented
  rather than changed, and a gotcha about the reproduce recipe: it excludes
  apps/, so mrpt_libapps_cli's ~40 CLI tests silently skip and the module
  measures ~8% instead of ~59%.
* Contributors: Jose Luis Blanco-Claraco

mrpt_tfest

  • No changes

mrpt_topography

  • No changes

mrpt_typemeta

  • No changes

mrpt_viz

  • No changes

@github-actions github-actions Bot added the jazzy Issue/PR is for the ROS 2 Jazzy distribution label Sep 4, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For changes related to rosdistro:

  • ✅ New packages are named appropriately
  • ✅ An up-to-date Bloom version was used
  • ✅ Release changes are confined to a single distribution

For changes related to yamllint:

  • ✅ All new lines of YAML pass linter checks

@ahcorde ahcorde left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ahcorde ahcorde added the held for sync Issue/PR has been held because the distribution is in a sync hold label Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

held for sync Issue/PR has been held because the distribution is in a sync hold jazzy Issue/PR is for the ROS 2 Jazzy distribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants