From: Mikko Rasa Date: Mon, 4 Oct 2010 19:59:30 +0000 (+0000) Subject: Create a more generic version of Train::get_reserved_distance X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=cc0ee0a5e71590960bc8cb7baee7a10ef09ce3f0;p=r2c2.git Create a more generic version of Train::get_reserved_distance Use it to determine if a trailing non-sensor block can be freed Don't release blocks if there's not enough distance for stopping Reserve enough blocks to maintain speed --- diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index 0c1748a..acf8aa5 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -299,6 +299,10 @@ void Train::place(Block &block, unsigned entry) bool Train::free_block(Block &block) { + float margin = 10*layout.get_catalogue().get_scale(); + if(get_reserved_distance_until(&block, false)get_braking_distance()*1.3+margin) + return false; + unsigned nsens = 0; for(list::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) { @@ -329,52 +333,7 @@ int Train::get_entry_to_block(Block &block) const float Train::get_reserved_distance() const { - if(cur_blocks.empty()) - return 0; - - Vehicle &veh = *(reverse ? vehicles.back() : vehicles.front()); - const VehicleType &vtype = veh.get_type(); - - Track *track = veh.get_track(); - if(!track) - return 0; - unsigned entry = veh.get_entry(); - - float result = -vtype.get_length()/2; - if(reverse) - { - entry = track->traverse(entry); - result += veh.get_offset(); - } - else - result -= veh.get_offset(); - - bool first = true; - list::const_iterator block = cur_blocks.begin(); - while(1) - { - if(!first || !reverse) - result += track->get_type().get_path_length(track->get_active_path()); - first = false; - - if(track->get_type().get_endpoints().size()<2) - return result; - - unsigned exit = track->traverse(entry); - Track *next = track->get_link(exit); - - while(!block->block->get_tracks().count(next)) - { - ++block; - if(block==cur_blocks.end()) - block = rsv_blocks.begin(); - if(block==rsv_blocks.end()) - return result; - } - - entry = next->get_endpoint_by_link(*track); - track = next; - } + return get_reserved_distance_until(0, false); } void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) @@ -453,47 +412,9 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) if(!cur_blocks.empty() && !cur_blocks.front().block->get_sensor_id()) { - Vehicle &veh = *(reverse ? vehicles.front() : vehicles.back()); - - list::iterator i = cur_blocks.begin(); - const Block::Endpoint &bep = i->block->get_endpoints()[i->entry]; - - Track *track = bep.track; - unsigned entry = bep.track_ep; - - bool found = false; - float dist = veh.get_offset(); - if(reverse) - dist = veh.get_track()->get_type().get_path_length(veh.get_track()->get_active_path())-dist; - dist -= veh.get_type().get_length()/2; - while(1) - { - if(track==veh.get_track()) - { - found = true; - break; - } - - if(i!=cur_blocks.begin()) - { - float path_len = track->get_type().get_path_length(track->get_active_path()); - dist += path_len; - } - - unsigned exit = track->traverse(entry); - Track *next = track->get_link(exit); - entry = next->get_endpoint_by_link(*track); - track = next; - - if(!i->block->get_tracks().count(track)) - { - ++i; - if(i==cur_blocks.end()) - break; - } - } + float dist = get_reserved_distance_until(cur_blocks.front().block, true); - if(found && i!=cur_blocks.begin() && dist>10*layout.get_catalogue().get_scale()) + if(dist>10*layout.get_catalogue().get_scale()) { cur_blocks.front().block->reserve(0); cur_blocks.erase(cur_blocks.begin()); @@ -727,11 +648,20 @@ unsigned Train::reserve_more() pending_block = 0; - // See how many sensor blocks we already have + // See how many sensor blocks and how much track we already have unsigned nsens = 0; + float dist = 0; for(list::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + { if(i->block->get_sensor_id()) ++nsens; + if(nsens>0) + { + float length = 0; + i->block->traverse(i->entry, &length); + dist += length; + } + } if(end_of_route) return nsens; @@ -749,17 +679,23 @@ unsigned Train::reserve_more() } } - SetFlag setf(reserving); + float approach_margin = 50*layout.get_catalogue().get_scale(); + float min_dist = controller->get_braking_distance()*1.3+approach_margin*2; BlockRef *last = start; BlockRef *good = start; unsigned good_sens = nsens; + float good_dist = dist; Train *blocking_train = 0; std::list contested_blocks; - while(good_sens<3 || !contested_blocks.empty()) + + SetFlag setf(reserving); + + while(good_sens<3 || good_distblock->traverse(last->entry, cur_route); + float length = 0; + unsigned exit = last->block->traverse(last->entry, cur_route, &length); Block *link = last->block->get_link(exit); if(!link) break; @@ -781,6 +717,7 @@ unsigned Train::reserve_more() { good = last; good_sens = nsens; + good_dist = dist; end_of_route = true; } break; @@ -795,6 +732,7 @@ unsigned Train::reserve_more() { good = last; good_sens = nsens; + good_dist = dist; } break; } @@ -849,6 +787,7 @@ unsigned Train::reserve_more() other train to pass */ good = last; good_sens = nsens; + good_dist = dist; // Ask a lesser priority train to free the block for us if(other_train->get_priority()block->get_sensor_id()) ++nsens; + if(nsens>0) + dist += length; } // Unreserve blocks that were not good @@ -936,6 +878,70 @@ unsigned Train::reserve_more() return good_sens; } +float Train::get_reserved_distance_until(const Block *until_block, bool back) const +{ + if(cur_blocks.empty()) + return 0; + + Vehicle &veh = *(reverse!=back ? vehicles.back() : vehicles.front()); + const VehicleType &vtype = veh.get_type(); + + Track *track = veh.get_track(); + if(!track) + return 0; + + list::const_iterator block = cur_blocks.begin(); + while(block!=cur_blocks.end() && !block->block->get_tracks().count(track)) + ++block; + if(block==cur_blocks.end() || block->block==until_block) + return 0; + + unsigned entry = veh.get_entry(); + + float result = veh.get_offset(); + if(reverse!=back) + entry = track->traverse(entry); + else + result = track->get_type().get_path_length(track->get_active_path())-result; + result -= vtype.get_length()/2; + + while(1) + { + if(track->get_type().get_endpoints().size()<2) + break; + + Track *next = track->get_link(track->traverse(entry)); + + if(!block->block->get_tracks().count(next)) + { + if(back) + { + if(block==cur_blocks.begin()) + break; + --block; + } + else + { + ++block; + if(block==cur_blocks.end()) + block = rsv_blocks.begin(); + if(block==rsv_blocks.end()) + break; + } + + if(block->block==until_block) + break; + } + + entry = next->get_endpoint_by_link(*track); + track = next; + + result += track->get_type().get_path_length(track->get_active_path()); + } + + return result; +} + float Train::get_real_speed(unsigned i) const { if(real_speed[i].weight) diff --git a/source/libmarklin/train.h b/source/libmarklin/train.h index 2b08289..f00d0fc 100644 --- a/source/libmarklin/train.h +++ b/source/libmarklin/train.h @@ -156,6 +156,7 @@ private: void halt_event(bool); void block_reserved(const Block &, const Train *); unsigned reserve_more(); + float get_reserved_distance_until(const Block *, bool) const; float get_real_speed(unsigned) const; unsigned find_speed(float) const; float get_travel_speed() const;