Sauvegarde d'une struct complexe vers fichier possible ?

Signaler
Messages postés
6
Date d'inscription
jeudi 2 juillet 2009
Statut
Membre
Dernière intervention
18 janvier 2010
-
Messages postés
6
Date d'inscription
jeudi 2 juillet 2009
Statut
Membre
Dernière intervention
18 janvier 2010
-
Salut !

Dans le cadre d'un de mes projets en c++, j'ai besoin de sauvegarder la structure Particle afin de pouvoir la recharger lors du redémarrage du programme.

Cependant avec tous ces pointeurs et autres structures de données complexes ... j'ai quelques doutes sur le fait que je puisse réellement faire ce dont j'ai besoin.
Donc ma question est la suivante:
Pensez-vous qu'il est possible de sauvegarder la struct Particle dans un fichier pour la recharger ultérieurement ?

Je vous ai mis les parties relevantes (variables) des différents types/struct et classes ci-dessous. J'ai généralement omis de mettre les differentes fonctions propres a chaque classe afin de rendre tout ca plus lisible !

Si c'est possible de le faire, quelques pistes seraient les bienvenues !
En vous remerciant !

Struct Particle{
ScanMatcherMap map;
OrientedPoint pose;
double weight;
double weightSum;
double gweight;
int previousIndex;
TNode* node;
}; 

typedef Map> ScanMatcherMap;
template <class Cell, class Storage, const bool isClass=true> class Map{
Point m_center;
double m_worldSizeX, m_worldSizeY, m_delta;
Storage m_storage;
int m_mapSizeX, m_mapSizeY;
int m_sizeX2, m_sizeY2;
static const Cell m_unknown;
};

struct PointAccumulator{
typedef point<float> FloatPoint;

PointAccumulator(): acc(0,0), n(0), visits(0){}
PointAccumulator(int i): acc(0,0), n(0), visits(0){assert(i==-1);}

static PointAccumulator* unknown_ptr;
FloatPoint acc;
int n, visits;
};

template <class Cell> class HierarchicalArray2D: public Array2D > >{

typedef std::set< point, pointcomparator > PointSet;
HierarchicalArray2D(int xsize, int ysize, int patchMagnitude=5);

PointSet m_activeArea;
int m_patchMagnitude;
int m_patchSize;
};

template<class Cell, const bool debug=false> class Array2D{
Cell ** m_cells;
int m_xsize, m_ysize;
};

template <class X> class autoptr{
struct reference{
X* data;
unsigned int shares;
};
reference * m_reference;
};


struct TNode{
      /**Constructs a node of the trajectory tree.
       @param pose:      the pose of the robot in the trajectory
       @param weight:    the weight of the particle at that point in the trajectory
       @param accWeight: the cumulative weight of the particle
       @param parent:    the parent node in the tree
       @param childs:    the number of childs
      */
      TNode(const OrientedPoint& pose, double weight, TNode* parent=0, unsigned int childs=0);

      OrientedPoint pose; 
      double weight;
      double accWeight;
      double gweight;
      TNode* parent;
      const RangeReading* reading;
      unsigned int childs;
      mutable unsigned int visitCounter;
      mutable bool flag;
    };

class RangeReading: public SensorReading, public std::vector<double>{
std::vector cartesianForm(double maxRange=1e6) const;
unsigned int activeBeams(double density=0.) const;
OrientedPoint m_pose;
};

6 réponses

Messages postés
3829
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
8 janvier 2021
114
Essaie de regarder du côté de Boost::Serialization.

Il y a un bon tuto ici:
http://khayyam.developpez.com/articles/cpp/boost/serialization/

_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
6
Date d'inscription
jeudi 2 juillet 2009
Statut
Membre
Dernière intervention
18 janvier 2010

Merci !

Je vais aller jeter un coup d'oeil à cette librairie.

Mais j'ai quand même quelques doutes sur le fait que j'arriver a serialiser tout ca ! Avec tous ces pointeurs et autres ... m'enfin on va essayer !

Je posterai mes résultats par ici si ca marche :-)
Messages postés
3829
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
8 janvier 2021
114
librairie => bibliothèque :p


