text:
#include <iostream>
#include <fstream>

#include <Eigen/Core>
#include <Eigen/Geometry>
#include "ceres/ceres.h"
#include "glog/logging.h"

using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solve;
using ceres::Solver;

const double DT = 1.0 / 18;
// const Eigen::Vector3d GRAVITY{0, 0, 0};
const Eigen::Vector3d GRAVITY{0, 0, -9.8};

struct State {
  Eigen::Vector3d pos = Eigen::Vector3d::Random(); // position
  Eigen::Vector3d vel = Eigen::Vector3d::Random(); // velocity
  Eigen::Quaterniond q = Eigen::Quaterniond::UnitRandom(); // pose Qwr

  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

struct Measurement{
  Eigen::Matrix3d Rwr;
  Eigen::Quaterniond qwr;
  Eigen::Vector3d twr;
  Eigen::Vector3d acc;
  Eigen::Vector3d omega;

  Measurement(Eigen::Matrix3d Rwr,
              Eigen::Quaterniond qwr,
              Eigen::Vector3d twr,
              Eigen::Vector3d acc,
              Eigen::Vector3d omega)
    : Rwr(Rwr), qwr(qwr), twr(twr), acc(acc), omega(omega) {}

  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

struct PositionError {
	PositionError(const Eigen::Vector3d& pos_measured)
		: pos_measured_(pos_measured) {}

	template <typename T>
	bool operator()(const T* const pos_hat_ptr,
									T* residuals_ptr) const {
		Eigen::Matrix<T, 3, 1> pos_hat(pos_hat_ptr);
		Eigen::Matrix<T, 3, 1> pos_delta = pos_hat - pos_measured_.template cast<T>();

    for (int i = 0; i < 3; i++) {
      residuals_ptr[i] = pos_delta[i];
    }
		return true;
	}

	static CostFunction* Create(const Eigen::Vector3d& pos_measured) {
		return new AutoDiffCostFunction<PositionError, 3, 3>(
			new PositionError(pos_measured)
		);
	}

EIGEN_MAKE_ALIGNED_OPERATOR_NEW

private:
	const Eigen::Vector3d pos_measured_;
};

struct PoseError {
  PoseError(const Eigen::Vector3d& pos_measured,
            const Eigen::Quaterniond& q_measured)
    : pos_measured_(pos_measured), q_measured_(q_measured) {}

  template <typename T>
  bool operator()(const T* const pos_hat_ptr,
                  const T* const q_hat_ptr,
                  T* residuals_ptr) const {
    Eigen::Matrix<T, 6, 1> residuals;

    Eigen::Matrix<T, 3, 1> pos_hat(pos_hat_ptr);
    Eigen::Matrix<T, 3, 1> pos_delta;
    residuals.template block<3, 1>(0, 0) = pos_hat - pos_measured_.template cast<T>();

    Eigen::Quaternion<T> q_hat(q_hat_ptr);
    Eigen::Quaternion<T> q_delta = q_measured_.conjugate().template cast<T>() * q_hat;
    residuals.template block<3, 1>(3, 0) = q_delta.vec();
    for (int i = 0; i < 6; i++) {
      residuals_ptr[i] = residuals[i];
    }
    return true;
  }

  static CostFunction* Create(const Eigen::Vector3d& pos_measured,
                              const Eigen::Quaterniond& q_measured) {
    return new AutoDiffCostFunction<PoseError, 6, 3, 4>(
      new PoseError(pos_measured, q_measured));
  }

EIGEN_MAKE_ALIGNED_OPERATOR_NEW

private:
  const Eigen::Vector3d pos_measured_;
  const Eigen::Quaterniond q_measured_;
};

struct PredictionError{
  PredictionError(const Eigen::Vector3d& acc_measured,
                  const Eigen::Vector3d& omega_measured)
    : acc_measured_(acc_measured), omega_measured_(omega_measured) {}

  template <typename T>
  bool operator()(const T* const pos_b_ptr,
                  const T* const vel_b_ptr,
                  const T* const q_b_ptr,
                  const T* const pos_e_ptr,
                  const T* const vel_e_ptr,
                  const T* const q_e_ptr,
                  const T* const bias_ptr,
                  T* residuals_ptr) const {
    Eigen::Matrix<T, 9, 1> residuals;

    // quat error
    const Eigen::Quaternion<T> q_b(q_b_ptr);
    const Eigen::Quaternion<T> q_e(q_e_ptr);

    Eigen::Quaternion<T> q_new;
    Eigen::Quaternion<T> q_add;

    // // https://gamedev.stackexchange.com/questions/108920/applying-angular-velocity-to-quaternion
    // Eigen::Quaternion<T> q_omega;
    // // q_omega.w() = 0;
    // q_omega.vec() = omega_measured_.template cast<T>() * DT * 0.5;
    // q_add = q_omega * q_b;
    // q_new.w() = q_b.w() + q_add.w();
    // q_new.vec() = q_b.vec() + q_add.vec();

    Eigen::Vector3d rotated = omega_measured_ * DT;
    double angle = rotated.norm();
    Eigen::Vector3d axis = rotated.normalized();
    q_add = Eigen::AngleAxisd(angle, axis).template cast<T>();
    q_new = q_b * q_add;

    Eigen::Quaternion<T> q_delta = q_e.conjugate() * q_new;
    residuals.template block<3, 1>(6, 0) = q_delta.vec();

    // vel error
    const Eigen::Matrix<T, 3, 1> bias(bias_ptr);
    const Eigen::Matrix<T, 3, 1> vel_b(vel_b_ptr);
    const Eigen::Matrix<T, 3, 1> vel_e(vel_e_ptr);
    residuals.template block<3, 1>(3, 0) = vel_b + (q_b * (acc_measured_.template cast<T>() - bias) - GRAVITY) * DT - vel_e;

    // pos error
    const Eigen::Matrix<T, 3, 1> pos_b(pos_b_ptr);
    const Eigen::Matrix<T, 3, 1> pos_e(pos_e_ptr);
    residuals.template block<3, 1>(0, 0) = pos_b + vel_b * DT - pos_e;

    for (int i = 0; i < 9; i++) {
      residuals_ptr[i] = residuals[i];
    }
    return true;
  }

  static CostFunction* Create(const Eigen::Vector3d& acc_measured,
                              const Eigen::Vector3d& omega_measured) {
    return new AutoDiffCostFunction<PredictionError, 9, 3, 3, 4, 3, 3, 4, 3>(
      new PredictionError(acc_measured, omega_measured));
  }

EIGEN_MAKE_ALIGNED_OPERATOR_NEW

private:
  const Eigen::Vector3d acc_measured_;
  const Eigen::Vector3d omega_measured_;
};

struct OriPredictionError{
  OriPredictionError(const Eigen::Vector3d& acc_measured,
                  const Eigen::Vector3d& omega_measured)
    : acc_measured_(acc_measured), omega_measured_(omega_measured) {}

  template <typename T>
  bool operator()(const T* const q_b_ptr,
                  const T* const q_e_ptr,
                  T* residuals_ptr) const {
    Eigen::Matrix<T, 3, 1> residuals;

    // quat error
    const Eigen::Quaternion<T> q_b(q_b_ptr);
    const Eigen::Quaternion<T> q_e(q_e_ptr);

    Eigen::Quaternion<T> q_new;
    Eigen::Quaternion<T> q_add;

    // // https://gamedev.stackexchange.com/questions/108920/applying-angular-velocity-to-quaternion
    // Eigen::Quaternion<T> q_omega;
    // // q_omega.w() = 0;
    // q_omega.vec() = omega_measured_.template cast<T>() * DT * 0.5;
    // q_add = q_omega * q_b;
    // q_new.w() = q_b.w() + q_add.w();
    // q_new.vec() = q_b.vec() + q_add.vec();

    Eigen::Vector3d rotated = omega_measured_ * DT;
    double angle = rotated.norm();
    Eigen::Vector3d axis = rotated.normalized();
    q_add = Eigen::AngleAxisd(angle, axis).template cast<T>();
    q_new = q_b * q_add;

    Eigen::Quaternion<T> q_delta = q_e.conjugate() * q_new;
    residuals.template block<3, 1>(0, 0) = T(2.0) * q_delta.vec();

    for (int i = 0; i < 3; i++) {
      residuals_ptr[i] = residuals[i];
    }
    return true;
  }

