/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2024, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */
#pragma once

#include <mrpt/core/bits_math.h>  // .0_deg
#include <mrpt/math/TPose3D.h>
#include <mrpt/poses/CPose3DGridTemplate.h>
#include <mrpt/poses/CPose3DPDF.h>

namespace mrpt::poses
{
/** Declares a class that represents a Probability Distribution
 *  function (PDF) of a SE(3) pose (x,y,z, yaw, pitch, roll), in
 * the form of a 6-dimensional grid of "voxels".
 *
 * \sa CPose3D, CPose3DPDF, CPose3DGridTemplate
 * \ingroup poses_pdf_grp
 */
class CPose3DPDFGrid : public CPose3DPDF, public CPose3DGridTemplate<double>
{
  DEFINE_SERIALIZABLE(CPose3DPDFGrid, mrpt::poses)

 protected:
 public:
  /** Constructor: Initializes a, uniform distribution over the whole given
   * range, given by a "rectangular" (6D) bounding box.
   */
  CPose3DPDFGrid(
      const mrpt::math::TPose3D& bb_min =
          mrpt::math::TPose3D(-1., -1., -1., -M_PI, -.5 * M_PI, -.5 * M_PI),
      const mrpt::math::TPose3D& bb_max =
          mrpt::math::TPose3D(1., 1., 1., M_PI, .5 * M_PI, .5 * M_PI),
      double resolution_XYZ = 0.10,
      double resolution_YPR = mrpt::DEG2RAD(10.0));

  /** Destructor */
  ~CPose3DPDFGrid() override = default;

  /** Copy operator, translating if necessary (for example, between
   * particles and gaussian representations) */
  void copyFrom(const CPose3DPDF& o) override;

  /** Normalizes the PDF, such as all voxels sum the unity. */
  void normalize();

  /** Assigns the same value to all the cells in the grid, so the sum 1 */
  void uniformDistribution();

  void getMean(CPose3D& mean_pose) const override;

  std::tuple<cov_mat_t, type_value> getCovarianceAndMean() const override;

  /** Save the contents of the 3D grid in one file, as a concatenation of
   * (X,Y) slices. The size in X,Y,and the values for Z,yaw, pitch, roll, PHI
   * are stored in another file named `<filename>_dims.txt`
   * \return false on error */
  bool saveToTextFile(const std::string& dataFile) const override;

  // See base docs
  void changeCoordinatesReference(const CPose3D& newReferenceBase) override;
  // See base docs. Not implemented in this class.
  void bayesianFusion(const CPose3DPDF& p1, const CPose3DPDF& p2) override;

  // See base docs. Not implemented in this class.
  void inverse(CPose3DPDF& o) const override;

  /** Draws a single sample from the distribution.
   * \note Precondition: voxel weights are assumed to be normalized. */
  void drawSingleSample(CPose3D& outPart) const override;

  /** Draws a number of samples from the distribution, and saves as a list
   * of 1x6 vectors, where each row contains a (x,y,z,yaw,pitch,roll) datum.
   */
  void drawManySamples(size_t N, std::vector<mrpt::math::CVectorDouble>& outSamples) const override;

};  // End of class def.
}  // namespace mrpt::poses
