[Positioning] Add InputDataReader & TopologyReaderCSV

InputDataReader handles all data input, i.e. data needed to prepare
computation (topology, calibration measurements, etc.).

TopologyReaderCSV reads topology from a CSV file (just Building and Area
for the moment).

cfg/topo.csv: change format (add building name and reorder coordinates).

UserInterface: add data input options.

posexcept: add data input exceptions.
This commit is contained in:
Matteo Cypriani 2010-04-02 15:49:22 +02:00
parent a30b08ac3c
commit 208c989c53
14 changed files with 376 additions and 36 deletions

View File

@ -57,6 +57,8 @@ OBJ_LIST = \
realposition.o \
configuration.o \
userinterface.o \
inputdatareader.o \
topologyreadercsv.o \
textfilereader.o \
csvfilereader.o \
textfilewriter.o \
@ -109,8 +111,19 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc $(SRC_DIR)/%.hh
$(LD) $(LDFLAGS) -o $@ $^
# Dependencies
$(OBJ_DIR)/owlps-positioning.o: \
$(OBJ_DIR)/userinterface.o \
$(OBJ_DIR)/inputdatareader.o \
$(OBJ_DIR)/stock.o \
$(OBJ_DIR)/positioning.o
$(OBJ_DIR)/userinterface.o: \
$(OBJ_DIR)/configuration.o
$(OBJ_DIR)/inputdatareader.o: \
$(OBJ_DIR)/topologyreadercsv.o \
$(OBJ_DIR)/configuration.o \
$(OBJ_DIR)/posexcept.o
$(OBJ_DIR)/topologyreadercsv.o: \
$(OBJ_DIR)/textfilereader.o
$(OBJ_DIR)/referencepoint.o: \
$(OBJ_DIR)/point3d.o
$(OBJ_DIR)/waypoint.o: \
@ -184,6 +197,7 @@ $(OBJ_DIR)/realposition.o: \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/referencepoint.o
$(OBJ_DIR)/positioning.o: \
$(OBJ_DIR)/inputdatareader.o \
$(OBJ_DIR)/input.o \
$(OBJ_DIR)/realposition.o \
$(OBJ_DIR)/output.o \

View File

@ -1,5 +1,6 @@
- Tests unitaires
° Finir le test de InputDataReader.
° Finir le test de Input.
° Finir le test de Output.
° Finir le test de Positioning.

View File