  static CostFunction* Create(const Eigen::Vector3d& acc_measured,
                              const Eigen::Vector3d& omega_measured) {
    return new AutoDiffCostFunction<OriPredictionError, 3, 4, 4>(
      new OriPredictionError(acc_measured, omega_measured));
  }

EIGEN_MAKE_ALIGNED_OPERATOR_NEW

private:
  const Eigen::Vector3d acc_measured_;
  const Eigen::Vector3d omega_measured_;
};

std::vector<Measurement, Eigen::aligned_allocator<Measurement>> readSensorData(std::string path) {
  std::vector<Measurement, Eigen::aligned_allocator<Measurement>> ret;

  std::ifstream csvFile;
  csvFile.open(path);

  std::string line;
  while(std::getline(csvFile, line)) {
    std::vector<double> row;
    std::cout << "line:" << line << std::endl;
    std::istringstream s(line);
    std::string field;
    while (std::getline(s, field,',')) {
      // std::cout << "field: " << field << std::endl;
      row.push_back(std::stod(field));
    }
    Eigen::Matrix3d Rwr;
    Eigen::Quaterniond qwr;
    Eigen::Vector3d twr;
    Eigen::Vector3d acc;
    Eigen::Vector3d omega;
    Rwr << row[0], row[1], row[2],
          row[4], row[5], row[6],
          row[8], row[9], row[10];
    qwr = Rwr;
    twr << row[3], row[7], row[11];
    acc << row[16], row[17], row[18];
    omega << row[19], row[20], row[21];
    std::cout << "Rwr: " << Rwr << std::endl;
    std::cout << "qwr: " << qwr.w() << " " << qwr.vec() << std::endl;
    std::cout << "twr: " << twr << std::endl;
    std::cout << "acc: " << acc << std::endl;
    std::cout << "omega: " << omega << std::endl;

    ret.push_back(Measurement(Rwr, qwr, twr, acc, omega));
  }

  return ret;
}

void output_pose(const Eigen::Vector3d& pos,
								 const Eigen::Quaterniond& q) {
	Eigen::AngleAxisd ori(q);

	std::cout << "Location: " << pos << std::endl;
	std::cout << "Orientation: " << ori.angle() << " * " << std::endl << ori.axis() << std::endl;
}

void output_measurement(const Measurement& data) {
  std::cout << "\nData State: \n" << "R: \n" << data.Rwr << "\nt: \n" << data.twr \
            << "\nacc: \n" << data.acc << "\nomega: \n" << data.omega << std::endl;
}

void save_states(const std::string& filename,
                 std::vector<State, Eigen::aligned_allocator<State>>& states) {
  std::fstream outfile;
  outfile.open(filename.c_str(), std::istream::out);

  for (auto& state : states) {
    Eigen::Matrix3d rot = state.q.matrix();
    outfile << rot << "\n" << state.pos.transpose() << "\n" << state.vel.transpose() << "\n\n";
  }
}

double abs_pos_error(const std::vector<State, Eigen::aligned_allocator<State>>& states,
                     const std::vector<State, Eigen::aligned_allocator<State>>& gt_states) {
  double err = 0.0;
  std::cout << "abs_pos_err by step: ";
  for (int i = 0; i < states.size(); i++) {
    double step_err = (states[i].pos - gt_states[i].pos).norm();
    err += step_err;
    std::cout << step_err << " ";
  }
  std::cout << std::endl;
  return err;
}

int main(int argc, char** argv) {
  if(argc < 2) {
    std::cout << "missing arg for the csv file" << std::endl;
  }

  std::string path = argv[1];
  std::vector<Measurement, Eigen::aligned_allocator<Measurement>> data = readSensorData(path);

  if (false) {
    output_measurement(data[0]);
    output_measurement(data[1]);

    Eigen::Vector3d rotated = data[0].omega * DT;
    double angle = rotated.norm();
    Eigen::Vector3d axis = rotated.normalized();
    Eigen::Quaterniond q_add(Eigen::AngleAxisd(angle, axis));
    Eigen::Quaterniond q_new = data[0].qwr * q_add;
    Eigen::Matrix3d R_new = q_new.normalized().toRotationMatrix();

    std::cout << "R_new: \n" << R_new << std::endl;

    Eigen::Vector3d vel_add = data[0].qwr * data[0].acc * DT;
    std::cout << "vel_new: \n" << vel_add << std::endl;
    return 0;
  }

  int cnt = data.size();
  // int cnt = 3;

  // Eigen::Vector3d bias = Eigen::Vector3d::Random();
  Eigen::Vector3d bias;
  bias << 0, 0, 0;
  std::vector<State, Eigen::aligned_allocator<State>> states(cnt);
  std::vector<State, Eigen::aligned_allocator<State>> gt_states(cnt);
  std::cout << "states size: " << states.size() << std::endl;

  for (int i = 0; i < gt_states.size(); i++) {
    gt_states[i].pos = data[i].twr;
    gt_states[i].vel = Eigen::Vector3d::Zero();
    gt_states[i].q = data[i].qwr;
  }

  Problem problem;

  ceres::LossFunction* loss_function = nullptr;
  ceres::LocalParameterization* quaternion_local_parameterization =
      new ceres::EigenQuaternionParameterization;

  for (int i = 0; i < cnt; i++) {
    ceres::CostFunction* position_cost_function = PositionError::Create(data[i].twr);
    problem.AddResidualBlock(position_cost_function,
                             loss_function,
                             states[i].pos.data());
    // ceres::CostFunction* pos_cost_function = PoseError::Create(data[i].twr, data[i].qwr);
    // problem.AddResidualBlock(pos_cost_function,
    //                          loss_function,
    //                          states[i].pos.data(),
    //                          states[i].q.coeffs().data());
    // problem.SetParameterization(states[i].q.coeffs().data(),
    //                             quaternion_local_parameterization);
    if (i > 0) {
      ceres::CostFunction* pred_cost_function = PredictionError::Create(data[i].acc, data[i].omega);
      problem.AddResidualBlock(pred_cost_function,
                               loss_function,
                               states[i - 1].pos.data(),
                               states[i - 1].vel.data(),
                               states[i - 1].q.coeffs().data(),
                               states[i].pos.data(),
                               states[i].vel.data(),
                               states[i].q.coeffs().data(),
                               bias.data());
      // ceres::CostFunction* pred_cost_function = OriPredictionError::Create(data[i].acc, data[i].omega);
      // problem.AddResidualBlock(pred_cost_function,
      //                          loss_function,
      //                          states[i - 1].q.coeffs().data(),
      //                          states[i].q.coeffs().data());
      problem.SetParameterization(states[i - 1].q.coeffs().data(),
                                  quaternion_local_parameterization);
      problem.SetParameterization(states[i].q.coeffs().data(),
                                  quaternion_local_parameterization);
    }
  }

  // set bias to constant
  // problem.SetParameterBlockConstant(bias.data());
  // Eigen::Quaterniond q_noise(Eigen::AngleAxisd(0.1, Eigen::Vector3d::Random().normalized()));
  // states[0].q = data[0].qwr * q_noise;
  // states[0].q = data[0].qwr;
  // problem.SetParameterBlockConstant(states[0].q.coeffs().data());

  ceres::Solver::Options options;
	options.max_num_iterations = 200;
  options.linear_solver_type = ceres::DENSE_SCHUR;
  // options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY;
  options.minimizer_progress_to_stdout = true;

  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);
  std::cout << summary.FullReport() << "\n";

  if (false) {
    output_measurement(data[0]);
    output_measurement(data[1]);
    output_measurement(data[2]);

    for (int i = 0; i < states.size(); i++) {
      std::cout << "Estimated State:" << i << " \n" << "R: \n" << states[i].q.matrix()
                                              << "\nt: \n" << states[i].pos
                                              << "\nvel: \n" << states[i].vel << std::endl;
    }
  }

  std::string est_filename = "./results/est_no_ori_measure_nofixfirst_states.txt";
  // std::string est_filename = "./results/est_position_predic_ori_states.txt";
  save_states(est_filename, states);
  std::string gt_filename = "./results/gt_states.txt";
  save_states(gt_filename, gt_states);

  double err = abs_pos_error(states, gt_states);
  std::cout << "absolute position error: " << err << std::endl;
  return 0;
}

max_stars_repo_name: yimuw/expriment

max_issues_repo_name: yimuw/expriment

max_forks_repo_name: yimuw/expriment


text:
#include "familytree.h"

#include <fstream>
#include <boost/graph/graphviz.hpp>

void FamilyTree::loadGEDCOM(const char* iFileName)
{
    lube::filemodule gm("ged");
    lube::file& vf = gm.create();
    var ged = vf.read(iFileName);

    std::cout << "Individuals: " << ged["Individual"].size() << std::endl;
    std::cout << "Families: " << ged["Family"].size() << std::endl;

    // Add to graph
    for (int i=0; i<ged["Individual"].size(); i++)
    {
        // Rely on vertex, returned by add_vertex(), just being an
        // integer that increments with each call.
        vertex v = addIndividual();
        if ((int)v != i)
            throw std::runtime_error(
                "FamilyTree::loadGEDCOM: vertex out of order"
            );
        var& ind = getIndividual(v);
        ind = ged["Individual"][i];
    }
    for (int i=0; i<ged["Family"].size(); i++)
    {
        var f = ged["Family"][i];
        var h = f.at("HUSB");
        var w = f.at("WIFE");
        h.dereference();
        w.dereference();
        for (int c=0; c<f["CHIL"].size(); c++)
        {
            var k = f["CHIL"][c];
            if (h)
                addRelationship(h.cast<int>(), k.cast<int>());
            if (w)
                addRelationship(w.cast<int>(), k.cast<int>());
        }
    }
}

FamilyTree::vertex FamilyTree::addIndividual()
{
    vertex v = add_vertex(mGraph);
    return v;
}

FamilyTree::edge FamilyTree::addRelationship(vertex iID1, vertex iID2)
{
    std::pair<edge, bool> ret;
    ret = add_edge(iID1, iID2, mGraph);
    return ret.first;
}

template <class T>
class LabelWriter
{
public:
    LabelWriter(T& iGraph) : mGraph(iGraph) {}
    template <class VertexOrEdge>
    void operator()(std::ostream& iOut, const VertexOrEdge& iV) const
    {
        var v = mGraph[iV];
        if (v.at("NAME"))
            // Should replace with escaped quote rather than nothing
            iOut << "[label=\"" << v.at("NAME").replace("\"", "").str() << "\"]";
    }
private:
    T& mGraph;
};

void FamilyTree::saveGraphViz(const char* iFileName)
{
    std::ofstream ofs(iFileName, std::ofstream::out);
    LabelWriter<graph> lw(mGraph);
    write_graphviz(ofs, mGraph, lw);
}

ext: cpp

max_stars_repo_name: pgarner/chums

max_issues_repo_name: pgarner/chums

max_forks_repo_name: pgarner/chums


text:
#include <string>
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <array>
#include <vector>
#include <sstream>
#include <algorithm>
/*
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

using namespace boost::algorithm;
*/
int part1(std::unordered_map<std::string, std::string> map);
int part2(std::unordered_map<std::string, std::string> map, std::string str,
 std::string last);
std::vector<std::string> splitStringToArray(std::string str, char token);

int main() {
    std::ifstream file("./day6.txt");
    std::string str;

    std::unordered_map<std::string, std::string> map;
    std::vector<std::string> orbits;

    while(std::getline(file, str)) {
        orbits = splitStringToArray(str, ')');
        map[orbits[1]] = orbits[0];
    }

    std::cout << "part1 = " << part1(map) << std::endl;
    std::cout << "part2 = " << part2(map, map.find("YOU")->second, "YOU")-1 << std::endl;

    return 0;
}

std::vector<std::string> splitStringToArray(std::string str, char token) {
    std::replace(str.begin(), str.end(), token, ' ');
    std::vector<std::string> v;
    std::stringstream ss(str);
    std::string tmp;
    while(ss >> tmp) {
        v.push_back(tmp);
    }
    return v;
}

int part1(std::unordered_map<std::string, std::string> map) {
    int count = 0;
    std::string tmp;

    for (auto el : map) {
        tmp = el.first;
        while(map.find(tmp) != map.end()) {
            count++;
            tmp = map[tmp];
        }
    }
    return count;
}

int part2(std::unordered_map<std::string, std::string> map, std::string str,
std::string last) {
    int count = map.size();
    if(str == "SAN") {
        return 0;
    }
    if(str == "COM") {
        return map.size();
    }

    auto it = map.find(str);
    if(it != map.end() && it->second != last) {
        count = std::min(count, 1 + part2(map, it->second, str));
    }

    it = map.begin();
    while(1) {
        it = std::find_if(std::next(it), map.end(), [&](std::pair<std::string, std::string> p)
            {return (p.second == str);});
        if(it == map.end()) break;
        count = std::min(count, 1 + part2(map, it->first, str));
    }

    return count;
}


text:
#include "MaterialProperties.h"
#include <cc_CommonUtilities.h>
#include <string>
#include <stdlib.h>
#include <locale>
#include <iostream>
#include <ostream>
#include <sstream>

#include <boost\filesystem.hpp>
#include <boost\property_tree\ptree.hpp>
#include <boost\property_tree\json_parser.hpp>
#include <boost\foreach.hpp>
#include <boost\algorithm\string.hpp>
#include <sstream>

#include <fstream>
#include <iterator>
#include <boost/regex.hpp>
#include <stdlib.h>
#include "cc_LoggerBoost.h"

namespace isis
{

