comparison engine/core/pathfinder/routepather/routepather.cpp @ 190:f970f7dab2dd

Allow routepather to re-plan when the plan becomes invalid: - one of the steps in the plan is blocked - the target of the plan is changed
author icelus@33b003aa-7bff-0310-803a-e67f0ece8222
date Sat, 28 Feb 2009 12:15:04 +0000
parents 90005975cdbb
children 6362c6812580
comparison
equal deleted inserted replaced
189:3d0cc4545938 190:f970f7dab2dd
43 return; 43 return;
44 } 44 }
45 m_map = map; 45 m_map = map;
46 } 46 }
47 47
48 int RoutePather::getNextLocation(const Instance* instance, const Location& target, 48 int RoutePather::makeSessionId() {
49 double distance_to_travel, Location& nextLocation, 49 return m_nextFreeSessionId++;
50 Location& facingLocation, int session_id, int priority) { 50 }
51 assert(instance); 51
52 assert(instance->getLocation().getLayer() == target.getLayer()); 52 void RoutePather::makePlan(const Instance *instance, const Location& target, int session_id, int priority) {
53 if(session_id != -1) {
54 PathMap::iterator j = m_paths.find(session_id);
55 if(j != m_paths.end()) {
56 if(j->second.empty()) {
57 m_paths.erase(j);
58 return -1;
59 } else {
60 followPath(instance, j->second, distance_to_travel, nextLocation, facingLocation);
61 return session_id;
62 }
63 } else {
64 if(!sessionIdValid(session_id)) {
65 //Session id is invalid.
66 return -1;
67 }
68 }
69 return session_id;
70 }
71 SearchSpace* searchspace = getSearchSpace(target.getLayer()); 53 SearchSpace* searchspace = getSearchSpace(target.getLayer());
72 if(!searchspace) { 54 if(!searchspace) {
73 searchspace = new SearchSpace(target.getLayer()); 55 searchspace = new SearchSpace(target.getLayer());
74 addSearchSpace(searchspace); 56 addSearchSpace(searchspace);
75 } 57 }
76 if(searchspace->isInSearchSpace(target)) { 58 if(searchspace->isInSearchSpace(target)) {
77 session_id = m_nextFreeSessionId++;
78 RoutePatherSearch* newSearch = new RoutePatherSearch(session_id, instance->getLocation(), target, searchspace); 59 RoutePatherSearch* newSearch = new RoutePatherSearch(session_id, instance->getLocation(), target, searchspace);
79 m_sessions.pushElement(SessionQueue::value_type(newSearch, priority)); 60 m_sessions.pushElement(SessionQueue::value_type(newSearch, priority));
80 addSessionId(session_id); 61 addSessionId(session_id);
62 m_path_targets.insert(LocationMap::value_type(session_id,target));
63 }
64 }
65
66 bool RoutePather::locationsEqual(const Location &a, const Location &b) {
67
68 const ModelCoordinate a_coord = a.getLayerCoordinates();
69 const ModelCoordinate b_coord = b.getLayerCoordinates();
70
71 return a_coord == b_coord;
72 }
73
74 bool RoutePather::testStep(const Instance *instance, Path& path) {
75 Location instanceLoc = instance->getLocation();
76 if(!path.empty() &&
77 !locationsEqual(path.front(), instanceLoc) &&
78 instanceLoc.getLayer()->cellContainsBlockingInstance(path.front().getLayerCoordinates())) {
79 const bool last_step = path.front() == path.back();
80 path.clear();
81 return last_step;
82 }
83 return true;
84 }
85
86 int RoutePather::getNextLocation(const Instance* instance, const Location& target,
87 double distance_to_travel, Location& nextLocation,
88 Location& facingLocation, int session_id, int priority) {
89 assert(instance);
90 assert(instance->getLocation().getLayer() == target.getLayer());
91 bool plan_needed = true;
92
93 if(session_id != -1) {
94 plan_needed = false;
95 PathMap::iterator path_itor = m_paths.find(session_id);
96 if(path_itor != m_paths.end()) {
97 LocationMap::iterator location_itor = m_path_targets.find(session_id);
98 assert(location_itor != m_path_targets.end());
99
100 if(path_itor->second.empty()) {
101 m_paths.erase(path_itor);
102 m_path_targets.erase(location_itor);
103 return -1;
104 }
105
106 if(!followPath(instance, path_itor->second, distance_to_travel, nextLocation, facingLocation)
107 || !locationsEqual(location_itor->second, target)) {
108 m_paths.erase(path_itor);
109 m_path_targets.erase(location_itor);
110 plan_needed = true;
111 }
112 } else if(!sessionIdValid(session_id)) {
113 //Session id is invalid.
114 return -1;
115 }
116 }
117 if(plan_needed) {
118 if(session_id == -1) {
119 session_id = makeSessionId();
120 }
121 makePlan(instance, target, session_id, priority);
81 } 122 }
82 return session_id; 123 return session_id;
83 } 124 }
84 125
85 void RoutePather::update() { 126 void RoutePather::update() {
86 int ticksleft = m_maxticks; 127 int ticksleft = m_maxticks;
87 while(ticksleft >= 0) { 128 while(ticksleft >= 0) {
88 if(m_sessions.empty()) { 129 if(m_sessions.empty()) {
89 break; 130 break;
94 m_sessions.popElement(); 135 m_sessions.popElement();
95 continue; 136 continue;
96 } 137 }
97 priority_session->updateSearch(); 138 priority_session->updateSearch();
98 if(priority_session->getSearchStatus() == Search::search_status_complete) { 139 if(priority_session->getSearchStatus() == Search::search_status_complete) {
140 const int session_id = priority_session->getSessionId();
99 Path newPath = priority_session->calcPath(); 141 Path newPath = priority_session->calcPath();
100 m_paths.insert(PathMap::value_type(priority_session->getSessionId(), newPath)); 142 newPath.erase(newPath.begin());
101 invalidateSessionId(priority_session->getSessionId()); 143 m_paths.insert(PathMap::value_type(session_id, newPath));
144 invalidateSessionId(session_id);
102 delete priority_session; 145 delete priority_session;
103 m_sessions.popElement(); 146 m_sessions.popElement();
104 } else if(priority_session->getSearchStatus() == Search::search_status_failed) { 147 } else if(priority_session->getSearchStatus() == Search::search_status_failed) {
105 invalidateSessionId(priority_session->getSessionId()); 148 const int session_id = priority_session->getSessionId();
149 invalidateSessionId(session_id);
106 delete priority_session; 150 delete priority_session;
107 m_sessions.popElement(); 151 m_sessions.popElement();
108 } 152 }
109 --ticksleft; 153 --ticksleft;
110 } 154 }
111 } 155 }
112 156
113 void RoutePather::followPath(const Instance* instance, Path& path, double speed, Location& nextLocation, Location& facingLocation) { 157 bool RoutePather::followPath(const Instance* instance, Path& path, double speed, Location& nextLocation, Location& facingLocation) {
114 Location instanceLoc = instance->getLocation(); 158 Location instanceLoc = instance->getLocation();
159 if(!testStep(instance, path)) {
160 return false;
161 }
162
163 if(path.empty()) {
164 return true;
165 }
166
115 ExactModelCoordinate instancePos = instanceLoc.getMapCoordinates(); 167 ExactModelCoordinate instancePos = instanceLoc.getMapCoordinates();
116 ExactModelCoordinate facingPos = path.front().getMapCoordinates(); 168 ExactModelCoordinate facingPos = path.front().getMapCoordinates();
117 facingPos.x = facingPos.x + (facingPos.x - instancePos.x); 169 facingPos.x = facingPos.x + (facingPos.x - instancePos.x);
118 facingPos.y = facingPos.y + (facingPos.y - instancePos.y); 170 facingPos.y = facingPos.y + (facingPos.y - instancePos.y);
119 facingLocation = path.front(); 171 facingLocation = path.front();
126 bool pop = false; 178 bool pop = false;
127 if(speed > distance) { 179 if(speed > distance) {
128 speed = distance; 180 speed = distance;
129 pop = true; 181 pop = true;
130 } 182 }
131 if(distance != 0) 183 if(distance != 0) {
132 {
133 instancePos.x += (dx / distance) * speed; 184 instancePos.x += (dx / distance) * speed;
134 instancePos.y += (dy / distance) * speed; 185 instancePos.y += (dy / distance) * speed;
135
136 } else { 186 } else {
137 pop = true; 187 pop = true;
138 } 188 }
189
139 nextLocation.setMapCoordinates(instancePos); 190 nextLocation.setMapCoordinates(instancePos);
140 if(pop) 191 if(pop) {
141 {
142 path.pop_front(); 192 path.pop_front();
143 if(!path.empty() && instanceLoc.getLayer()->cellContainsBlockingInstance(path.front().getLayerCoordinates())) 193 if(!testStep(instance, path)) {
144 { 194 return false;
145 //TODO: Determine if we're close enough to stop, otherwise find alternate route. 195 }
146 path.clear(); 196 }
147 return; 197 return true;
148 }
149 }
150 } 198 }
151 199
152 bool RoutePather::cancelSession(const int session_id) { 200 bool RoutePather::cancelSession(const int session_id) {
153 if(session_id >= 0) { 201 if(session_id >= 0) {
154 PathMap::iterator i = m_paths.find(session_id); 202 PathMap::iterator i = m_paths.find(session_id);
155 if(i != m_paths.end()) { 203 if(i != m_paths.end()) {
204 LocationMap::iterator j = m_path_targets.find(session_id);
205 assert(j != m_path_targets.end());
156 m_paths.erase(i); 206 m_paths.erase(i);
207 m_path_targets.erase(j);
157 return true; 208 return true;
158 } else { 209 } else {
159 invalidateSessionId(session_id); 210 invalidateSessionId(session_id);
160 } 211 }
161 } 212 }
162 return false; 213 return false;
163 } 214 }
164 215
165 void RoutePather::addSessionId(const int sessionId) { 216 void RoutePather::addSessionId(const int sessionId) {
166 m_registeredSessionIds.push_back(sessionId); 217 m_registeredSessionIds.push_back(sessionId);
167 } 218 }
168 219
169 bool RoutePather::sessionIdValid(const int sessionId) { 220 bool RoutePather::sessionIdValid(const int sessionId) {
170 for(SessionList::const_iterator i = m_registeredSessionIds.begin(); 221 for(SessionList::const_iterator i = m_registeredSessionIds.begin();
171 i != m_registeredSessionIds.end(); 222 i != m_registeredSessionIds.end();
172 ++i) { 223 ++i) {
173 if((*i) == sessionId) { 224 if((*i) == sessionId) {
174 return true; 225 return true;
175 } 226 }
176 } 227 }
177 return false; 228 return false;
178 } 229 }
179 230
180 bool RoutePather::invalidateSessionId(const int sessionId) { 231 bool RoutePather::invalidateSessionId(const int sessionId) {
181 for(SessionList::iterator i = m_registeredSessionIds.begin(); 232 for(SessionList::iterator i = m_registeredSessionIds.begin();
182 i != m_registeredSessionIds.end(); 233 i != m_registeredSessionIds.end();
183 ++i) { 234 ++i) {
184 if((*i) == sessionId) { 235 if((*i) == sessionId) {
185 m_registeredSessionIds.erase(i); 236 m_registeredSessionIds.erase(i);
186 return true; 237 return true;
187 } 238 }
188 } 239 }
189 return false; 240 return false;
190 } 241 }
191 242
192 bool RoutePather::addSearchSpace(SearchSpace* search_space) { 243 bool RoutePather::addSearchSpace(SearchSpace* search_space) {
193 std::pair<SearchSpaceMap::iterator, bool> res = m_searchspaces.insert(SearchSpaceMap::value_type(search_space->getLayer(), search_space)); 244 std::pair<SearchSpaceMap::iterator, bool> res = m_searchspaces.insert(SearchSpaceMap::value_type(search_space->getLayer(), search_space));
194 245
195 return res.second; 246 return res.second;
196 } 247 }
197 248
198 SearchSpace* RoutePather::getSearchSpace(Layer * const layer) { 249 SearchSpace* RoutePather::getSearchSpace(Layer * const layer) {
199 SearchSpaceMap::iterator i = m_searchspaces.find(layer); 250 SearchSpaceMap::iterator i = m_searchspaces.find(layer);
200 if(i == m_searchspaces.end()) { 251 if(i == m_searchspaces.end()) {
201 return 0; 252 return 0;
202 } 253 }