_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
6
Date d'inscription
jeudi 2 juillet 2009
Statut
Membre
Dernière intervention
18 janvier 2010

Hello !

Alors je continue dans ce post ...
J'ai jeté un oeil a cette "bibliothèque" (lib...) et ça m'a l'air pas si mal.
J'ai commencé à sérialiser ma structure depuis le bas.

Je rencontre cependant quelques problèmes pour sérialiser mon tableau bi-dimensionnel (Cell** m_cells).
Je vois bien que c'est un problème de mémoire (pointeurs) mais je n'arrive pas à comprendre pourquoi ... peut-être l'un de vous pourra m'expliquer.

A noter que j'ai mis en rouge dans l'output ce qui pose problüme.
En gros, lorsque je charge mon tableau depuis le fichier, il "ecrase" les autres tableaux. Je pense qu'il le charge en "overlapant" sur leurs emplacmement mémoire ...

A noter également que je transforme mon tableau2D en 1D (flatten) avant de le sérialiser puis que j'effectue l'opération inverse juste aprüs l'avoir chargé (unflatten). Si quelqu'un connait une solution plus élégante je suis preneur ...

Voici le code et l'output:

#include 
#include 
#include 

#include <sstream>
#include <fstream>

#include 
#include 
#include 

using namespace std;
using namespace boost::archive;
using namespace boost::serialization;

/*
 * point
 *
 */
template <class T> struct point{
inline point():x(0),y(0) {}
inline point(T _x, T _y):x(_x),y(_y){}
T x, y;
friend class boost::serialization::access;
template <class Archive> 
void serialize(Archive& ar, const unsigned int version){
ar & x & y;
}
};

/*
 * PointAccumulator
 *
 */
struct PointAccumulator{
typedef point<float> FloatPoint;

PointAccumulator(): acc(0,0), n(0), visits(0){}
PointAccumulator(int i): acc(0,0), n(0), visits(0){assert(i==-1);}
//PointAccumulator& operator=(const PointAccumulator & pa);


static PointAccumulator* unknown_ptr;
FloatPoint acc;
int n, visits;

friend class boost::serialization::access; 
template <class Archive> void serialize(Archive& ar, const unsigned int version){
ar & n & visits & acc;
}
};
/*
PointAccumulator& PointAccumulator::operator=(const PointAccumulator &pa){
acc = point<float>(pa.acc.x,pa.acc.y);
n = pa.n;
visits = pa.visits; 
cout << "copied pa " << acc.x << endl;
return *this;
}
*/
/*
 * Array2D
 *
 */
template<class Cell, const bool debug=false> class Array2D{
public:
Array2D(int xsize=0, int ysize=0);
Array2D& operator=(const Array2D &);
Array2D(const Array2D<Cell,debug> &);
void clear();
//inline Array2D(int xsize, int ysize, const Cell * flatCells): m_cells(flatCells), m_ysize(ysize), m_xsize(xsize){}
void flatten();
void unflatten();
//~Array2D();
inline Cell& cell(int x, int y);
inline void print(){
cout << "Displaying array2D (x,y) --> (" << m_xsize << "," << m_ysize << ")" << " as (n,visits,acc.x,acc.y)" <<  endl;
for(int i=0;i<m_xsize;i++){
for(int j=0;j<m_ysize;j++){
cout << "(" << cell(i,j).n << "," << cell(i,j).visits << "," << cell(i,j).acc.x << "," << cell(i,j).acc.y << ") ";
}	
cout<<endl;
} 
/*cout << "flattened: " << endl;
for(int i=0;i<m_xsize*m_ysize;i++){
cout << "acc.x: " << m_cells1D[i].acc.x << "  acc.visits: " << m_cells1D[i].visits << " ";
}*/
cout << endl;
}	
Cell ** m_cells;
Cell * m_cells1D;
protected:
int m_xsize, m_ysize;

friend class boost::serialization::access; 
template <class Archive> void serialize(Archive& ar, const unsigned int version){
ar & m_xsize & m_ysize;

for(int i=0; i<m_xsize*m_ysize;i++){		
ar & m_cells1D[i];
}
}
};