	const double PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR = 1.0 / 1000000.0;
	const double CONVERSION_FACTOR_ONE = 1.0;
	const double M_CUBED_TO_MM_CUBED = 1000.0 * 1000.0 * 1000.0;
	const double M_CUBED_TO_MM_CUBED_RECIPROCAL = 1.0 / M_CUBED_TO_MM_CUBED;
	const double M_TO_MM_RECIPROCAL = 1.0  / 1000.0;
/*
	std::string ConvertToUpperCase(const std::string &in_String)
	{
		std::string temp_string(in_String);
		std::locale loc;
		for (std::string::iterator p = temp_string.begin(); temp_string.end() != p; ++p)    *p = toupper(*p, loc);
		return temp_string;
	}

*/

void stream_AnalysisMaterialProperties( const AnalysisMaterialProperties &in_CADAnalyses, std::ostream &out_Stream )
{
	out_Stream << std::endl << "Material Name: " << in_CADAnalyses.materialName;
	out_Stream << std::endl << "Material Type: " << isis::MaterialType_string(in_CADAnalyses.materialType);

	out_Stream << std::endl << "   ModulusOfElasticity";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.modulusOfElasticityDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.modulusOfElasticity;

	out_Stream << std::endl << "   PoissonsRatio";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.poissonsRatioDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.poissonsRatio;

	out_Stream << std::endl << "   TensileYieldStrength";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.tensileYieldStrengthDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.tensileYieldStrength;

	out_Stream << std::endl << "   TensileUltimateStrength";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.tensileUltimateStrengthDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.tensileUltimateStrength;

	out_Stream << std::endl << "   ShearStrength";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.shearStrengthDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.shearStrength;

	out_Stream << std::endl << "   BearingYieldStrength";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.bearingYieldStrengthDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.bearingYieldStrength;

	out_Stream << std::endl << "   BearingUltimateStrength";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.bearingUltimateStrengthDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.bearingUltimateStrength;

	out_Stream << std::endl << "   FatigueStrength";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.fatigueStrengthDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.fatigueStrength;

	out_Stream << std::endl << "   fatigueNumberOfCycles";
	out_Stream << std::endl << "      Defined: " << in_CADAnalyses.fatigueNumberOfCyclesDefined;
	out_Stream << std::endl << "      Value: "   << in_CADAnalyses.fatigueNumberOfCycles;

};

void stream_AnalysisMaterialProperties_Allowables( const AnalysisMaterialProperties_Allowables	&in_AnalysisMaterialProperties, std::ostream &out_Stream )
{
	out_Stream << std::endl << "Material Name: " << in_AnalysisMaterialProperties.materialName;
	out_Stream << std::endl << "Material Type: " << isis::MaterialType_string(in_AnalysisMaterialProperties.materialType);

	out_Stream << std::endl << "   TensileStrength";
	out_Stream << std::endl << "      Value: "   << in_AnalysisMaterialProperties.tensileStrength;

	out_Stream << std::endl << "   ShearStrength";
	out_Stream << std::endl << "      Value: "   << in_AnalysisMaterialProperties.shearStrength;

	out_Stream << std::endl << "   BearingStrength";
	out_Stream << std::endl << "      Value: "   << in_AnalysisMaterialProperties.bearingStrength;

	out_Stream << std::endl << "   NumberOfCycles";
	out_Stream << std::endl << "      Value: "   << in_AnalysisMaterialProperties.numberOfCycles;

};

///////////////////////////////////////////////////////////////////////////////////////////////
bool 	StressValueComputed(	bool	in_Value_1_Defined,
								double	in_Value_1,
								bool	in_Value_2_Defined,
								double	in_Value_2,
								double	in_ReferenceValue,
								double  &out_ComputedValue )
{

		if ( in_Value_1_Defined && in_Value_2_Defined  )
		{
			out_ComputedValue =  (in_ReferenceValue / in_Value_1 ) * in_Value_2;
			//std::cout << std::endl << "BEGIN StressValueComputed";
			//std::cout << std::endl << "  in_Value_1_Defined: "	<< in_Value_1_Defined;
			//std::cout << std::endl << "  in_Value_1: "			<< in_Value_1;
			//std::cout << std::endl << "  in_Value_2_Defined: "	<< in_Value_1_Defined;
			//std::cout << std::endl << "  in_Value_2: "			<< in_Value_2;
			//std::cout << std::endl << "  in_ReferenceValue:  "	<< in_ReferenceValue;
			//std::cout << std::endl << "  out_ComputedValue:  "	<< out_ComputedValue;
			//std::cout << std::endl << "END StressValueComputed";
			return true;
		}
		else
		{
			return false;
		}
}
/////////////////////////////////////////////////////////////////////////////////////////////////

// General Rules:
//	1)	If in_NumberOfCycles == 0 assume infinite number of cycles
//	2)	Consider 500,000,000 (5M) cycles to be infinite cycles
//	3)  Consider less than 1,000 cycles to be equivalent to 1 cycle for determining the allowable stress levels.
//	3)	Aluminum must have in_AnalysisMaterialProperties.fatigueStrength and fatigueNumberOfCycles set.
//	4)	For Steel, if in_AnalysisMaterialProperties.fatigueStrength is not set, assume that it is
//		50% of in_AnalysisMaterialProperties.tensileUltimateStrength
//	5)	TBD For cycle values between 1,000 and 500,000,000, we need a graph of X-Number Cycles, and Y-Stress.  These
//		are usually log base 10 graphs.
//
//	Material  		Fatigue		Number 		Tensile							Bearing							Shear
//					Given		Cycles		Strength						Strength						Strength
//	-----------		--------	-------		--------------					-----------						---------------
//	Steel/Aluminum	Yes			N < 1000	tensileYieldStrength			bearingYieldStrength			shearStrength
//	Stee/Aluminum	Yes			1000 < N 	fatigueStrength					SF * bearingUltimateStrength	SF * shearStrength
//	Steel			No			1000 < N 	.5 * tensileUltimateStrength	SF  * bearingYieldStrength		SF  * shearStrength
//	Aluminum		No			(Not Allowed, throw exception)
//
// SF - Scale Factor = fatigueStrength / tensileUltimateStrength;

void ComputeAllowableStressLevels(	int										in_NumberOfCycles,
									const AnalysisMaterialProperties		&in_AnalysisMaterialProperties,
								    AnalysisMaterialProperties_Allowables	&out_AnalysisMaterialProperties )
																				throw (isis::application_exception)
{
	///////////////////////////////////////////////
	// zero out values
	///////////////////////////////////////////////
	out_AnalysisMaterialProperties.materialName = "";
	out_AnalysisMaterialProperties.tensileStrength	= 0;
	out_AnalysisMaterialProperties.bearingStrength	= 0;
	out_AnalysisMaterialProperties.shearStrength	= 0;
	out_AnalysisMaterialProperties.numberOfCycles	= 0;

	///////////////////////////////////////////////
	// Only Aluminum and Steel Currently Supported
	///////////////////////////////////////////////
	if ( ( in_AnalysisMaterialProperties.materialType != MATERIAL_ALUMINUM ) &&
		 ( in_AnalysisMaterialProperties.materialType != MATERIAL_STEEL ) )

	{
		// zzz fix this to use the common functions
		std::string tempMaterialType = "Unknown";
		if (in_AnalysisMaterialProperties.materialType == MATERIAL_CERAMIC )tempMaterialType = "Ceramic";
		if (in_AnalysisMaterialProperties.materialType == MATERIAL_PLASTIC )tempMaterialType = "Plastic";

		std::string TempError = "Function ComputeAllowableStressLevels(...) for material " + in_AnalysisMaterialProperties.materialName +
		" was passed: " + tempMaterialType +
		".  Currently only Steel and Aluminum are supported. Plastic and Ceramic will be supported in future releases.";
		throw isis::application_exception(TempError.c_str());
	}

	///////////////////////////////////////////////////////
	// Fatigue strength must be given defined for Aluminum
	///////////////////////////////////////////////////////
	if ( ( in_AnalysisMaterialProperties.materialType == MATERIAL_ALUMINUM ) &&
		 ( !in_AnalysisMaterialProperties.fatigueStrengthDefined ) )
	{
		std::string TempError = "Function ComputeAllowableStressLevels(...) for material " + in_AnalysisMaterialProperties.materialName +
		" does not have a fatigue strength defined.  Aluminum must have fatigue strength defined.";
		throw isis::application_exception(TempError.c_str());
	}

	////////////////////////////////////////
	// Tensile yield strength must be given
	////////////////////////////////////////
	if ( !in_AnalysisMaterialProperties.tensileYieldStrengthDefined )
	{
		std::string TempError = "Function ComputeAllowableStressLevels(...) for material " + in_AnalysisMaterialProperties.materialName +
		" does not have a tensile yield strength defined.  All material must have tensile yield strength defined.";
		throw isis::application_exception(TempError.c_str());
	}

	////////////////////////////////////////
	// Tensile Ultimate strength must be given
	////////////////////////////////////////
	if ( !in_AnalysisMaterialProperties.tensileUltimateStrengthDefined )
	{
		std::string TempError = "Function ComputeAllowableStressLevels(...) for material " + in_AnalysisMaterialProperties.materialName +
		" does not have a tensile ultimate strength defined.  All material must have tensile ultimate strength defined.";
		throw isis::application_exception(TempError.c_str());
	}

	//////////////////////////////////////////////
	// Shear Strength must be given for Aluminum
	/////////////////////////////////////////////
	if ( !in_AnalysisMaterialProperties.shearStrengthDefined &&  in_AnalysisMaterialProperties.materialType == MATERIAL_ALUMINUM  )
	{
		std::string TempError = "Function ComputeAllowableStressLevels(...) for material " + in_AnalysisMaterialProperties.materialName +
		" does not have a shear strength defined.  Aluminum must have shear strength defined.";
		throw isis::application_exception(TempError.c_str());
	}

	////////////////////////////////////////
	// Set Material Name and Type
	////////////////////////////////////////
	out_AnalysisMaterialProperties.materialName = in_AnalysisMaterialProperties.materialName;
	out_AnalysisMaterialProperties.materialType = in_AnalysisMaterialProperties.materialType;

	////////////////////////////////////////
	// Set Number of cycles
	////////////////////////////////////////
	out_AnalysisMaterialProperties.numberOfCycles = in_NumberOfCycles;

	////////////////////////////////////////
	// Compute tempShearStrength
	////////////////////////////////////////
	double tempShearStrength;
	if ( in_AnalysisMaterialProperties.shearStrengthDefined )
	{
		tempShearStrength = in_AnalysisMaterialProperties.shearStrength;
	}
	else
	{
		// Case for steel when shear strength is not defined, use rule of thumb
		tempShearStrength = .58 * in_AnalysisMaterialProperties.tensileYieldStrength;
	}

	////////////////////////////////////////
	// No Fatigue Case
	////////////////////////////////////////
	if ( ( in_NumberOfCycles != 0 ) && ( in_NumberOfCycles < 1000 ) )
	{
		out_AnalysisMaterialProperties.tensileStrength = in_AnalysisMaterialProperties.tensileYieldStrength;
		out_AnalysisMaterialProperties.shearStrength   = tempShearStrength;

		if (in_AnalysisMaterialProperties.bearingYieldStrengthDefined )
			out_AnalysisMaterialProperties.bearingStrength = in_AnalysisMaterialProperties.bearingYieldStrength;
		else
			out_AnalysisMaterialProperties.bearingStrength = in_AnalysisMaterialProperties.tensileYieldStrength;

	}
	else
	{
		/////////////////////////////////////////
		// Fatigue Case - Steel and Aluminum
		////////////////////////////////////////

		// Note fatigue strength would be defined for aluminum as checked above, maybe not for steel.
		double tempFatigueStrength;

		if ( in_AnalysisMaterialProperties.fatigueStrengthDefined )
			tempFatigueStrength = in_AnalysisMaterialProperties.fatigueStrength;
		else
			tempFatigueStrength = .5 * in_AnalysisMaterialProperties.tensileUltimateStrength;

		// Tensile
		out_AnalysisMaterialProperties.tensileStrength = tempFatigueStrength;

		// Bearing
		bool stressComputed = false;
		stressComputed = StressValueComputed(
							in_AnalysisMaterialProperties.tensileUltimateStrengthDefined,
							in_AnalysisMaterialProperties.tensileUltimateStrength,
							in_AnalysisMaterialProperties.bearingUltimateStrengthDefined,
							in_AnalysisMaterialProperties.bearingUltimateStrength,
							tempFatigueStrength,
							out_AnalysisMaterialProperties.bearingStrength );

		if ( !stressComputed )
		   stressComputed = StressValueComputed(
							in_AnalysisMaterialProperties.tensileYieldStrengthDefined,
							in_AnalysisMaterialProperties.tensileYieldStrength,
							in_AnalysisMaterialProperties.bearingYieldStrengthDefined,
							in_AnalysisMaterialProperties.bearingYieldStrength,
							tempFatigueStrength,
							out_AnalysisMaterialProperties.bearingStrength );

		if ( !stressComputed )
			out_AnalysisMaterialProperties.bearingStrength = tempFatigueStrength;

		// Shear
		stressComputed = StressValueComputed(
							in_AnalysisMaterialProperties.tensileUltimateStrengthDefined,
							in_AnalysisMaterialProperties.tensileUltimateStrength,
							true,
							tempShearStrength,
							tempFatigueStrength,
							out_AnalysisMaterialProperties.shearStrength );

		if ( !stressComputed )
			stressComputed = StressValueComputed(
							in_AnalysisMaterialProperties.tensileYieldStrengthDefined,
							in_AnalysisMaterialProperties.tensileYieldStrength,
							true,
							tempShearStrength,
							tempFatigueStrength,
							out_AnalysisMaterialProperties.shearStrength );
		if ( !stressComputed )
			out_AnalysisMaterialProperties.shearStrength =  .5 * in_AnalysisMaterialProperties.shearStrength;

	}

	///////////////////////////////////////////////
	//	At this point, the strength properties
	//	should be set.  It would be a programming
	//	error if this was not the case. Throw
	//	and exception if the strength properties
	//	are not set.
	///////////////////////////////////////////////

	if ( out_AnalysisMaterialProperties.tensileStrength	== 0 ||
		 out_AnalysisMaterialProperties.bearingStrength	== 0 ||
	     out_AnalysisMaterialProperties.shearStrength	== 0 )
	{
		std::ostringstream tensileStrength_str;
		std::ostringstream bearingStrength_str;
		std::ostringstream shearStrength_str;

		tensileStrength_str << out_AnalysisMaterialProperties.tensileStrength;
		bearingStrength_str << out_AnalysisMaterialProperties.bearingStrength;
		shearStrength_str   << out_AnalysisMaterialProperties.shearStrength;

		std::string TempError = "Function ComputeAllowableStressLevels(...) for material " + in_AnalysisMaterialProperties.materialName +
		" failed to compute the all of the strength material properties.  Computed properties are: Tensile Strength: " +
		tensileStrength_str.str() + ", Bearing Strength: " + bearingStrength_str.str() + ", Shear Strength: " + shearStrength_str.str() + ".";
		throw isis::application_exception(TempError.c_str());
	}
}

enum e_UnitType
{
	UNIT_MPA,
	UNIT_GPA,
	UNIT_NA
};

e_UnitType RetrieveUnitType(	const std::string &in_MaterialName,
								const std::string &in_Units )
																	throw (isis::application_exception)
{
	std::string units = isis::ConvertToUpperCase(in_Units);

	if ( strcmp(units.c_str(), "MPA") == 0  )
		return UNIT_MPA;
	else
		if ( strcmp(units.c_str(), "GPA")  == 0  )
			return UNIT_GPA;
		else
			if ( strcmp(units.c_str(), "N/A")  == 0  )
				return UNIT_NA;

	// No known type found.
	std::string TempError = "Function RetrieveUnitType(...) for material " + in_MaterialName +
		" was passed: " + in_Units +
		".  Acceptable types (case insensitive) are: MPA, GPA, and N/A.";
	throw isis::application_exception(TempError.c_str());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Description:
//		This function converts string representations of material properties
//		(i.e. in_MaterialMetrics_map[in_MaterialPropertyName] ) to doubles and stores
//		the results in out_Property.
//
//		Note -	All units stored in out_Property will be in MPa except for unit-less values
//				such as PoissonsRatio.
//
// Pre-Conditions:
//		if in_MaterialPropertyName[in_MaterialPropertyName] exists
//			in_MaterialPropertyName[in_MaterialPropertyName].units must be MPa, GPa, or N/A
//
// Post-Conditions:
//		if in_MaterialPropertyName[in_MaterialPropertyName] not exists
//			return (no action taken)
//		else
//			if in_MaterialPropertyName[in_MaterialPropertyName].units != MPa, GPa, or N/A
//				throw isis::application_exception
//			else
//				out_Property =  in_MaterialPropertyName[in_MaterialPropertyName].value
//				out_PropertyDefnied = true
//				if in_MaterialPropertyName[in_MaterialPropertyName].units == GPa
//					scale out_Property to be in MPA
//
void SetSingleAnalysisMaterialProperty(
					const std::string						&in_MaterialPropertyName,
					const std::map<std::string, MaterialMetrics> &in_MaterialMetrics_map,
					double									&out_Property,
					bool									&out_PropertyDefnied)
																throw (isis::application_exception)
{
	std::map<std::string, MaterialMetrics>::const_iterator itr = in_MaterialMetrics_map.find(in_MaterialPropertyName);

	if (itr != in_MaterialMetrics_map.end() )
	{
		// Note Poissoin's ration could be zero.  Since we will analyze metals, this should not be a problem.
		if ( itr->second.value == 0 )
		{
			out_PropertyDefnied = false;
		}
		else
		{
			out_Property = itr->second.value;
			out_PropertyDefnied = true;
			if( RetrieveUnitType(in_MaterialPropertyName,itr->second.units ) == UNIT_GPA ) out_Property *= 1000;
		}
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// This funcdtion will convert integer values.  The only integer value is FatigueNumberOfCycles
// which has no units.
void SetSingleAnalysisMaterialProperty(
					const std::string						&in_MaterialPropertyName,
					const std::map<std::string, MaterialMetrics> &in_MaterialMetrics_map,
					long									&out_Property,
					bool									&out_PropertyDefnied)
{
	std::map<std::string, MaterialMetrics>::const_iterator itr = in_MaterialMetrics_map.find(in_MaterialPropertyName);

	if (itr != in_MaterialMetrics_map.end() )
	{
		//out_Property = strtol(itr->second.value.c_str(), NULL,10 );
		out_Property = itr->second.value;

		out_PropertyDefnied = true;
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PopulateAnalysisMaterialStruct( const Material				 &in_Material,
									 AnalysisMaterialProperties  &out_AnalysisMaterialProperties_struct )
																		throw (isis::application_exception)
{
	out_AnalysisMaterialProperties_struct.materialType = in_Material.materialType;
	out_AnalysisMaterialProperties_struct.materialName = in_Material.materialName;

	//std::map<std::string, MaterialMetrics> i;

	SetSingleAnalysisMaterialProperty(	"ModulusOfElasticity",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.modulusOfElasticity,
										out_AnalysisMaterialProperties_struct.modulusOfElasticityDefined);

	SetSingleAnalysisMaterialProperty(	"PoissonsRatio",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.poissonsRatio,
										out_AnalysisMaterialProperties_struct.poissonsRatioDefined);

	SetSingleAnalysisMaterialProperty(	"TensileYieldStrength",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.tensileYieldStrength,
										out_AnalysisMaterialProperties_struct.tensileYieldStrengthDefined);

	SetSingleAnalysisMaterialProperty(	"TensileUltimateStrength",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.tensileUltimateStrength,
										out_AnalysisMaterialProperties_struct.tensileUltimateStrengthDefined);

	SetSingleAnalysisMaterialProperty(	"ShearStrength",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.shearStrength,
										out_AnalysisMaterialProperties_struct.shearStrengthDefined);

	SetSingleAnalysisMaterialProperty(	"BearingYieldStrength",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.bearingYieldStrength,
										out_AnalysisMaterialProperties_struct.bearingYieldStrengthDefined);

	SetSingleAnalysisMaterialProperty(	"BearingUltimateStrength",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.bearingUltimateStrength,
										out_AnalysisMaterialProperties_struct.bearingUltimateStrengthDefined);

	SetSingleAnalysisMaterialProperty(	"FatigueStrength",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.fatigueStrength,
										out_AnalysisMaterialProperties_struct.fatigueStrengthDefined);

	SetSingleAnalysisMaterialProperty(	"FatigueNumberOfCycles",
										in_Material.materialMetrics_map,
										out_AnalysisMaterialProperties_struct.fatigueNumberOfCycles,
										out_AnalysisMaterialProperties_struct.fatigueNumberOfCyclesDefined);

}

	////////////////////////////////////////////////////////////////////////////////////////////////////

	// in_UnitsConversionFactor should equal to 1.0 if no conversion.
	bool MaterialPropertyFound_RetrieveValue(
						const boost::property_tree::ptree::value_type	&in_Material_pt,
						const std::string	    &in_MaterialName,
						const std::string		&in_MaterialLibPropertyName, // e.g. strength_tensile_ultimate
						const					std::string in_MaterialLibRequiredUnit,  // e.g. Pa
						double					in_UnitsConversionFactor,  // e.g. PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR
						const std::string		&in_ConvertToUnit,
						double					&out_Value)
	{

		//std::clog << std::endl << "   " << in_Material_pt.first.data();

		bool materialFound = false;

		// Case insensitive check.
		if ( isis::ConvertToUpperCase(std::string(in_Material_pt.first.data())) == isis::ConvertToUpperCase(in_MaterialLibPropertyName) )
		{
			std::string unit;
			if ( in_MaterialLibRequiredUnit.size() == 0 )
			{
				unit = "None";
			}
			else
			{
				try
				{
					unit = in_Material_pt.second.get<std::string>("unit");
				}
				catch (...)  // Could not get the unit, but units are required.  Assume the property is not defined
				{

					isis_LOG(lg, isis_CONSOLE_FILE, isis_ERROR) << "Material units not defined for: " << isis_EOL <<
											  "   Material Name:     " << in_MaterialName << isis_EOL <<
											  "   Material Property: " << in_MaterialLibPropertyName << isis_EOL <<
											  "   Note:              Without units, this material property cannot be used.";
					return false;
				}
			}

			materialFound = true;
			if ( in_MaterialLibRequiredUnit.size() > 0 )
			{
				// Must verify units.
				if ( isis::ConvertToUpperCase(in_MaterialLibRequiredUnit) != isis::ConvertToUpperCase(unit) )
				{
					std::stringstream errorString;
								errorString <<
										"Material:          " <<  in_MaterialName << std::endl <<
										"Material Property: " <<  in_MaterialLibPropertyName << std::endl <<
										"Material Unit:	    " <<  unit  << std::endl <<
										"Required Unit:     " << in_MaterialLibRequiredUnit << std::endl <<
										"The units in the material library are incompatible with the required units.";
					throw isis::application_exception(errorString.str());
				}
			}

			std::string value_string =  in_Material_pt.second.get<std::string>("value");

			if ( isis::ConvertToUpperCase(value_string) == "NONE") return false;

			out_Value =  atof(value_string.c_str()) * in_UnitsConversionFactor;
			// Alternate conversion approach, should consider.
			// boost::optional<float> v = pt.get_optional<float>("a.path.to.float.value");
			// http://www.boost.org/doc/libs/1_43_0/doc/html/boost_propertytree/accessing.html

			if ( out_Value == 0 )
			{
				std::stringstream errorString;
				errorString <<
					"Material:          " <<  in_MaterialName << std::endl <<
					"Material Property: " <<  in_MaterialLibPropertyName << std::endl <<
					"Material Unit:	    " <<  unit  << std::endl <<
					"Value:             " << value_string << std::endl <<
					"A zero value is not allowed.";
				throw isis::application_exception(errorString.str());
			}

			isis_LOG(lg, isis_FILE, isis_INFO) <<
					"Material:                " <<  in_MaterialName << isis_EOL <<
					"Material Property:       " <<  in_MaterialLibPropertyName << isis_EOL <<
					"Material Unit:	          " <<  unit  << isis_EOL <<
					"Material Library Value:  " <<  value_string << isis_EOL <<
					"Unit Conversion Factor:  " <<  in_UnitsConversionFactor << isis_EOL <<
					"Convert to Unit:         " << in_ConvertToUnit << isis_EOL <<
					"Converted Value		  " << out_Value;
		}

		return materialFound;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////

	// Throw an exception if:
	// a) All the meterials in in_MaterialNames are not found in n_MaterialLibrary_PathAndFileName
	// b) Material properties are not in Pa or kg/m3.
	//
	//  Note - this function converts :
	//				Pa to MPa
	//				kg/m3 to kg/mm3
	//				W/(m*K) to W/(mm*K)
	//				and stores the converted values
	//         in out_Materials
	//

	void ReadMaterialsLibrary(  	const std::string &in_MaterialLibrary_PathAndFileName,
									const std::set<std::string> &in_MaterialNames,
									std::map<std::string, Material> &out_Materials )
													 throw (isis::application_exception)
	{
		using boost::property_tree::ptree;

		std::string currentMaterialName;
		std::string currentMaterialProperty;

		try
		{
			// Create a set of material names.  When a material is found remove it from the set.
			// If the set is not empty at the end of the program, throw and exception.
			std::set<std::string>  notFound_MaterialNames_set;
			for each ( std::string i in in_MaterialNames) notFound_MaterialNames_set.insert(i);

			boost::filesystem::path p(in_MaterialLibrary_PathAndFileName);
			if (boost::filesystem::exists(p))
			{
				if (boost::filesystem::is_regular_file(p))
				{
					ptree pt;
					boost::property_tree::read_json(p.make_preferred().string(), pt);
					BOOST_FOREACH(ptree::value_type& materialLib_pt, pt.get_child("Material library"))
					{
						//if (materialLib_pt.size() != 1 )
						//{
						//	std::stringstream errorString;
						//		errorString <<
						//				"Function:         ReadMaterialsLibrary" << endl <<
						//				"Material Library: "  << in_MaterialLibrary_PathAndFileName << endl <<
						//				"Number of \"Material library\" tags: " << pt.size() << endl <<
						//				"The material library must contain one and only one \"Material library\" tag.";
						//		throw isis::application_exception(errorString.str());
						//}

						//std::clog << std::endl << materialLib_pt.first.data();
						for each ( const std::string materialName in in_MaterialNames )
						{
							currentMaterialName = materialName;
							if ( isis::ConvertToUpperCase(std::string(materialLib_pt.first.data())) == isis::ConvertToUpperCase(materialName) )
							{
								notFound_MaterialNames_set.erase(materialName);
								out_Materials[materialName].materialName = materialName;
								out_Materials[materialName].analysisMaterialProperties.materialName = materialName;

								//std::cout << std::endl << materialLib_pt.first.data();
								BOOST_FOREACH(const ptree::value_type& material_pt, materialLib_pt.second)
								{
									double materialPropertyValue;

									if ( isis::ConvertToUpperCase(material_pt.first) ==  "MATERIAL_CATEGORY" )
									{
										std::string materialType =  material_pt.second.get<std::string>("value");
										out_Materials[materialName].materialType = MaterialType_enum(materialType);
										out_Materials[materialName].analysisMaterialProperties.materialType = MaterialType_enum(materialType);
									}

									currentMaterialProperty = "mechanical__modulus_elastic";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"Pa",
																	PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR,
																	"MPa",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.modulusOfElasticityDefined = true;
										out_Materials[materialName].analysisMaterialProperties.modulusOfElasticity = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.modulusOfElasticityUnit = CADUnitsPressure_enum("MPa");
									}

									currentMaterialProperty = "mechanical__ratio_poissons";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"",
																	1.0,
																	"",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.poissonsRatioDefined = true;
										out_Materials[materialName].analysisMaterialProperties.poissonsRatio = materialPropertyValue;
									}

									currentMaterialProperty = "mechanical__strength_tensile_yield";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"Pa",
																	PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR,
																	"MPa",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.tensileYieldStrengthDefined = true;
										out_Materials[materialName].analysisMaterialProperties.tensileYieldStrength = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.tensileYieldStrengthUnit = CADUnitsPressure_enum("MPa");
									}

									currentMaterialProperty = "mechanical__strength_tensile_ultimate";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"Pa",
																	PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR,
																	"MPa",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.tensileUltimateStrengthDefined = true;
										out_Materials[materialName].analysisMaterialProperties.tensileUltimateStrength = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.tensileUltimateStrengthUnit = CADUnitsPressure_enum("MPa");
									}

									currentMaterialProperty = "mechanical__strength_shear";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"Pa",
																	PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR,
																	"MPa",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.shearStrengthDefined = true;
										out_Materials[materialName].analysisMaterialProperties.shearStrength = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.shearStrengthUnit = CADUnitsPressure_enum("MPa");
									}

									currentMaterialProperty = "mechanical__strength_fatigue";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"Pa",
																	PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR,
																	"MPa",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.fatigueStrengthDefined = true;
										out_Materials[materialName].analysisMaterialProperties.fatigueStrength = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.fatigueStrengthUnit = CADUnitsPressure_enum("MPa");
									}

									currentMaterialProperty = "mechanical__strength_bearing_yield";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"Pa",
																	PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR,
																	"MPa",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.bearingYieldStrengthDefined = true;
										out_Materials[materialName].analysisMaterialProperties.bearingYieldStrength = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.bearingYieldStrengthUnit = CADUnitsPressure_enum("MPa");
									}

									currentMaterialProperty = "mechanical__strength_bearing_ultimate";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"Pa",
																	PASCAL_TO_MEGA_PASCAL_CONVERSION_FACTOR,
																	"MPa",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.bearingUltimateStrengthDefined = true;
										out_Materials[materialName].analysisMaterialProperties.bearingUltimateStrength = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.bearingUltimateStrengthUnit = CADUnitsPressure_enum("MPa");
									}

									currentMaterialProperty = "density";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	//"kg/m3",
																	"kg/m^3",
																	M_CUBED_TO_MM_CUBED_RECIPROCAL,
																	"kg/mm3",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.denstiyDefined = true;
										out_Materials[materialName].analysisMaterialProperties.density= materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.densityUnit = CADUnitsDensity_enum("kg/mm3");
									}

									currentMaterialProperty = "thermal__conductivity";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"W/(m*K)",
																	M_TO_MM_RECIPROCAL,
																	"w/mmk",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.thermalConductivityDefined = true;
										out_Materials[materialName].analysisMaterialProperties.thermalConductivity = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.thermalConductivityUnit = CADUnitsThermalConductivity_enum("w/mmk");
									}

									currentMaterialProperty = "thermal__capacity_specific_heat";

									if ( MaterialPropertyFound_RetrieveValue( material_pt,
																	materialName,
																	currentMaterialProperty,
																	"J/(kg-K)",
																	1.0,
																	"j/kgk",
																	materialPropertyValue ) )
									{
										out_Materials[materialName].analysisMaterialProperties.heatCapacityDefined = true;
										out_Materials[materialName].analysisMaterialProperties.heatCapacity = materialPropertyValue;
										out_Materials[materialName].analysisMaterialProperties.heatCapacityUnit = CADUnitsHeatCapacity_enum("j/kgk");
									}

								}  // END BOOST_FOREACH(const ptree::value_type& material_pt, materialLib_pt.second)
							}  // END if ( isis::ConvertToUpperCase(std::string(materialLib_pt.first.data())) == isis::ConvertToUpperCase(materialName) )
						}  // END for each ( const std::string i in in_MaterialNames )
					} // END BOOST_FOREACH(ptree::value_type& materialLib_pt, pt.get_child("Material library"))
				} // END if (boost::filesystem::is_regular_file(p))
			} // END if (boost::filesystem::exists(p))
			else
			{
				std::stringstream errorString;
				errorString << "Material library input file not found: " << in_MaterialLibrary_PathAndFileName;
				throw isis::application_exception(errorString.str());
			}

			if ( notFound_MaterialNames_set.size() != 0 )
			{
				std::stringstream errorString;
				errorString << "Material(s) not found in the material library: " << in_MaterialLibrary_PathAndFileName << std::endl <<
								"Material(s):" << std::endl;
				for each (std::string i in notFound_MaterialNames_set) errorString << i << std::endl;
				throw isis::application_exception(errorString.str());

			}

		}
		catch(const boost::property_tree::ptree_error &exc)
		{
			std::stringstream errorString;
			errorString << "Input file processing error: " << in_MaterialLibrary_PathAndFileName <<  std::endl <<
							"   Material Name:     " << currentMaterialName <<  std::endl <<
							"   Material Property: " << currentMaterialProperty <<  std::endl <<
							"   Error: " << exc.what();
			throw isis::application_exception(errorString.str());
		}

		catch(const isis::application_exception &exc)
		{
			std::stringstream errorString;
			errorString << "Input file processing error: " << in_MaterialLibrary_PathAndFileName <<  std::endl <<
							"   Material Name:     " << currentMaterialName <<  std::endl <<
							"   Material Property: " << currentMaterialProperty <<  std::endl <<
							"   Error: " << exc.what();
			throw isis::application_exception(errorString.str());
		}

	} // END ReadMaterialsLibrary

} // namespace isis