@ -1,48 +1,48 @@
# Liste des zones homogènes du bâtiment (pièces).
# Liste des bâtiments et de leurs zones homogènes (pièces).
# Chaque ligne définit une zone, de la forme :
# Nom de la pièce;X1;Y1;X2;Y2;Z1;Z2
# Nom du bâtiment;Nom de la pièce;X1;Y1;X2;Y2;Z1;Z2
### Rez-de-chaussée ###
#
0140;1.00;7.28;6.05;3.70;0.00;2.99
0130;1.00;10.88;6.05;7.28;0.00;2.99
0120;1.00;14.48;6.05;10.88;0.00;2.99
0110;1.00;18.12;6.05;14.48;0.00;2.99
0100;1.00;21.66;6.05;18.12;0.00;2.99
0090;1.00;25.32;6.05;21.66;0.00;2.99
0080;1.00;29.00;6.05;25.32;0.00;2.99
0070;1.00;32.00;6.05;29.00;0.00;2.99
WC N0;8.20;5.30;10.00;0.50;0.00;2.99
0085;8.20;9.00;10.00;5.30;0.00;2.99
0075;8.20;10.88;10.00;9.00;0.00;2.99
Palier N0;5.00;3.70;8.20;0.50;0.00;2.99
Couloir N0 A;6.05;30.00;8.20;3.70;0.00;2.99
Couloir N0 B;8.20;16.50;10.00;10.88;0.00;2.99
Couloir N0 C;8.20;24.80;10.00;22.60;0.00;2.99
Numerica;0140;1.00;7.28;6.05;3.70;0.00;2.99
Numerica;0130;1.00;10.88;6.05;7.28;0.00;2.99
Numerica;0120;1.00;14.48;6.05;10.88;0.00;2.99
Numerica;0110;1.00;18.12;6.05;14.48;0.00;2.99
Numerica;0100;1.00;21.66;6.05;18.12;0.00;2.99
Numerica;0090;1.00;25.32;6.05;21.66;0.00;2.99
Numerica;0080;1.00;29.00;6.05;25.32;0.00;2.99
Numerica;0070;1.00;32.00;6.05;29.00;0.00;2.99
Numerica;WC N0;8.20;5.30;10.00;0.50;0.00;2.99
Numerica;0085;8.20;9.00;10.00;5.30;0.00;2.99
Numerica;0075;8.20;10.88;10.00;9.00;0.00;2.99
Numerica;Palier N0;5.00;3.70;8.20;0.50;0.00;2.99
Numerica;Couloir N0 A;6.05;30.00;8.20;3.70;0.00;2.99
Numerica;Couloir N0 B;8.20;16.50;10.00;10.88;0.00;2.99
Numerica;Couloir N0 C;8.20;24.80;10.00;22.60;0.00;2.99
### Escaliers N0 / N1 ###
#
# TODO : affiner la hauteur, etc.
Escalier N0-N1 A;8.20;22.60;10.00;16.50;0.00;6.00
Escalier N0-N1 B1;2.50;2.00;5.00;0.50;0.00;6.00
Escalier N0-N1 B palier;1.00;3.70;2.50;0.50;1.50;6.00
Escalier N0-N1 B2;2.50;3.70;5.00;2.00;1.50;6.00
Numerica;Escalier N0-N1 A;8.20;22.60;10.00;16.50;0.00;6.00
Numerica;Escalier N0-N1 B1;2.50;2.00;5.00;0.50;0.00;6.00
Numerica;Escalier N0-N1 B palier;1.00;3.70;2.50;0.50;1.50;6.00
Numerica;Escalier N0-N1 B2;2.50;3.70;5.00;2.00;1.50;6.00
### Premier étage ###
#
1100;1.00;7.28;6.05;3.70;3.00;6.00
0190;1.00;10.88;6.05;7.28;3.00;6.00
0180;1.00;14.48;6.05;10.88;3.00;6.00
1070;1.00;18.12;6.05;14.48;3.00;6.00
1060;1.00;25.32;6.05;18.12;3.00;6.00
1050;1.00;31.40;6.05;25.32;3.00;6.00
WC N1;8.20;9.00;10.00;0.50;3.00;6.00
1105;8.20;10.88;10.00;9.00;3.00;6.00
1095;8.20;29.30;10.00;24.80;3.00;6.00
Palier N1;5.00;3.70;8.20;0.50;3.00;6.00
Couloir N1 A;6.05;29.50;8.20;3.70;3.00;6.00
Couloir N1 B;8.20;16.50;10.00;10.88;3.00;6.00
Couloir N1 C;8.20;24.80;10.00;22.60;3.00;6.00
Numerica;1100;1.00;7.28;6.05;3.70;3.00;6.00
Numerica;0190;1.00;10.88;6.05;7.28;3.00;6.00
Numerica;0180;1.00;14.48;6.05;10.88;3.00;6.00
Numerica;1070;1.00;18.12;6.05;14.48;3.00;6.00
Numerica;1060;1.00;25.32;6.05;18.12;3.00;6.00
Numerica;1050;1.00;31.40;6.05;25.32;3.00;6.00
Numerica;WC N1;8.20;9.00;10.00;0.50;3.00;6.00
Numerica;1105;8.20;10.88;10.00;9.00;3.00;6.00
Numerica;1095;8.20;29.30;10.00;24.80;3.00;6.00
Numerica;Palier N1;5.00;3.70;8.20;0.50;3.00;6.00
Numerica;Couloir N1 A;6.05;29.50;8.20;3.70;3.00;6.00
Numerica;Couloir N1 B;8.20;16.50;10.00;10.88;3.00;6.00
Numerica;Couloir N1 C;8.20;24.80;10.00;22.60;3.00;6.00

