arma::Cube<double> MultiLevelStewartPlatform::getModelImplementation(
        const arma::Col<double>& endEffectorPose,
        const arma::Row<double>& redundantJointsActuation) const {
      assert(redundantJointsActuation.n_elem == numberOfRedundantJoints_);
      assert(arma::all(redundantJointsActuation >= 0) && arma::all(redundantJointsActuation <= 1));

      arma::Cube<double> model = platformLevels_.at(0).getModel(endEffectorPose, {});
      for (arma::uword n = 1; n < platformLevels_.size(); ++n) {
        arma::join_slices(model, platformLevels_.at(n).getModel(redundantJointsActuation.subvec(6 * n - 6, 6 * n - 1), {}));
      }

      return model;
    }
DecisionStump<MatType>::DecisionStump(const MatType& data,
                                      const arma::Row<size_t>& labels,
                                      const size_t classes,
                                      size_t inpBucketSize)
{
  numClass = classes;
  bucketSize = inpBucketSize;

  // If classLabels are not all identical, proceed with training.
  int bestAtt = 0;
  double entropy;
  const double rootEntropy = CalculateEntropy<size_t>(
      labels.subvec(0, labels.n_elem - 1));

  double gain, bestGain = 0.0;
  for (int i = 0; i < data.n_rows; i++)
  {
    // Go through each attribute of the data.
    if (IsDistinct<double>(data.row(i)))
    {
      // For each attribute with non-identical values, treat it as a potential
      // splitting attribute and calculate entropy if split on it.
      entropy = SetupSplitAttribute(data.row(i), labels);

      // Rcpp::Rcout << "Entropy for attribute " << i << " is " << entropy << ".\n";
      gain = rootEntropy - entropy;
      // Find the attribute with the best entropy so that the gain is
      // maximized.

      // if (entropy < bestEntropy)
      // Instead of the above rule, we are maximizing gain, which was
      // what is returned from SetupSplitAttribute.
      if (gain < bestGain)
      {
        bestAtt = i;
        bestGain = gain;
      }
    }
  }
  splitAttribute = bestAtt;

  // Once the splitting column/attribute has been decided, train on it.
  TrainOnAtt<double>(data.row(splitAttribute), labels);
}
    double MultiLevelStewartPlatform::getEndEffectorPoseErrorImplementation(
        const arma::Col<double>& endEffectorPose,
        const arma::Row<double>& redundantJointsActuation) const {
      assert(redundantJointsActuation.n_elem == numberOfRedundantJoints_);
      assert(arma::all(redundantJointsActuation >= 0) && arma::all(redundantJointsActuation <= 1));

      double endEffectorPoseError = platformLevels_.at(0).getEndEffectorPoseError(endEffectorPose, {});
      for (arma::uword n = 1; n < platformLevels_.size(); ++n) {
        const double partialEndEffectorPoseError = platformLevels_.at(n).getEndEffectorPoseError(redundantJointsActuation.subvec(6 * n - 6, 6 * n - 1), {});

        assert(partialEndEffectorPoseError >= 0);

        endEffectorPoseError += partialEndEffectorPoseError;
      }

      return endEffectorPoseError;
    }
    arma::Row<double> MultiLevelStewartPlatform::getActuationImplementation(
        const arma::Col<double>& endEffectorPose,
        const arma::Row<double>& redundantJointsActuation) const {
      assert(redundantJointsActuation.n_elem == numberOfRedundantJoints_);
      assert(arma::all(redundantJointsActuation >= 0) && arma::all(redundantJointsActuation <= 1));

      arma::Row<double> actuation = platformLevels_.at(0).getActuation(endEffectorPose, {});
      for (arma::uword n = 1; n < platformLevels_.size(); ++n) {
        const arma::Row<double>& partialActuation = platformLevels_.at(n).getActuation(redundantJointsActuation.subvec(6 * n - 6, 6 * n - 1), {});

        assert(partialActuation.n_elem == numberOfActiveJoints_);
        assert(arma::all(partialActuation >= platformLevels_.at(n).minimalActiveJointsActuation_) && arma::all(partialActuation <= platformLevels_.at(n).maximalActiveJointsActuation_));

        actuation = arma::join_rows(actuation, partialActuation);
      }

      return actuation;
    }