max_stars_repo_name: lefevre-fraser/openmeta-mms

max_issues_repo_name: lefevre-fraser/openmeta-mms

max_forks_repo_name: lefevre-fraser/openmeta-mms


text:
/*
 * Copyright (C) 2012 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#ifdef _WIN32
  #include <io.h>

  // Seems like W_OK does not exists on Windows.
  // Reading access function documentation, the value should be 2
  // http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx
  // Test for write permission.
  #define W_OK    2
  #define access _access
#endif

#include <functional>

#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>

#include <boost/date_time.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/copy.hpp>
#include <iomanip>

#include <ignition/math/Rand.hh>

#include "gazebo/common/CommonIface.hh"
#include "gazebo/common/Assert.hh"
#include "gazebo/common/Base64.hh"
#include "gazebo/common/Console.hh"
#include "gazebo/common/Events.hh"
#include "gazebo/common/Exception.hh"
#include "gazebo/common/Time.hh"
#include "gazebo/common/SystemPaths.hh"
#include "gazebo/gazebo_config.h"
#include "gazebo/transport/transport.hh"
#include "gazebo/util/LogRecordPrivate.hh"
#include "gazebo/util/LogRecord.hh"

using namespace gazebo;
using namespace util;

//////////////////////////////////////////////////
LogRecord::LogRecord()
: dataPtr(new LogRecordPrivate)
{
  this->dataPtr->pauseState = false;
  this->dataPtr->running = false;
  this->dataPtr->paused = false;
  this->dataPtr->initialized = false;
  this->dataPtr->stopThread = false;
  this->dataPtr->firstUpdate = true;
  this->dataPtr->readyToStart = false;

  // Get the user's home directory
#ifndef _WIN32
  const char *homePath = common::getEnv("HOME");
#else
  const char *homePath = common::getEnv("HOMEPATH");
#endif

  GZ_ASSERT(homePath, "HOME environment variable is missing");

  if (!homePath)
  {
    common::SystemPaths *paths = common::SystemPaths::Instance();
    this->dataPtr->logBasePath = paths->TmpPath() + "/gazebo";
  }
  else
  {
    this->dataPtr->logBasePath = boost::filesystem::path(homePath);
  }

  this->dataPtr->logBasePath /= "/.gazebo/log/";

  this->dataPtr->logsEnd = this->dataPtr->logs.end();

  this->dataPtr->connections.push_back(
     event::Events::ConnectPause(
       std::bind(&LogRecord::OnPause, this, std::placeholders::_1)));
}

//////////////////////////////////////////////////
void LogRecord::OnPause(const bool _pause)
{
  this->dataPtr->pauseState = _pause;
}

//////////////////////////////////////////////////
LogRecord::~LogRecord()
{
  // Stop the write thread.
  this->Fini();
}

//////////////////////////////////////////////////
bool LogRecord::Init(const std::string &_subdir)
{
  if (_subdir.empty())
  {
    gzerr << "LogRecord initialization directory is empty." << std::endl;
    return false;
  }

  this->dataPtr->logSubDir = _subdir;

  this->ClearLogs();

  this->dataPtr->initialized = true;
  this->dataPtr->running = false;
  this->dataPtr->paused = false;
  this->dataPtr->stopThread = false;
  this->dataPtr->firstUpdate = true;
  this->dataPtr->readyToStart = true;

  return true;
}

//////////////////////////////////////////////////
bool LogRecord::Start(const LogRecordParams &_params)
{
  this->dataPtr->period = _params.period;
  this->dataPtr->filter = _params.filter;
  return this->Start(_params.encoding, _params.path);
}

//////////////////////////////////////////////////
bool LogRecord::Start(const std::string &_encoding, const std::string &_path)
{
  std::unique_lock<std::mutex> lock(this->dataPtr->controlMutex);

  // Make sure ::Init has been called.
  if (!this->dataPtr->initialized)
  {
    gzerr << "LogRecord has not been initialized." << std::endl;
    return false;
  }

  // Check to see if the logger is already started.
  if (this->dataPtr->running)
  {
    /// \TODO replace this with gzlog
    gzerr << "LogRecord has already been started" << std::endl;
    return false;
  }

  // Get the current time as an ISO string.
  std::string logTimeDir = common::Time::GetWallTimeAsISOString();

  // remove ":" if the dir is to be added to env path, e.g. for playback
  // with resources
  logTimeDir = common::replaceAll(logTimeDir, ":", "");

  // Override the default path settings if the _path parameter is set.
  if (!_path.empty())
  {
    this->dataPtr->logBasePath = boost::filesystem::path(_path);
    this->dataPtr->logCompletePath = this->dataPtr->logBasePath;
  }
  else
  {
    this->dataPtr->logCompletePath = this->dataPtr->logBasePath /
      logTimeDir / this->dataPtr->logSubDir;
  }

  // Create the log directory if necessary
  if (!boost::filesystem::exists(this->dataPtr->logCompletePath))
    boost::filesystem::create_directories(this->dataPtr->logCompletePath);

  if (_encoding != "bz2" && _encoding != "txt" && _encoding != "zlib")
    gzthrow("Invalid log encoding[" + _encoding +
            "]. Must be one of [bz2, zlib, txt]");

  this->dataPtr->encoding = _encoding;

  {
    std::unique_lock<std::mutex> logLock(this->dataPtr->writeMutex);
    this->dataPtr->logsEnd = this->dataPtr->logs.end();

    // Start all the logs
    for (LogRecordPrivate::Log_M::iterator iter = this->dataPtr->logs.begin();
         iter != this->dataPtr->logsEnd; ++iter)
      iter->second->Start(this->dataPtr->logCompletePath);
  }

  this->dataPtr->running = true;
  this->dataPtr->paused = false;
  this->dataPtr->firstUpdate = true;
  this->dataPtr->stopThread = false;
  this->dataPtr->readyToStart = false;

  this->dataPtr->startTime = this->dataPtr->currTime = common::Time();

  // Create a thread to cleanup recording.
  this->dataPtr->cleanupThread.reset(new std::thread(
        std::bind(&LogRecord::Cleanup, this)));

  // Wait for thread to start
  this->dataPtr->startThreadCondition.wait(lock);

  // Start the update thread if it has not already been started
  if (!this->dataPtr->updateThread)
  {
    std::unique_lock<std::mutex> updateLock(this->dataPtr->updateMutex);
    this->dataPtr->updateThread.reset(new std::thread(
        std::bind(&LogRecord::RunUpdate, this)));
    this->dataPtr->startThreadCondition.wait(updateLock);
  }

  // Start the writing thread if it has not already been started
  if (!this->dataPtr->writeThread)
  {
    std::unique_lock<std::mutex> writeLock(this->dataPtr->runWriteMutex);
    this->dataPtr->writeThread.reset(new std::thread(
        std::bind(&LogRecord::RunWrite, this)));
    this->dataPtr->startThreadCondition.wait(writeLock);
  }

  return true;
}

//////////////////////////////////////////////////
const std::string &LogRecord::Encoding() const
{
  return this->dataPtr->encoding;
}

//////////////////////////////////////////////////
void LogRecord::Fini()
{
  this->dataPtr->logControlSub.reset();
  this->dataPtr->logStatusPub.reset();
  if (this->dataPtr->node)
    this->dataPtr->node->Fini();
  this->dataPtr->node.reset();

  {
    std::unique_lock<std::mutex> lock(this->dataPtr->controlMutex);
    this->dataPtr->cleanupCondition.notify_all();
  }

  if (this->dataPtr->cleanupThread && this->dataPtr->cleanupThread->joinable())
    this->dataPtr->cleanupThread->join();
  this->dataPtr->cleanupThread.reset();

  std::lock_guard<std::mutex> lock(this->dataPtr->controlMutex);
  this->dataPtr->connections.clear();

  // Remove all the logs.
  this->ClearLogs();
}

//////////////////////////////////////////////////
void LogRecord::Stop()
{
  this->dataPtr->running = false;
  this->dataPtr->cleanupCondition.notify_all();

  if (this->dataPtr->cleanupThread && this->dataPtr->cleanupThread->joinable())
    this->dataPtr->cleanupThread->join();
  this->dataPtr->cleanupThread.reset();
  this->dataPtr->savedModels.clear();
  this->dataPtr->savedFiles.clear();
}

//////////////////////////////////////////////////
void LogRecord::ClearLogs()
{
  std::lock_guard<std::mutex> logLock(this->dataPtr->writeMutex);

  // Delete all the log objects
  for (LogRecordPrivate::Log_M::iterator iter = this->dataPtr->logs.begin();
      iter != this->dataPtr->logs.end(); ++iter)
  {
    delete iter->second;
  }

  this->dataPtr->logs.clear();
  this->dataPtr->logsEnd = this->dataPtr->logs.end();
}

//////////////////////////////////////////////////
void LogRecord::SetPaused(const bool _paused)
{
  this->dataPtr->paused = _paused;
}

//////////////////////////////////////////////////
bool LogRecord::Paused() const
{
  return this->dataPtr->paused;
}

//////////////////////////////////////////////////
double LogRecord::Period() const
{
  return this->dataPtr->period;
}

//////////////////////////////////////////////////
void LogRecord::SetPeriod(const double _period)
{
  this->dataPtr->period = _period;
}

//////////////////////////////////////////////////
std::string LogRecord::Filter() const
{
  return this->dataPtr->filter;
}

//////////////////////////////////////////////////
void LogRecord::SetFilter(const std::string &_filter)
{
  this->dataPtr->filter = _filter;
}

//////////////////////////////////////////////////
bool LogRecord::Running() const
{
  return this->dataPtr->running;
}

//////////////////////////////////////////////////
bool LogRecord::RecordResources() const
{
  return this->dataPtr->recordResources;
}

//////////////////////////////////////////////////
void LogRecord::SetRecordResources(const bool _record)
{
  this->dataPtr->recordResources = _record;
}

//////////////////////////////////////////////////
void LogRecord::Add(const std::string &_name, const std::string &_filename,
                    std::function<bool (std::ostringstream &)> _logCallback)
{
  std::lock_guard<std::mutex> logLock(this->dataPtr->writeMutex);

  // Check to see if the log has already been added.
  if (this->dataPtr->logs.find(_name) != this->dataPtr->logs.end())
  {
    GZ_ASSERT(this->dataPtr->logs.find(_name)->second != NULL,
        "Unable to find log");

    if (this->dataPtr->logs.find(_name)->second->RelativeFilename() !=
        _filename)
    {
      gzerr << "Attempting to add a duplicate log object named["
          << _name << "] with a filename of [" << _filename << "].\n";
      return;
    }
    else
    {
      return;
    }
  }

  LogRecordPrivate::Log *newLog;

  // Create a new log object
  try
  {
    newLog = new LogRecordPrivate::Log(this, _filename, _logCallback);
  }
  catch(...)
  {
    gzthrow("Unable to create log. File permissions are probably bad.");
  }

  if (this->dataPtr->running)
    newLog->Start(this->dataPtr->logCompletePath);

  // Add the log to our map
  this->dataPtr->logs[_name] = newLog;

  // Update the pointer to the end of the log objects list.
  this->dataPtr->logsEnd = this->dataPtr->logs.end();

  if (!this->dataPtr->node)
  {
    this->dataPtr->node = transport::NodePtr(new transport::Node());
    this->dataPtr->node->Init();

    this->dataPtr->logControlSub =
      this->dataPtr->node->Subscribe("~/log/control",
          &LogRecord::OnLogControl, this);
    this->dataPtr->logStatusPub =
      this->dataPtr->node->Advertise<msgs::LogStatus>("~/log/status");
  }
}

//////////////////////////////////////////////////
bool LogRecord::Remove(const std::string &_name)
{
  std::lock_guard<std::mutex> logLock(this->dataPtr->writeMutex);

  bool result = false;

  LogRecordPrivate::Log_M::iterator iter = this->dataPtr->logs.find(_name);
  if (iter != this->dataPtr->logs.end())
  {
    delete iter->second;
    this->dataPtr->logs.erase(iter);

    // Update the pointer to the end of the log objects list.
    this->dataPtr->logsEnd = this->dataPtr->logs.end();

    result = true;
  }

  return result;
}

//////////////////////////////////////////////////
std::string LogRecord::Filename(const std::string &_name) const
{
  std::lock_guard<std::mutex> logLock(this->dataPtr->writeMutex);

  std::string result;

  LogRecordPrivate::Log_M::const_iterator iter =
    this->dataPtr->logs.find(_name);
  if (iter != this->dataPtr->logs.end())
  {
    GZ_ASSERT(iter->second, "Invalid log");
    result = iter->second->CompleteFilename();
  }
  else
    result = this->dataPtr->logs.begin()->second->CompleteFilename();

  return result;
}

//////////////////////////////////////////////////
unsigned int LogRecord::FileSize(const std::string &_name) const
{
  unsigned int result = 0;

  // Get the filename of the specified log object;
  std::string filename = this->Filename(_name);

  // Get the size of the log file on disk.
  if (!filename.empty())
  {
    // Get the size of the file
    if (!filename.empty() && boost::filesystem::exists(filename))
      result = boost::filesystem::file_size(filename);
  }

  // Add in the contents of the write buffer. This is the data that will be
  // written to disk soon.
  {
    std::lock_guard<std::mutex> lock(this->dataPtr->writeMutex);
    LogRecordPrivate::Log_M::const_iterator iter =
      this->dataPtr->logs.find(_name);

    if (iter != this->dataPtr->logs.end())
    {
      GZ_ASSERT(iter->second, "Log object is NULL");
      result += iter->second->BufferSize();
    }
  }

  return result;
}

//////////////////////////////////////////////////
void LogRecord::SetBasePath(const std::string &_path)
{
  // Make sure the  directory exists
  if (!boost::filesystem::exists(_path))
    boost::filesystem::create_directories(_path);

  // Make sure we have a directory
  if (!boost::filesystem::is_directory(_path))
  {
    gzerr << "Path " << _path << " is not a directory. Please only specify a "
           << "directory for data logging.\n";
    return;
  }

  // Make sure the path is writable.
  // Note: This is not cross-platform compatible.
  if (access(_path.c_str(), W_OK) != 0)
  {
    gzerr << "You do no have permission to write into " << _path << "\n";
    return;
  }

  this->dataPtr->logBasePath = _path;
}

//////////////////////////////////////////////////
std::string LogRecord::BasePath() const
{
  return this->dataPtr->logBasePath.string();
}

//////////////////////////////////////////////////
bool LogRecord::FirstUpdate() const
{
  return this->dataPtr->firstUpdate;
}

//////////////////////////////////////////////////
bool LogRecord::SaveModels(const std::set<std::string> &_models)
{
  std::set<std::string> diff;
  std::set_difference(_models.begin(), _models.end(),
      this->dataPtr->savedModels.begin(), this->dataPtr->savedModels.end(),
      std::inserter(diff, diff.begin()));

  for (auto &model: diff)
  {
    if (model.empty())
      continue;

    this->dataPtr->savedModels.insert(model);

    bool modelFound = false;
    for (const auto &path : common::SystemPaths::Instance()->GetModelPaths())
    {
      boost::filesystem::path srcModelPath(path);
      srcModelPath /= model;
      if (boost::filesystem::exists(srcModelPath))
      {
        modelFound = true;
        boost::filesystem::path destModelPath =
          this->dataPtr->logCompletePath / model;
        if (!gazebo::common::copyDir(srcModelPath, destModelPath))
        {
          gzerr << "Failed to copy model from '" << srcModelPath.string()
                 << "' to '" << destModelPath.string() << "'" << std::endl;
        }
        break;
      }
    }

    if (!modelFound)
    {
      gzwarn << "Model: " << model << " not found, "
        << "please check the value of env variable GAZEBO_MODEL_PATH\n";
    }
  }
  return true;
}

//////////////////////////////////////////////////
bool LogRecord::SaveFiles(const std::set<std::string> &_files)
{
  if (_files.empty())
    return false;

  bool saveError = false;
  std::set<std::string> diff;
  std::set_difference(_files.begin(), _files.end(),
      this->dataPtr->savedFiles.begin(),
      this->dataPtr->savedFiles.end(),
      std::inserter(diff, diff.begin()));

  for (auto &file : diff)
  {
    if (file.empty())
      continue;

    this->dataPtr->savedFiles.insert(file);

    bool fileFound = false;
    std::string prefix = "file://";
    std::string fileName = file;

    boost::filesystem::path srcPath;
    if (fileName.compare(0, prefix.size(), prefix) == 0)
    {
      // strip prefix
      fileName = file.substr(prefix.size());
      // search in gazebo path
      for (const auto &path : common::SystemPaths::Instance()->GetGazeboPaths())
      {
        auto p = boost::filesystem::path(path) / fileName;
        if (common::exists(p.string()))
        {
          srcPath = path;
          fileFound = true;
          break;
        }
      }
    }

    // if not found in gazebo path or resource has abs path then check local
    // filesystem
    if (!fileFound || fileName[0] == '/')
    {
      fileFound = common::exists(fileName);
    }

    // copy resource
    // NOTE: if file is a mesh, e.g. box.dae, it could contain reference to
    // to texture files in other directories. A hacky workaround is to copy
    // entire model dir
    if (fileFound)
    {
      // HACK! copy entire model dir if mesh
      size_t meshIdx = fileName.find("/meshes/");
      if (meshIdx != std::string::npos)
      {
        auto modelPath =
            boost::filesystem::path(fileName.substr(0, meshIdx));
        srcPath = srcPath / modelPath;
        boost::filesystem::path destPath =
          this->dataPtr->logCompletePath / modelPath;
        boost::system::error_code errorCode;
        boost::filesystem::create_directories(destPath, errorCode);
        if (errorCode != boost::system::errc::success ||
            !gazebo::common::copyDir(srcPath, destPath))
        {
          gzerr << "Failed to copy model from '" << srcPath.string()
                 << "' to '" << destPath.string() << "'" << std::endl;
          saveError = true;
        }
      }
      // else copy only the specified file
      else
      {
        srcPath = srcPath / fileName;
        boost::filesystem::path destPath =
          this->dataPtr->logCompletePath / fileName;
        boost::system::error_code errorCode;
        boost::filesystem::create_directories(
            destPath.parent_path(), errorCode);
        if (errorCode == boost::system::errc::success)
          boost::filesystem::copy_file(srcPath, destPath, errorCode);
        else
        {
          gzerr << "Failed to copy file from '" << srcPath.string()
                 << "' to '" << destPath.string() << "'" << std::endl;
          saveError = true;
        }
      }
    }
    else
    {
      gzerr << "File: " << file << " not found!" << std::endl;
      saveError = true;
    }
  }

  return !saveError;
}

//////////////////////////////////////////////////
void LogRecord::Notify()
{
  if (this->dataPtr->running)
    this->dataPtr->updateCondition.notify_all();
}

//////////////////////////////////////////////////
void LogRecord::RunUpdate()
{
  std::unique_lock<std::mutex> updateLock(this->dataPtr->updateMutex);
  this->dataPtr->startThreadCondition.notify_all();

  // This loop will write data to disk.
  while (!this->dataPtr->stopThread)
  {
    // Don't completely lock, just to be safe.
    this->dataPtr->updateCondition.wait(updateLock);

    if (!this->dataPtr->stopThread)
      this->Update();
  }
}

//////////////////////////////////////////////////
void LogRecord::Update()
{
  if (!this->dataPtr->paused)
  {
    unsigned int size = 0;

    {
      std::lock_guard<std::mutex> lock(this->dataPtr->writeMutex);

      // Collect all the new log data. This will not write data to disk.
      for (this->dataPtr->updateIter = this->dataPtr->logs.begin();
           this->dataPtr->updateIter != this->dataPtr->logsEnd;
           ++this->dataPtr->updateIter)
      {
        size += this->dataPtr->updateIter->second->Update();
      }
    }

    if (this->dataPtr->firstUpdate)
    {
      this->dataPtr->firstUpdate = false;
      this->dataPtr->startTime = common::Time::GetWallTime();
    }

    // Signal that new data is available.
    if (size > 0)
      this->dataPtr->dataAvailableCondition.notify_one();

    this->dataPtr->currTime = common::Time::GetWallTime();

    // Output the new log status
    this->PublishLogStatus();
  }
}

//////////////////////////////////////////////////
void LogRecord::RunWrite()
{
  // Wait for new data.
  std::unique_lock<std::mutex> lock(this->dataPtr->runWriteMutex);
  this->dataPtr->startThreadCondition.notify_all();

  // This loop will write data to disk.
  while (!this->dataPtr->stopThread)
  {
    this->dataPtr->dataAvailableCondition.wait(lock);

    this->Write(false);
  }
}

//////////////////////////////////////////////////
void LogRecord::Write(const bool /*_force*/)
{
  std::lock_guard<std::mutex> lock(this->dataPtr->writeMutex);

  // Collect all the new log data.
  for (this->dataPtr->updateIter = this->dataPtr->logs.begin();
      this->dataPtr->updateIter != this->dataPtr->logsEnd;
      ++this->dataPtr->updateIter)
  {
    this->dataPtr->updateIter->second->Write();
  }
}

