Update, seems to work!
[mtp.git] / tracker.cc
1
2 ///////////////////////////////////////////////////////////////////////////
3 // This program is free software: you can redistribute it and/or modify  //
4 // it under the terms of the version 3 of the GNU General Public License //
5 // as published by the Free Software Foundation.                         //
6 //                                                                       //
7 // This program is distributed in the hope that it will be useful, but   //
8 // WITHOUT ANY WARRANTY; without even the implied warranty of            //
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
10 // General Public License for more details.                              //
11 //                                                                       //
12 // You should have received a copy of the GNU General Public License     //
13 // along with this program. If not, see <http://www.gnu.org/licenses/>.  //
14 //                                                                       //
15 // Written by and Copyright (C) Francois Fleuret                         //
16 // Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
17 ///////////////////////////////////////////////////////////////////////////
18
19 #include "tracker.h"
20
21 #include <iostream>
22
23 using namespace std;
24
25 Tracker::Tracker(int nb_time_steps, int nb_locations) {
26   _nb_locations = nb_locations;
27   _nb_time_steps = nb_time_steps;
28   _detection_score = allocate_array<scalar_t>(nb_time_steps, nb_locations);
29   _allowed_motion = allocate_array<int>(nb_locations, nb_locations);
30   for(int l = 0; l < nb_locations; l++) {
31     for(int m = 0; m < nb_locations; m++) {
32       _allowed_motion[l][m] = 0;
33     }
34   }
35
36   _edge_lengths = 0;
37   _graph = 0;
38 }
39
40 Tracker::~Tracker() {
41   delete[] _edge_lengths;
42   delete _graph;
43   deallocate_array<scalar_t>(_detection_score);
44   deallocate_array<int>(_allowed_motion);
45 }
46
47 void Tracker::set_allowed_motion(int from_location, int to_location, int v) {
48   _allowed_motion[from_location][to_location] = v;
49 }
50
51 void Tracker::set_detection_score(int time, int location, scalar_t score) {
52   _detection_score[time][location] = score;
53 }
54
55 void Tracker::build_graph() {
56
57   // Delete existing graph
58   delete[] _edge_lengths;
59   delete _graph;
60
61   int nb_motions = 0;
62   for(int l = 0; l < _nb_locations; l++) {
63     for(int m = 0; m < _nb_locations; m++) {
64       if(_allowed_motion[l][m]) nb_motions++;
65     }
66   }
67
68   int nb_vertices = 2 + 2 * _nb_time_steps * _nb_locations;
69   int nb_edges = _nb_locations * 2
70     + (_nb_time_steps - 1) * nb_motions
71     + _nb_locations * _nb_time_steps;
72
73   int source = 0, sink = nb_vertices - 1;
74   int *node_from = new int[nb_edges];
75   int *node_to = new int[nb_edges];
76   int e = 0;
77
78   _edge_lengths = new scalar_t[nb_edges];
79
80   // We put the in-node edges first, since these are the ones whose
81   // lengths we will have to change according to the detection score
82
83   for(int t = 0; t < _nb_time_steps; t++) {
84     for(int l = 0; l < _nb_locations; l++) {
85       node_from[e] = 1 + (2 * (t + 0) + 0) * _nb_locations + l;
86       node_to[e] =   1 + (2 * (t + 0) + 1) * _nb_locations + l;
87       e++;
88     }
89   }
90
91   // We put the other edges after
92
93   for(int l = 0; l < _nb_locations; l++) {
94     node_from[e] = source;
95     node_to[e] = 1 + l + 0 * _nb_locations;
96     _edge_lengths[e] = 0.0;
97     e++;
98   }
99
100   for(int t = 0; t < _nb_time_steps; t++) {
101     for(int l = 0; l < _nb_locations; l++) {
102       if(t == _nb_time_steps - 1) {
103         node_from[e] = 1 + (2 * (t + 0) + 1) * _nb_locations + l;
104         node_to[e] = sink;
105         _edge_lengths[e] = 0.0;
106         e++;
107       } else {
108         for(int k = 0; k < _nb_locations; k++) {
109           if(_allowed_motion[l][k]) {
110             node_from[e] = 1 + (2 * (t + 0) + 1) * _nb_locations + l;
111             node_to[e] =   1 + (2 * (t + 1) + 0) * _nb_locations + k;
112             _edge_lengths[e] = 0.0;
113             e++;
114           }
115         }
116       }
117     }
118   }
119
120   _graph = new MTPGraph(nb_vertices, nb_edges,
121                         node_from, node_to,
122                         source, sink);
123
124   delete[] node_from;
125   delete[] node_to;
126 }
127
128 void Tracker::track() {
129   int e = 0;
130   for(int t = 0; t < _nb_time_steps; t++) {
131     for(int l = 0; l < _nb_locations; l++) {
132       _edge_lengths[e] = - _detection_score[t][l];
133       e++;
134     }
135   }
136
137   _graph->find_best_paths(_edge_lengths);
138   _graph->retrieve_disjoint_paths();
139
140   for(int p = 0; p < _graph->nb_paths; p++) {
141     Path *path = _graph->paths[p];
142     cout << "PATH " << p << " [length " << path->length << "] " << path->nodes[0];
143     for(int n = 1; n < path->length; n++) {
144       cout << " -> " << path->nodes[n];
145     }
146     cout << endl;
147   }
148   // _graph->print_dot();
149 }
150
151 int Tracker::nb_trajectories() {
152   return _graph->nb_paths;
153 }
154
155 int Tracker::trajectory_duration(int k) {
156   return (_graph->paths[k]->length - 2) / 2;
157 }
158
159 int Tracker::trajectory_location(int k, int time) {
160   return (_graph->paths[k]->nodes[2 * time + 1] - 1) % _nb_locations;
161 }