1 # Liste des zones homogènes du bâtiment (pièces). # Liste des bâtiments et de leurs zones homogènes (pièces).
2 # Chaque ligne définit une zone, de la forme : # Chaque ligne définit une zone, de la forme :
3 # Nom de la pièce;X1;Y1;X2;Y2;Z1;Z2 # Nom du bâtiment;Nom de la pièce;X1;Y1;X2;Y2;Z1;Z2
4 ### Rez-de-chaussée ### ### Rez-de-chaussée ###
5 # #
6 0140;1.00;7.28;6.05;3.70;0.00;2.99 Numerica;0140;1.00;7.28;6.05;3.70;0.00;2.99
7 0130;1.00;10.88;6.05;7.28;0.00;2.99 Numerica;0130;1.00;10.88;6.05;7.28;0.00;2.99
8 0120;1.00;14.48;6.05;10.88;0.00;2.99 Numerica;0120;1.00;14.48;6.05;10.88;0.00;2.99
9 0110;1.00;18.12;6.05;14.48;0.00;2.99 Numerica;0110;1.00;18.12;6.05;14.48;0.00;2.99
10 0100;1.00;21.66;6.05;18.12;0.00;2.99 Numerica;0100;1.00;21.66;6.05;18.12;0.00;2.99
11 0090;1.00;25.32;6.05;21.66;0.00;2.99 Numerica;0090;1.00;25.32;6.05;21.66;0.00;2.99
12 0080;1.00;29.00;6.05;25.32;0.00;2.99 Numerica;0080;1.00;29.00;6.05;25.32;0.00;2.99
13 0070;1.00;32.00;6.05;29.00;0.00;2.99 Numerica;0070;1.00;32.00;6.05;29.00;0.00;2.99
14 WC N0;8.20;5.30;10.00;0.50;0.00;2.99 Numerica;WC N0;8.20;5.30;10.00;0.50;0.00;2.99
15 0085;8.20;9.00;10.00;5.30;0.00;2.99 Numerica;0085;8.20;9.00;10.00;5.30;0.00;2.99
16 0075;8.20;10.88;10.00;9.00;0.00;2.99 Numerica;0075;8.20;10.88;10.00;9.00;0.00;2.99
17 Palier N0;5.00;3.70;8.20;0.50;0.00;2.99 Numerica;Palier N0;5.00;3.70;8.20;0.50;0.00;2.99
18 Couloir N0 A;6.05;30.00;8.20;3.70;0.00;2.99 Numerica;Couloir N0 A;6.05;30.00;8.20;3.70;0.00;2.99
19 Couloir N0 B;8.20;16.50;10.00;10.88;0.00;2.99 Numerica;Couloir N0 B;8.20;16.50;10.00;10.88;0.00;2.99
20 Couloir N0 C;8.20;24.80;10.00;22.60;0.00;2.99 Numerica;Couloir N0 C;8.20;24.80;10.00;22.60;0.00;2.99
21 ### Escaliers N0 / N1 ### ### Escaliers N0 / N1 ###
22 # #
23 # TODO : affiner la hauteur, etc. # TODO : affiner la hauteur, etc.
24 Escalier N0-N1 A;8.20;22.60;10.00;16.50;0.00;6.00 Numerica;Escalier N0-N1 A;8.20;22.60;10.00;16.50;0.00;6.00
25 Escalier N0-N1 B1;2.50;2.00;5.00;0.50;0.00;6.00 Numerica;Escalier N0-N1 B1;2.50;2.00;5.00;0.50;0.00;6.00
26 Escalier N0-N1 B palier;1.00;3.70;2.50;0.50;1.50;6.00 Numerica;Escalier N0-N1 B palier;1.00;3.70;2.50;0.50;1.50;6.00
27 Escalier N0-N1 B2;2.50;3.70;5.00;2.00;1.50;6.00 Numerica;Escalier N0-N1 B2;2.50;3.70;5.00;2.00;1.50;6.00
28 ### Premier étage ### ### Premier étage ###
29 # #
30 1100;1.00;7.28;6.05;3.70;3.00;6.00 Numerica;1100;1.00;7.28;6.05;3.70;3.00;6.00
31 0190;1.00;10.88;6.05;7.28;3.00;6.00 Numerica;0190;1.00;10.88;6.05;7.28;3.00;6.00
32 0180;1.00;14.48;6.05;10.88;3.00;6.00 Numerica;0180;1.00;14.48;6.05;10.88;3.00;6.00
33 1070;1.00;18.12;6.05;14.48;3.00;6.00 Numerica;1070;1.00;18.12;6.05;14.48;3.00;6.00
34 1060;1.00;25.32;6.05;18.12;3.00;6.00 Numerica;1060;1.00;25.32;6.05;18.12;3.00;6.00
35 1050;1.00;31.40;6.05;25.32;3.00;6.00 Numerica;1050;1.00;31.40;6.05;25.32;3.00;6.00
36 WC N1;8.20;9.00;10.00;0.50;3.00;6.00 Numerica;WC N1;8.20;9.00;10.00;0.50;3.00;6.00
37 1105;8.20;10.88;10.00;9.00;3.00;6.00 Numerica;1105;8.20;10.88;10.00;9.00;3.00;6.00
38 1095;8.20;29.30;10.00;24.80;3.00;6.00 Numerica;1095;8.20;29.30;10.00;24.80;3.00;6.00
39 Palier N1;5.00;3.70;8.20;0.50;3.00;6.00 Numerica;Palier N1;5.00;3.70;8.20;0.50;3.00;6.00
40 Couloir N1 A;6.05;29.50;8.20;3.70;3.00;6.00 Numerica;Couloir N1 A;6.05;29.50;8.20;3.70;3.00;6.00
41 Couloir N1 B;8.20;16.50;10.00;10.88;3.00;6.00 Numerica;Couloir N1 B;8.20;16.50;10.00;10.88;3.00;6.00
42 Couloir N1 C;8.20;24.80;10.00;22.60;3.00;6.00 Numerica;Couloir N1 C;8.20;24.80;10.00;22.60;3.00;6.00
43
44
45
46
47
48