//////////////////////////////////////////////////
common::Time LogRecord::RunTime() const
{
  return this->dataPtr->currTime - this->dataPtr->startTime;
}

//////////////////////////////////////////////////
LogRecordPrivate::Log::Log(LogRecord *_parent,
    const std::string &_relativeFilename,
    std::function<bool (std::ostringstream &)> _logCB)
{
  this->parent = _parent;
  this->logCB = _logCB;

  this->relativeFilename = _relativeFilename;
}

//////////////////////////////////////////////////
LogRecordPrivate::Log::~Log()
{
  this->Stop();
}

//////////////////////////////////////////////////
unsigned int LogRecordPrivate::Log::Update()
{
  std::ostringstream stream;

  // Get log data via the callback.
  if (this->logCB(stream))
  {
    std::string data = stream.str();
    if (!data.empty())
    {
      const std::string &encodingLocal = this->parent->Encoding();

      this->buffer.append("<chunk encoding='");
      this->buffer.append(encodingLocal);
      this->buffer.append("'>\n");

      this->buffer.append("<![CDATA[");
      // Compress the data.
      if (encodingLocal == "bz2")
      {
        std::string str;

        // Compress to bzip2
        {
          boost::iostreams::filtering_ostream out;
          out.push(boost::iostreams::bzip2_compressor());
          out.push(std::back_inserter(str));
          boost::iostreams::copy(boost::make_iterator_range(data), out);
        }

        // Encode in base64.
        Base64Encode(str.c_str(), str.size(), this->buffer);
      }
      else if (encodingLocal == "zlib")
      {
        std::string str;

        // Compress to zlib
        {
          boost::iostreams::filtering_ostream out;
          out.push(boost::iostreams::zlib_compressor());
          out.push(std::back_inserter(str));
          boost::iostreams::copy(boost::make_iterator_range(data), out);
        }

        // Encode in base64.
        Base64Encode(str.c_str(), str.size(), this->buffer);
      }
      else if (encodingLocal == "txt")
        this->buffer.append(data);
      else
        gzerr << "Unknown log file encoding[" << encodingLocal << "]\n";
      this->buffer.append("]]>\n");

      this->buffer.append("</chunk>\n");
    }
  }

  return this->buffer.size();
}

