From: Mikko Rasa Date: Tue, 2 Nov 2010 21:35:26 +0000 (+0000) Subject: Clear end_of_route if we have to free blocks from the end X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=f054840cec26b55d68910e750192079f0c6e0230;p=r2c2.git Clear end_of_route if we have to free blocks from the end Drop the return value of reserve_more as it's not useful anymore simplify the logic of keeping good blocks Don't keep any turnouts at the end of reservation Fix a bug where a blocks could be current but not clear Always set turnouts according to reserved blocks Handle instant turnout switches correctly --- diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index 7030f38..e4afef7 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -513,7 +513,6 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) if(!active && stop_timeout && t>=stop_timeout) { release_blocks(cur_blocks_end, blocks.end()); - end_of_route = false; stop_timeout = Time::TimeStamp(); } @@ -783,13 +782,8 @@ void Train::sensor_event(unsigned addr, bool state) void Train::turnout_path_changed(Track &track) { for(list::iterator i=blocks.begin(); i!=blocks.end(); ++i) - if((*i)->get_turnout_id()==track.get_turnout_id()) - { - if(!reserving) - check_turnout_paths(false); - else if(i==clear_blocks_end) - ++clear_blocks_end; - } + if((*i)->get_turnout_id()==track.get_turnout_id() && !reserving) + check_turnout_paths(false); } void Train::halt_event(bool h) @@ -804,10 +798,10 @@ void Train::block_reserved(const Block &block, const Train *train) reserve_more(); } -unsigned Train::reserve_more() +void Train::reserve_more() { - if(!active || blocks.empty()) - return 0; + if(!active || blocks.empty() || end_of_route) + return; BlockIter start = blocks.back(); @@ -823,9 +817,6 @@ unsigned Train::reserve_more() if(nsens>0) dist += (*i)->get_path_length(i->entry()); } - - if(end_of_route) - return nsens; list::iterator cur_route = routes.begin(); advance_route(cur_route, *start.track_iter()); @@ -837,19 +828,21 @@ unsigned Train::reserve_more() list::iterator good_end = blocks.end(); Track *divert_track = 0; bool try_divert = false; - unsigned good_sens = nsens; - float good_dist = dist; Train *blocking_train = 0; BlockList contested_blocks; SetFlag setf(reserving); - while(good_sens<3 || good_distroute : 0); - if(!block) + if(!block || block->get_endpoints().size()<2) + { + if(!blocking_train) + good_end = blocks.end(); break; + } TrackIter track = block.track_iter(); @@ -861,25 +854,20 @@ unsigned Train::reserve_more() if(!blocking_train) { good_end = blocks.end(); - good_sens = nsens; - good_dist = dist; end_of_route = true; } break; } } - else if(!routes.empty() && routes.front().route->has_track(*track)) - cur_route = routes.begin(); - if(block->get_endpoints().size()<2) + if(block->get_turnout_id() && !last->get_turnout_id()) { - if(!blocking_train) - { - good_end = blocks.end(); - good_sens = nsens; - good_dist = dist; - } - break; + /* We can keep the blocks if we arrive at a turnout from a non-turnout + block. Having a turnout block as our last reserved block is not good + as it would limit our diversion possibilities for little benefit. */ + good_end = blocks.end(); + if(nsens>=3 && dist>=min_dist) + break; } if(blocking_train) @@ -929,13 +917,9 @@ unsigned Train::reserve_more() bool entry_conflict = (block.entry()==other_exit); bool exit_conflict = (exit==static_cast(other_entry)); if(!entry_conflict && !last->get_turnout_id()) - { /* The other train is not coming to the blocks we're holding, so we can keep them. */ good_end = blocks.end(); - good_sens = nsens; - good_dist = dist; - } int other_prio = other_train->get_priority(); @@ -971,17 +955,6 @@ unsigned Train::reserve_more() const TrackType::Endpoint &track_ep = track->get_type().get_endpoints()[track.entry()]; bool multiple_paths = (track_ep.paths&(track_ep.paths-1)); - if(multiple_paths || !last->get_turnout_id()) - { - /* We can keep the blocks reserved so far if we are facing the - points or if there was no turnout immediately before this one. - With multiple successive turnouts (as is common in crossovers) it's - best to hold at one we can divert from. */ - good_end = blocks.end(); - good_sens = nsens; - good_dist = dist; - } - if(multiple_paths && cur_route!=routes.end() && cur_route->diversion!=block->get_turnout_id()) /* There's multiple paths to be taken and we are on a route - take note of the diversion possibility */ @@ -1016,13 +989,11 @@ unsigned Train::reserve_more() check_turnout_paths(true); // Make any sensorless blocks at the beginning immediately current - while(cur_blocks_end!=blocks.end() && !(*cur_blocks_end)->get_sensor_id()) + while(cur_blocks_end!=clear_blocks_end && !(*cur_blocks_end)->get_sensor_id()) ++cur_blocks_end; if(try_divert && divert(*divert_track)) - return reserve_more(); - - return good_sens; + reserve_more(); } void Train::check_turnout_paths(bool set) @@ -1030,41 +1001,33 @@ void Train::check_turnout_paths(bool set) if(clear_blocks_end==blocks.end()) return; - list::iterator route = routes.begin(); - for(list::iterator i=clear_blocks_end; i!=blocks.end(); ++i) { - advance_route(route, *i->track_iter()); - if((*i)->get_turnout_id()) { TrackIter track = i->track_iter(); const TrackType::Endpoint &track_ep = track->get_type().get_endpoints()[track.entry()]; - int path = -1; - for(list::iterator j=route; (path<0 && j!=routes.end()); ++j) - path = j->route->get_turnout((*i)->get_turnout_id()); - if(path<0) - path = track->get_active_path(); - if(!(track_ep.paths&(1<::iterator j = i; + if(++j!=blocks.end()) { - list::iterator j = i; - if(++j!=blocks.end()) - { - TrackIter rev = j->track_iter().flip(); - unsigned mask = rev->get_type().get_endpoints()[rev.entry()].paths&track_ep.paths; - for(path=0; mask>1; mask>>=1, ++path) ; - } - else - return; + TrackIter rev = j->track_iter().flip(); + unsigned mask = rev->get_type().get_endpoints()[rev.entry()].paths&track_ep.paths; + for(path=0; mask>1; mask>>=1, ++path) ; } + else + return; - if(path!=static_cast(track->get_active_path())) + if(path!=track->get_active_path()) { if(set) track->set_active_path(path); - continue; + /* Check again, in case the driver was able to service the request + instantly */ + if(!set || path!=track->get_active_path()) + continue; } } @@ -1222,6 +1185,9 @@ void Train::release_blocks(BlockList::iterator begin, BlockList::iterator end) Block &block = **begin; blocks.erase(begin++); block.reserve(0); + + if(begin==blocks.end()) + end_of_route = false; } } diff --git a/source/libmarklin/train.h b/source/libmarklin/train.h index 87fd4a5..5f85256 100644 --- a/source/libmarklin/train.h +++ b/source/libmarklin/train.h @@ -161,7 +161,7 @@ private: void turnout_path_changed(Track &); void halt_event(bool); void block_reserved(const Block &, const Train *); - unsigned reserve_more(); + void reserve_more(); void check_turnout_paths(bool); float get_reserved_distance_until(const Block *, bool) const; float get_real_speed(unsigned) const;