View File

@ -0,0 +1,50 @@
#include "inputdatareader.hh"
#include "configuration.hh"
#include "posexcept.hh"
#include "topologyreadercsv.hh"
using namespace std ;
/* *** Constructors *** */
InputDataReader::InputDataReader()
{
initialise_topology_media() ;
}
/* *** Operations *** */
void InputDataReader::initialise_topology_media()
{
if (! Configuration::is_configured("data-input.topology-medium"))
return ;
const vector<string> &media_names =
Configuration::string_vector_value("data-input.topology-medium") ;
for (vector<string>::const_iterator i = media_names.begin() ;
i != media_names.end() ; ++i)
{
if (*i == "CSV")
initialise_topology_csv() ;
else
throw topology_input_medium_type_unknown(*i) ;
}
}
void InputDataReader::initialise_topology_csv()
{
if (! Configuration::is_configured("data-input.areas-csv-file"))
throw no_topology_input_csv_file() ;
TopologyReaderCSV(
Configuration::string_value("data-input.areas-csv-file")) ;
}

View File

@ -0,0 +1,17 @@
#ifndef _OWLPS_POSITIONING_INPUTDATAREADER_HH_
#define _OWLPS_POSITIONING_INPUTDATAREADER_HH_
/// Read input data using parameters in Configuration
class InputDataReader
{
protected:
void initialise_topology_media(void) ;
void initialise_topology_csv(void) ;
public:
InputDataReader(void) ;
~InputDataReader(void) {}
} ;
#endif // _OWLPS_POSITIONING_INPUTDATAREADER_HH_