//////////////////////////////////////////////////
void LogRecordPrivate::Log::ClearBuffer()
{
  this->buffer.clear();
}

//////////////////////////////////////////////////
unsigned int LogRecordPrivate::Log::BufferSize()
{
  return this->buffer.size();
}

//////////////////////////////////////////////////
std::string LogRecordPrivate::Log::RelativeFilename() const
{
  return this->relativeFilename;
}

//////////////////////////////////////////////////
std::string LogRecordPrivate::Log::CompleteFilename() const
{
  return this->completePath.string();
}

//////////////////////////////////////////////////
void LogRecordPrivate::Log::Stop()
{
  if (this->logFile.is_open())
  {
    this->Update();
    this->Write();

    std::string xmlEnd = "</gazebo_log>";
    this->logFile.write(xmlEnd.c_str(), xmlEnd.size());

    this->logFile.close();
  }

  this->completePath.clear();
}

//////////////////////////////////////////////////
void LogRecordPrivate::Log::Start(const boost::filesystem::path &_path)
{
  // Make the full path for the log file
  this->completePath = _path / this->relativeFilename;

  // Make sure the file does not exist
  if (boost::filesystem::exists(this->completePath))
    gzlog << "Filename [" + this->completePath.string() + "], already exists."
          << " The log file will be overwritten.\n";

  std::ostringstream stream;
  stream << "<?xml version='1.0'?>\n"
         << "<gazebo_log>\n"
         << "<header>\n"
         << "<log_version>" << GZ_LOG_VERSION << "</log_version>\n"
         << "<gazebo_version>" << GAZEBO_VERSION_FULL << "</gazebo_version>\n"
         << "<rand_seed>" << ignition::math::Rand::Seed() << "</rand_seed>\n"
         << "</header>\n";

  this->buffer.append(stream.str());
}

