X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibmarklin%2Ftrain.cpp;h=d6ed044954286ba549c0da0c0e75d363e300861e;hb=1f9af43b6ab300693c044b431e95b25422b36507;hp=0c1748ac7d4286a2d0f220fdbaa3d0a4c8bf259a;hpb=98047057e4adae31aa449161ca845db1a6c2db77;p=r2c2.git diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index 0c1748a..d6ed044 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -288,17 +288,38 @@ void Train::place(Block &block, unsigned entry) const Block::Endpoint &bep = block.get_endpoints()[exit]; Track *track = bep.track->get_link(bep.track_ep); unsigned ep = track->get_endpoint_by_link(*bep.track); - vehicles.front()->place(track, ep, 0, Vehicle::FRONT_BUFFER); + vehicles.front()->place(*track, ep, 0, Vehicle::FRONT_BUFFER); } else { const Block::Endpoint &bep = block.get_endpoints()[entry]; - vehicles.back()->place(bep.track, bep.track_ep, 0, Vehicle::BACK_BUFFER); + vehicles.back()->place(*bep.track, bep.track_ep, 0, Vehicle::BACK_BUFFER); } } +void Train::unplace() +{ + if(controller->get_speed()) + throw InvalidState("Must be stopped before unplacing"); + + release_blocks(rsv_blocks); + release_blocks(cur_blocks); + + set_active(false); + accurate_position = false; + + for(vector::iterator i=vehicles.begin(); i!=vehicles.end(); ++i) + (*i)->unplace(); + + set_status("Unplaced"); +} + 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 +350,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 +429,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()); @@ -626,10 +564,10 @@ void Train::sensor_event(unsigned addr, bool state) { Track *track = bep.track->get_link(bep.track_ep); unsigned ep = track->get_endpoint_by_link(*bep.track); - vehicles.back()->place(track, ep, 0, Vehicle::BACK_AXLE); + vehicles.back()->place(*track, ep, 0, Vehicle::BACK_AXLE); } else - vehicles.front()->place(bep.track, bep.track_ep, 0, Vehicle::FRONT_AXLE); + vehicles.front()->place(*bep.track, bep.track_ep, 0, Vehicle::FRONT_AXLE); } } last_entry_time = Time::now(); @@ -664,9 +602,14 @@ void Train::sensor_event(unsigned addr, bool state) } else { + const Vehicle &veh = *(reverse ? vehicles.front() : vehicles.back()); + // Find the first sensor in our current blocks that's still active list::iterator end = cur_blocks.begin(); for(list::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i) + { + if(i->block->get_tracks().count(veh.get_track())) + break; if(i->block->get_sensor_id()) { if(layout.get_driver().get_sensor(i->block->get_sensor_id())) @@ -677,6 +620,7 @@ void Train::sensor_event(unsigned addr, bool state) ++end; } } + } if(end!=cur_blocks.begin() && end!=cur_blocks.end()) // Free blocks up to the last inactive sensor @@ -727,11 +671,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 +702,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 +740,7 @@ unsigned Train::reserve_more() { good = last; good_sens = nsens; + good_dist = dist; end_of_route = true; } break; @@ -795,6 +755,7 @@ unsigned Train::reserve_more() { good = last; good_sens = nsens; + good_dist = dist; } break; } @@ -849,6 +810,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 +901,78 @@ 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!=rsv_blocks.end() && !block->block->get_tracks().count(track)) + { + ++block; + if(block==cur_blocks.end()) + { + if(back) + return 0; + block = rsv_blocks.begin(); + } + } + if(block==rsv_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) @@ -973,9 +1010,11 @@ unsigned Train::find_speed(float real) const unsigned low = 0; unsigned high = 0; + unsigned last = 0; for(unsigned i=0; (!high && i<=14); ++i) if(real_speed[i].weight) { + last = i; if(real_speed[i].speed(low*real/real_speed[low].speed), 14U); + return min(min(static_cast(low*real/real_speed[low].speed), 14U), last+3); } float f = (real-real_speed[low].speed)/(real_speed[high].speed-real_speed[low].speed); @@ -1085,7 +1124,7 @@ void Train::Loader::finish() { const BlockRef &blkref = obj.cur_blocks.front(); const Block::Endpoint &bep = blkref.block->get_endpoints()[blkref.entry]; - obj.vehicles.back()->place(bep.track, bep.track_ep, 0, Vehicle::BACK_BUFFER); + obj.vehicles.back()->place(*bep.track, bep.track_ep, 0, Vehicle::BACK_BUFFER); obj.set_status("Stopped"); }