template <class Cell, const bool debug>
Array2D<Cell,debug> & Array2D<Cell,debug>::operator=(const Array2D<Cell,debug> & g){
if (debug || m_xsize!=g.m_xsize || m_ysize!=g.m_ysize){
for (int i=0; i<m_xsize; i++)
delete [] m_cells[i];
delete [] m_cells;
m_xsize=g.m_xsize;
m_ysize=g.m_ysize;
m_cells=new Cell*[m_xsize];
for (int i=0; i<m_xsize; i++)
m_cells[i]=new Cell[m_ysize];
}
for (int x=0; x<m_xsize; x++)
for (int y=0; y<m_ysize; y++)
m_cells[x][y]=g.m_cells[x][y];

if (debug){
std::cerr << __PRETTY_FUNCTION__ << std::endl;
std::cerr << "m_xsize= " << m_xsize<< std::endl;
std::cerr << "m_ysize= " << m_ysize<< std::endl;
}
return *this;
}

template <class Cell, const bool debug>
Array2D<Cell,debug>::Array2D(int xsize, int ysize){
//	assert(xsize>0);
//	assert(ysize>0);
m_xsize=xsize;
m_ysize=ysize;
if (m_xsize>0 && m_ysize>0){
m_cells=new Cell*[m_xsize];
for (int i=0; i<m_xsize; i++)
m_cells[i]=new Cell[m_ysize];
}
else{
m_xsize=m_ysize=0;
m_cells=0;
}
if (debug){
std::cerr << __PRETTY_FUNCTION__ << std::endl;
std::cerr << "m_xsize= " << m_xsize<< std::endl;
std::cerr << "m_ysize= " << m_ysize<< std::endl;
}
}
template <class Cell, const bool debug>
inline Cell& Array2D<Cell,debug>::cell(int x, int y){
return m_cells[x][y];
}

template <class Cell, const bool debug>
Array2D<Cell,debug>::Array2D(const Array2D<Cell,debug> & g){
m_xsize=g.m_xsize;
m_ysize=g.m_ysize;
m_cells=new Cell*[m_xsize];
for (int x=0; x<m_xsize; x++){
m_cells[x]=new Cell[m_ysize];
for (int y=0; y<m_ysize; y++)
m_cells[x][y]=g.m_cells[x][y];
}
if (debug){
std::cerr << __PRETTY_FUNCTION__ << std::endl;
std::cerr << "m_xsize= " << m_xsize<< std::endl;
std::cerr << "m_ysize= " << m_ysize<< std::endl;
}
}

template <class Cell, const bool debug>
void Array2D<Cell,debug>::clear(){
  if (debug){
  	std::cerr << __PRETTY_FUNCTION__ << std::endl;
std::cerr << "m_xsize= " << m_xsize<< std::endl;
std::cerr << "m_ysize= " << m_ysize<< std::endl;
  }
  for (int i=0; i<m_xsize; i++){
    delete [] m_cells[i];
    m_cells[i]=0;
  }
  delete [] m_cells;
  m_cells=0;

delete [] m_cells1D;
m_cells1D = 0;

m_xsize =0;
m_ysize =0;
}

template <class Cell, const bool debug>
void Array2D<Cell,debug>::flatten(){
m_cells1D=new Cell[m_ysize*m_xsize];
for (int x=0; x<m_xsize; x++){
for (int y=0; y<m_ysize; y++)
m_cells1D[x*m_ysize+y]= m_cells[x][y];
}
}

template <class Cell, const bool debug>
void Array2D<Cell,debug>::unflatten(){
m_cells=new Cell*[m_xsize];
for (int x=0; x<m_xsize; x++){
m_cells[x]=new Cell[m_ysize];
for (int y=0; y<m_ysize; y++)
m_cells[x][y]= m_cells1D[x*m_ysize+y];
}
}


/*
 * SaveToFile and LoadFromFile
 *
 */
template <class A> void saveIntoFile(Array2D& array, const char* file){
ofstream ofile(file);
A ar(ofile);		
ar << array;
ofile.close();
}