//////////////////////////////////////////////////
void LogRecordPrivate::Log::Write()
{
  // Make sure the file is open for writing
  if (!this->logFile.is_open())
  {
    // Try to open it...
    this->logFile.open(this->completePath.string().c_str(),
                       std::fstream::out | std::ios::binary);

    // Throw an error if we couldn't open the file for writing.
    if (!this->logFile.is_open())
      gzthrow("Unable to open file for logging:" +
              this->completePath.string() + "]");
  }

  // Check to see if the log file still exists on disk. This will catch the
  // case when someone deletes a log file while recording.
  if (!boost::filesystem::exists(this->completePath.string().c_str()))
  {
    gzerr << "Log file[" << this->completePath << "] no longer exists. "
          << "Unable to write log data.\n";

    // We have to clear the buffer, or else it may grow indefinitely.
    this->buffer.clear();
    return;
  }

  // Write out the contents of the buffer.
  this->logFile.write(this->buffer.c_str(), this->buffer.size());
  this->logFile.flush();

  // Clear the buffer.
  this->buffer.clear();
}

//////////////////////////////////////////////////
void LogRecord::OnLogControl(ConstLogControlPtr &_data)
{
  if (_data->has_base_path() && !_data->base_path().empty())
    this->SetBasePath(_data->base_path());

  std::string msgEncoding = "zlib";
  if (_data->has_encoding())
    msgEncoding = _data->encoding();

  if (_data->has_start() && _data->start())
  {
    this->Start(msgEncoding);
  }
  else if (_data->has_stop() && _data->stop())
  {
    this->Stop();
  }
  else if (_data->has_paused())
  {
    this->SetPaused(_data->paused());
  }

  // Output the new log status
  this->PublishLogStatus();
}

