X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibmarklin%2Ftrain.cpp;h=8166c09a86944d1bb4251dec61a38819d08b8920;hb=3d38bcbe8add00b558012fa0cd4e0be26464dbeb;hp=d87d3768a7e0a482db808d934cd5f5211f389197;hpb=182ee232f01d5bb25ddc4cf6e00249698871412f;p=r2c2.git diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index d87d376..8166c09 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -24,6 +24,19 @@ Distributed under the GPL using namespace std; using namespace Msp; +namespace { + +struct SetFlag +{ + bool &flag; + + SetFlag(bool &f): flag(f) { flag = true; } + ~SetFlag() { flag = false; } +}; + +} + + namespace Marklin { Train::Train(Layout &l, const VehicleType &t, unsigned a): @@ -32,6 +45,8 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a): address(a), priority(0), pending_block(0), + reserving(false), + advancing(false), controller(new AIControl(*this, new SimpleController)), timetable(0), active(false), @@ -200,7 +215,7 @@ void Train::set_route(const Route *r) next_route = 0; end_of_route = false; - if(route) + if(route && !cur_blocks.empty()) { BlockRef &last = (rsv_blocks.empty() ? cur_blocks.back() : rsv_blocks.back()); BlockRef next = last.next(); @@ -272,7 +287,7 @@ void Train::place(Block &block, unsigned entry) else { const Block::Endpoint &bep = block.get_endpoints()[entry]; - vehicles.front()->place(bep.track, bep.track_ep, 0, Vehicle::BACK_BUFFER); + vehicles.back()->place(bep.track, bep.track_ep, 0, Vehicle::BACK_BUFFER); } } @@ -308,6 +323,9 @@ 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(); @@ -407,7 +425,10 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) float d = get_real_speed(current_speed)*(dt/Time::sec); if(ok) + { + SetFlag setf(advancing); vehicle.advance(reverse ? -d : d); + } else if(accurate_position) { overshoot_dist += d; @@ -435,7 +456,10 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) unsigned entry = bep.track_ep; bool found = false; - float dist = veh.get_offset()-veh.get_type().get_length()/2; + 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()) @@ -589,7 +613,7 @@ void Train::sensor_event(unsigned addr, bool state) j->block->traverse(j->entry, &block_len); travel_dist += block_len; - if(j->block->get_sensor_id()==addr) + if(j->block->get_sensor_id()==addr && !advancing) { const Block::Endpoint &bep = j->block->get_endpoints()[j->entry]; if(reverse) @@ -648,7 +672,7 @@ void Train::sensor_event(unsigned addr, bool state) } } - if(end!=cur_blocks.begin()) + if(end!=cur_blocks.begin() && end!=cur_blocks.end()) // Free blocks up to the last inactive sensor release_blocks(cur_blocks, cur_blocks.begin(), end); } @@ -661,7 +685,12 @@ void Train::turnout_event(unsigned addr, bool) unsigned pending_addr = pending_block->get_turnout_id(); bool double_addr = (*pending_block->get_tracks().begin())->get_type().is_double_address(); if(addr==pending_addr || (double_addr && addr==pending_addr+1)) - reserve_more(); + { + if(reserving) + pending_block = 0; + else + reserve_more(); + } } } @@ -714,6 +743,8 @@ unsigned Train::reserve_more() } } + SetFlag setf(reserving); + bool got_more = false; BlockRef *good = last; unsigned good_sens = nsens; @@ -802,10 +833,13 @@ unsigned Train::reserve_more() if(path!=static_cast(entry_ep.track->get_active_path())) { // The turnout is set to wrong path - switch and wait for it - link->reserve(0); pending_block = link; entry_ep.track->set_active_path(path); - break; + if(pending_block) + { + link->reserve(0); + break; + } } } @@ -827,6 +861,7 @@ unsigned Train::reserve_more() last = &rsv_blocks.back(); } + // Make any sensorless blocks at the beginning immediately current list::iterator i; for(i=rsv_blocks.begin(); (i!=rsv_blocks.end() && !i->block->get_sensor_id()); ++i) ;