template <class A> void loadFromFile(Array2D& array, const char* file){
ifstream ifile(file);
A ar(ifile);
ar >> array;
ifile.close();
//return array;
}


/*
 * MAIN
 *
 */
int main(){

Array2D myArr = Array2D(2,2);
myArr.cell(0,0).acc.x = 3;
myArr.cell(0,0).n = 15;
myArr.cell(0,0).visits =16; 
myArr.cell(0,1).acc.x = 3;
myArr.cell(0,1).n = 17;
myArr.cell(0,1).visits = 18;
myArr.cell(1,0).acc.x = 3;

myArr.cell(1,1).n = 20;
myArr.cell(1,1).visits = 21;
myArr.cell(1,1).acc.x = 22;
myArr.cell(1,1).acc.y = 23;

myArr.flatten();
cout << "myArray (toSave)" << endl;	
myArr.print();	
saveIntoFile<text_oarchive>(myArr,"out.txt");

Array2D myArr4 = Array2D();
myArr4 = myArr;

//Destroy myArr
myArr.clear();
cout << "myArray copy" << endl;
myArr4.print();


Array2D myArr2; // = Array2D();
loadFromFile<text_iarchive>(myArr2,"out.txt");
myArr2.unflatten();
cout << "myArray2 (loaded)" << endl;
myArr2.print();

//myArr2 = myArr4;

cout << "myArray (base)" << endl;
myArr.print();
cout << "myArray copy" << endl;
myArr4.print();
cout << "myArray2" << endl;	
myArr2.print();
//myArr2.clear();

cout << "end" << endl;

return 0;
}



Output:

wheelchair@wheelchair-laptop:~/playerstage/boostTest$ g++ simple2.cpp -o simple -lboost_serialization
wheelchair@wheelchair-laptop:~/playerstage/boostTest$ ./simple
myArray (toSave)
Displaying array2D (x,y) --> (2,2) as (n,visits,acc.x,acc.y)
(15,16,3,0) (17,18,3,0)
(0,0,3,0) (20,21,22,23)

myArray copy
Displaying array2D (x,y) --> (2,2) as (n,visits,acc.x,acc.y)
(15,16,3,0) (17,18,3,0)
(0,0,3,0) (20,21,22,23)

myArray2 (loaded)
Displaying array2D (x,y) --> (2,2) as (n,visits,acc.x,acc.y)
(15,16,3,0) (17,18,3,0)
(0,0,3,0) (20,21,22,23)

myArray (base)
Displaying array2D (x,y) --> (0,17) as (n,visits,acc.x,acc.y)

myArray copy
Displaying array2D (x,y) --> (0,15) as (n,visits,acc.x,acc.y)

myArray2
Displaying array2D (x,y) --> (2,2) as (n,visits,acc.x,acc.y)
(15,16,3,0) (17,18,3,0)
(0,0,3,0) (20,21,22,23)

end
Segmentation fault
wheelchair@wheelchair-laptop:~/playerstage/boostTest$
Messages postés
3829
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
8 janvier 2021
114
Je n'arrive pas à compiler ton exemple (Je pense que c'est de ma faute, j'ai une ancienne version de Boost, la 1.35, sachant que la 1.41 est sortie).

Néanmoins, as-tu essayé de ne pas utilisé de Cell** (pas terrible en C++), mais plutôt des collections de la STL (vector de Cell par exemple) ?
Sachant qu'il est possible des les sérialiser.
Voir, tout en bas, dernier chapitre:
http://www.boost.org/doc/libs/1_41_0/libs/serialization/doc/serialization.html

_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
6
Date d'inscription
jeudi 2 juillet 2009
Statut
Membre
Dernière intervention
18 janvier 2010

J'ai en effet penser a convertir mon tableau de Cell en un type plus "amical". Cependant étant donné que l'algorithme utilisant ces structures de donnée est bien complexe et fourni en code, je voulais essayer de preserver la strcuture de donnée tel quel afin d'éviter de reporter l'erreur plus loin ou de corriger tous les appels au tableau ...
Mais si je n'arrive pas a solutinner ce problème, je vais changer de structure pour un multi-array de la librairie boost je pense. ...

Merci encore d'avoir essayé !