//////////////////////////////////////////////////
void LogRecord::PublishLogStatus()
{
  if (this->dataPtr->logs.empty() || !this->dataPtr->logStatusPub ||
      !this->dataPtr->logStatusPub->HasConnections())
    return;

  /// \todo right now this function will only report on the first log.

  msgs::LogStatus msg;
  unsigned int size = 0;

  // Set the time of the status message
  msgs::Set(msg.mutable_sim_time(), this->RunTime());

  // Set the log recording base path name
  msg.mutable_log_file()->set_base_path(this->BasePath());

  // Get the full name of the log file
  msg.mutable_log_file()->set_full_path(this->Filename());

  // Set the URI of th log file
  msg.mutable_log_file()->set_uri(transport::Connection::GetLocalHostname());

  // Get the size of the log file
  size = this->FileSize();

  if (size < 1000)
    msg.mutable_log_file()->set_size_units(msgs::LogStatus::LogFile::BYTES);
  else if (size < 1e6)
  {
    msg.mutable_log_file()->set_size(size / 1.0e3);
    msg.mutable_log_file()->set_size_units(msgs::LogStatus::LogFile::K_BYTES);
  }
  else if (size < 1e9)
  {
    msg.mutable_log_file()->set_size(size / 1.0e6);
    msg.mutable_log_file()->set_size_units(msgs::LogStatus::LogFile::M_BYTES);
  }
  else
  {
    msg.mutable_log_file()->set_size(size / 1.0e9);
    msg.mutable_log_file()->set_size_units(msgs::LogStatus::LogFile::G_BYTES);
  }

  this->dataPtr->logStatusPub->Publish(msg);
}

//////////////////////////////////////////////////
void LogRecord::Cleanup()
{
  std::unique_lock<std::mutex> lock(this->dataPtr->controlMutex);
  this->dataPtr->startThreadCondition.notify_all();

  // Wait for the cleanup signal
  this->dataPtr->cleanupCondition.wait(lock);

  bool currentPauseState = this->dataPtr->pauseState;
  event::Events::pause(true);

  // Reset the flags
  this->dataPtr->paused = false;
  this->dataPtr->running = false;
  this->dataPtr->stopThread = true;

  // Kick the update thread
  {
    std::lock_guard<std::mutex> updateLock(this->dataPtr->updateMutex);
    this->dataPtr->updateCondition.notify_all();
  }

  // Wait for the write thread, if it exists
  if (this->dataPtr->updateThread)
    this->dataPtr->updateThread->join();

  // Kick the write thread
  {
    std::lock_guard<std::mutex> lock2(this->dataPtr->runWriteMutex);
    this->dataPtr->dataAvailableCondition.notify_all();
  }

  // Wait for the write thread, if it exists
  if (this->dataPtr->writeThread)
    this->dataPtr->writeThread->join();

  this->dataPtr->updateThread.reset();
  this->dataPtr->writeThread.reset();

  // Update and write one last time to make sure we log all data.
  this->Update();

  this->Write(true);

  // Stop all the logs
  for (LogRecordPrivate::Log_M::iterator iter = this->dataPtr->logs.begin();
      iter != this->dataPtr->logsEnd; ++iter)
  {
    iter->second->Stop();
  }

  // Reset the times
  this->dataPtr->startTime = this->dataPtr->currTime = common::Time();

  // Output the new log status
  this->PublishLogStatus();

  event::Events::pause(currentPauseState);
  this->dataPtr->readyToStart = true;
}

//////////////////////////////////////////////////
bool LogRecord::IsReadyToStart() const
{
  return this->dataPtr->readyToStart;
}

//////////////////////////////////////////////////
unsigned int LogRecord::BufferSize() const
{
  std::lock_guard<std::mutex> lock(this->dataPtr->writeMutex);
  unsigned int size = 0;

  for (LogRecordPrivate::Log_M::const_iterator iter =
       this->dataPtr->logs.begin();
       iter != this->dataPtr->logs.end(); ++iter)
  {
    size += iter->second->BufferSize();
  }

  return size;
}

ext: cc

max_stars_repo_name: nyxrobotics/gazebo

max_issues_repo_name: nyxrobotics/gazebo

max_forks_repo_name: nyxrobotics/gazebo


text:
/**
 * Copyright (c) 2018, University Osnabrück
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the University Osnabrück nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL University Osnabrück BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * EigenSVDPointAlign.hpp
 *
 *  @date Feb 21, 2014
 *  @author Thomas Wiemann
 */
#ifndef EIGENSVDPOINTALIGN_HPP_
#define EIGENSVDPOINTALIGN_HPP_

#include "SLAMScanWrapper.hpp"
#include "lvr2/types/MatrixTypes.hpp"

#include <Eigen/Dense>

namespace lvr2
{

template<typename T, typename PointT = float>
class EigenSVDPointAlign
{
public:
    using Vec3 = Vector3<T>;
    using Mat4 = Transform<T>;
    using Mat3 = Eigen::Matrix<T, 3, 3>;
    using Point3 = Vector3<PointT>;
    using PointPairVector = std::vector<std::pair<Point3, Point3>>;

    EigenSVDPointAlign() {};

    /**
     * @brief Calculates the estimated Transformation to match a Data Pointcloud to a Model
     *        Pointcloud
     *
     * Apply the resulting Transform to the Data Pointcloud.
     *
     * @param scan       The Data Pointcloud
     * @param neighbors  An array containing a Pointer to a neighbor in the Model Pointcloud for
     *                   each Point in `scan`, or nullptr if there is no neighbor for a Point
     * @param centroid_m The center of the Model Pointcloud
     * @param centroid_d The center of the Data Pointcloud
     * @param align      Will be set to the Transformation
     *
     * @return The average Point-to-Point error of the Scans
     */
    T alignPoints(
        SLAMScanPtr scan,
        Point3** neighbors,
        const Vec3& centroid_m,
        const Vec3& centroid_d,
        Mat4& align) const;

    /**
     * @brief Calculates the estimated Transformation to match a Data Pointcloud to a Model
     *        Pointcloud
     *
     * Apply the resulting Transform to the Data Pointcloud.
     *
     * @param points     A vector of pairs with (model, data) Points
     * @param centroid_m The center of the Model Pointcloud
     * @param centroid_d The center of the Data Pointcloud
     * @param align      Will be set to the Transformation
     *
     * @return The average Point-to-Point error of the Scans
     */
    T alignPoints(
        PointPairVector& points,
        const Vec3& centroid_m,
        const Vec3& centroid_d,
        Mat4& align) const;
};

} /* namespace lvr2 */

#include "EigenSVDPointAlign.tcc"

#endif /* EIGENSVDPOINTALIGN_HPP_ */

ext: hpp

max_stars_repo_name: uos/lvr

max_issues_repo_name: uos/lvr

max_forks_repo_name: uos/lvr


text: #include <boost/spirit/include/phoenix_container.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#ifndef BOOST_SERIALIZATION_NVP_HPP
#define BOOST_SERIALIZATION_NVP_HPP

// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// nvp.hpp: interface for serialization system.

// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org for updates, documentation, and revision history.

#include <boost/core/nvp.hpp>
#include <boost/preprocessor/stringize.hpp>

#define BOOST_SERIALIZATION_NVP(name)                       \
    boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), name)
/**/

#define BOOST_SERIALIZATION_BASE_OBJECT_NVP(name)           \
    boost::serialization::make_nvp(                         \
        BOOST_PP_STRINGIZE(name),                           \
        boost::serialization::base_object<name >(*this)     \
    )
/**/

#include <boost/serialization/level.hpp>
#include <boost/serialization/tracking.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/wrapper.hpp>
#include <boost/serialization/base_object.hpp>

namespace boost {
namespace serialization {

template<class Archive, class T>
void save(
    Archive & ar,
    const nvp<T> & t,
    const unsigned int /* file_version */
){
    ar << t.const_value();
}
template<class Archive, class T>
void load(
    Archive & ar,
    nvp<T> & t ,
    const unsigned int /* file_version */
){
    ar >> t.value();
}

template<class Archive, class T>
inline void serialize(
    Archive & ar,
    nvp<T> & t,
    const unsigned int file_version
){
    split_free(ar, t, file_version);
}

template <class T>
struct implementation_level<nvp< T > >
{
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<object_serializable> type;
    BOOST_STATIC_CONSTANT(int, value = implementation_level::type::value);
};
template <class T>
struct implementation_level<const nvp< T > >
{
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<object_serializable> type;
    BOOST_STATIC_CONSTANT(int, value = implementation_level::type::value);
};

// nvp objects are generally created on the stack and are never tracked
template<class T>
struct tracking_level<nvp< T > >
{
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<track_never> type;
    BOOST_STATIC_CONSTANT(int, value = tracking_level::type::value);
};
template<class T>
struct tracking_level<const nvp< T > >
{
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<track_never> type;
    BOOST_STATIC_CONSTANT(int, value = tracking_level::type::value);
};

// these traits aren't used by nvp so they don't need to be defined
#if 0
template<class T>
struct version<const nvp< T > > {
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<0> type;
    BOOST_STATIC_CONSTANT(int, value = 0);
};
struct version<const nvp< T > > {
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<0> type;
    BOOST_STATIC_CONSTANT(int, value = 0);
};

template<class T>
struct extended_type_info_impl<const nvp< T > > {
    typedef extended_type_info_impl< T > type;
};
#endif

template<class T>
struct is_wrapper<const nvp<T> > {
    typedef boost::mpl::true_ type;
};
template<class T>
struct is_wrapper<nvp<T> > {
    typedef boost::mpl::true_ type;
};

} // seralization
} // boost

#endif // BOOST_SERIALIZATION_NVP_HPP

max_stars_repo_name: cpp-pm/boost

max_issues_repo_name: cpp-pm/boost

max_forks_repo_name: cpp-pm/boost