View File

@ -1,12 +1,13 @@
#include "userinterface.hh"
#include "inputdatareader.hh"
#include "stock.hh"
#include "positioning.hh"
int main(int argc, char **argv)
{
UserInterface *ui = new UserInterface(argc, argv) ;
delete ui ; // We don't need it any more
delete new UserInterface(argc, argv) ;
delete new InputDataReader() ;
Positioning positioning ;

View File

@ -24,6 +24,26 @@ element_not_found(const string &_explanation) throw():
/* *** Data input *** */
topology_input_medium_type_unknown::
topology_input_medium_type_unknown(const string &medium_name) throw():
posexcept("The specified topology input medium « "+ medium_name +
" » is unknown!") {}
no_topology_input_csv_file::no_topology_input_csv_file() throw():
posexcept(
"No topologyinput CSV file specified in the configuration!") {}
malformed_topology::
malformed_topology(const string &_explanation) throw():
posexcept("Error reading the topology:" + _explanation) {}
/* *** Input *** */

View File

@ -44,6 +44,32 @@ public:
/* *** Data input *** */
class topology_input_medium_type_unknown: public posexcept
{
public:
topology_input_medium_type_unknown(
const std::string &medium_name) throw() ;
} ;
class no_topology_input_csv_file: public posexcept
{
public:
no_topology_input_csv_file(void) throw() ;
} ;
class malformed_topology: public posexcept
{
public:
malformed_topology(const std::string &_explanation) throw() ;
} ;
/* *** Input *** */

View File

@ -0,0 +1,60 @@
#include "topologyreadercsv.hh"
#include "posexcept.hh"
#include "stock.hh"
#include "point3d.hh"
#include "area.hh"
using namespace std ;
/* *** Constructors *** */
TopologyReaderCSV::TopologyReaderCSV(const string &filename):
file(filename)
{
read_topology() ;
}
/* *** Operations *** */
void TopologyReaderCSV::read_topology()
{
while (file.next_line())
process_line() ;
}
void TopologyReaderCSV::process_line()
{
string building_name ;
if (! file.read_field(building_name))
throw malformed_topology("Cannot read building name!") ;
Building &building = const_cast<Building&>(
Stock::find_create_building(building_name)) ;
string name ;
if (! file.read_field(name))
throw malformed_topology("Cannot read area name!") ;
Point3D p_min(read_point()) ;
Point3D p_max(read_point()) ;
Area *area = new Area(&building, name, p_min, p_max) ;
building.add_area(area) ;
}
Point3D TopologyReaderCSV::read_point()
{
float coord[3] ;
for (unsigned int i = 0 ; i < 3 ; ++i)
if (! file.read_field(coord[i]))
throw malformed_topology("Cannot read a whole Point3D!") ;
return Point3D(coord) ;
}

View File

@ -0,0 +1,30 @@
#ifndef _OWLPS_POSITIONING_TOPOLOGYREADERCSV_HH_
#define _OWLPS_POSITIONING_TOPOLOGYREADERCSV_HH_
class Point3D ;
#include "csvfilereader.hh"
#include <string>
/// Reads and registers to the Stock an Area list from a CSV file
/**
* CSV format is:
* Building name;Room name;X1;Y1;Z1;X2;Y2;Z2
*/
class TopologyReaderCSV
{
protected:
CSVFileReader file ;
void read_topology(void) ;
void process_line(void) ;
Point3D read_point(void) ;
public:
TopologyReaderCSV(const std::string &filename) ;
~TopologyReaderCSV(void) {}
} ;
#endif // _OWLPS_POSITIONING_TOPOLOGYREADERCSV_HH_

View File

@ -82,6 +82,7 @@ void UserInterface::fill_cli_options()
void UserInterface::fill_file_options()
{
fill_server_options() ;
fill_data_input_options() ;
fill_input_options() ;
fill_log_options() ;
fill_positioning_options() ;
@ -103,6 +104,27 @@ void UserInterface::fill_server_options()
}
void UserInterface::fill_data_input_options()
{
po::options_description options("Data input options") ;
options.add_options()
("data-input.topology-medium,T", po::value< vector<string> >()
->composing(),
"Medium from which topology (buildings, areas and waypoints) is \
read. You can specify this option more than once. Allowed: CSV.")
("data-input.areas-csv-file,A", po::value<string>(),
"CSV file to use for topology input (when \
data-input.topology-medium = CSV).")
("data-input.waypoints-csv-file,W", po::value<string>(),
"CSV file to use for waypoints input (when \
data-input.topology-medium = CSV).")
;
file_options->add(options) ;
}
void UserInterface::fill_input_options()
{
po::options_description options("Input options") ;

View File

@ -25,6 +25,7 @@ protected:
/// the configuration file
void fill_file_options(void) ;
void fill_server_options(void) ;
void fill_data_input_options(void) ;
void fill_input_options(void) ;
void fill_log_options(void) ;
void fill_positioning_options(void) ;

View File

@ -0,0 +1,15 @@
#include <cxxtest/TestSuite.h>
#include "inputdatareader.hh"
class InputDataReader_test: public CxxTest::TestSuite
{
public:
void test_constructor(void)
{
// TODO: test with a mock Configuration?
InputDataReader inputdatareader1 ;
}
} ;

View File

@ -0,0 +1,83 @@
#include <cxxtest/TestSuite.h>
#include "topologyreadercsv.hh"
class TopologyReaderCSV_test: public CxxTest::TestSuite
{
private:
std::string topology_file_name ;
public:
TopologyReaderCSV_test(void):
topology_file_name("/tmp/TopologyReaderCSV_topology_file.csv")
{
Stock::clear() ;
std::ofstream topology_file(topology_file_name.c_str()) ;
topology_file
<< "My building;My room #1;1;2;3;9;8;7\n"
<< "My building;Room #2;4;5;6;6;5;4\n"
<< "Building #2;My room #1;1;2;3;9;8;7\n"
<< "My building;Room #2;4;5;6;6;5;4\n"
<< "My building;Room #2;4;5;6;6;5;4\n" ;
topology_file.close() ;
}
~TopologyReaderCSV_test(void)
{
Stock::clear() ;
TestUtil::remove_file(topology_file_name) ;
}
static TopologyReaderCSV_test* createSuite(void)
{
return new TopologyReaderCSV_test() ;
}
static void destroySuite(TopologyReaderCSV_test *suite)
{
delete suite ;
}
void test_topologyreadercsv(void)
{
TS_ASSERT_THROWS_NOTHING(
TopologyReaderCSV toporeader(topology_file_name)) ;
Building *building1 ;
TS_ASSERT_THROWS_NOTHING(
building1 = const_cast<Building*>(
&Stock::get_building("My building"))) ;
Building *building2 ;
TS_ASSERT_THROWS_NOTHING(
building2 = const_cast<Building*>(
&Stock::get_building("Building #2"))) ;
TS_ASSERT_EQUALS(building1->get_areas().size(), 2u) ;
Area *area_ptr ;
area_ptr = building1->get_areas().find("My room #1")->second ;
Area area1(building1, "My room #1",
Point3D(1,2,3), Point3D(9,8,7)) ;
assert(area_ptr) ;
TS_ASSERT_EQUALS(*area_ptr, area1) ;
area_ptr = building1->get_areas().find("Room #2")->second ;
assert(area_ptr) ;
Area area2(building1, "Room #2",
Point3D(4,5,6), Point3D(6,5,4)) ;
TS_ASSERT_EQUALS(*area_ptr, area2) ;
TS_ASSERT_EQUALS(building2->get_areas().size(), 1u) ;
area1.set_building(building2) ;
area_ptr = building2->get_areas().find("My room #1")->second ;
assert(area_ptr) ;
TS_ASSERT_EQUALS(*area_ptr, area1) ;
}
} ;