]> git.tdb.fi Git - r2c2.git/commitdiff
Fix critical block logic
authorMikko Rasa <tdb@tdb.fi>
Thu, 12 Feb 2015 14:46:45 +0000 (16:46 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 12 Feb 2015 15:52:19 +0000 (17:52 +0200)
First noncritical block is not reliable, as it could be outside of the
train's allocated blocks and not guaranteed to set to a consistent path.
Worse, the get_first_noncritical_block function could return a block on
the other side of a turnout which is changing path, and is_block_critical
used completely different logic.

source/libr2c2/train.cpp
source/libr2c2/train.h
source/libr2c2/trainrouteplanner.cpp
source/libr2c2/trainrouter.cpp

index 858cbbc9e8c8d093971af814a3acb049717ffc37..b1fbc6a76ebb1bf4ad02f85d981f465fef1a1759 100644 (file)
@@ -241,33 +241,53 @@ void Train::stop_at(Block *block)
 
 bool Train::is_block_critical(const Block &block) const
 {
-       return get_reserved_distance_until(&block)<=controller->get_braking_distance()*1.3;
+       if(allocator.is_block_current(block))
+               return true;
+
+       BlockIter i = check_critical_blocks(&block);
+       return i.block()==&block;
+}
+
+BlockIter Train::get_last_critical_block() const
+{
+       return check_critical_blocks(0);
 }
 
-BlockIter Train::get_first_noncritical_block() const
+BlockIter Train::check_critical_blocks(const Block *check) const
 {
        if(allocator.empty())
                return BlockIter();
 
-       BlockIter i = allocator.last_current().next();
+       BlockIter i = allocator.last_current();
 
        if(controller->get_speed()==0)
                return i;
 
+       BlockIter last = allocator.last();
+       if(i.block()==last.block())
+               return i;
+
        float margin = 10*layout.get_catalogue().get_scale();
        float min_dist = controller->get_braking_distance()*1.3+margin;
 
        float dist = 0;
        bool sensor_seen = false;
-       for(; i->get_train()==this; i=i.next())
+       i = i.next();
+       while(i.block()!=last.block() && i.block()!=check)
        {
-               if(dist>min_dist && sensor_seen)
-                       return i;
-
                dist += i->get_path_length(i.entry());
 
                if(i->get_sensor_address())
                        sensor_seen = true;
+
+               if(dist>min_dist && sensor_seen)
+                       break;
+
+               BlockIter j = i.next();
+               if(j->get_train()!=this)
+                       break;
+
+               i = j;
        }
 
        return i;
@@ -276,7 +296,7 @@ BlockIter Train::get_first_noncritical_block() const
 void Train::refresh_blocks_from(Block &block)
 {
        if(is_block_critical(block))
-               allocator.rewind_to(*get_first_noncritical_block());
+               allocator.rewind_to(*get_last_critical_block().next());
        else
                allocator.rewind_to(block);
 }
index 113af0e09a3d424f5744406601d4c5640ce67730..dff9aae666fa3f301b02bf21203024c578a677dc 100644 (file)
@@ -121,7 +121,10 @@ public:
        bool is_placed() const { return !allocator.empty(); }
        void stop_at(Block *);
        bool is_block_critical(const Block &) const;
-       BlockIter get_first_noncritical_block() const;
+       BlockIter get_last_critical_block() const;
+private:
+       BlockIter check_critical_blocks(const Block *) const;
+public:
        void refresh_blocks_from(Block &);
        const BlockAllocator &get_block_allocator() const { return allocator; }
        float get_reserved_distance() const;
index 9bed406f102576c893a6f3b890ad031d36329840..9f19ffcdfb06ae470447ebeb5f01154845ae49ea 100644 (file)
@@ -214,7 +214,7 @@ void TrainRoutePlanner::finalize_plan()
 TrainRoutePlanner::TrainRoutingInfo::TrainRoutingInfo(Train &t):
        train(&t),
        speed(train->get_maximum_speed()),
-       first_noncritical(train->get_first_noncritical_block().block()),
+       first_noncritical(train->get_last_critical_block().next().block()),
        router(train->get_ai_of_type<TrainRouter>()),
        waypoints(router ? router->get_n_waypoints() : 0),
        has_duration(false)
index d95bdff4bc85c0db6afa45ff55ef3ffe166e0ae0..3d8b9d4b7b42a3c7ee3c69c84a81407232107107 100644 (file)
@@ -83,7 +83,7 @@ void TrainRouter::use_planned_route()
 
 void TrainRouter::route_changed()
 {
-       BlockIter fncb = train.get_first_noncritical_block();
+       BlockIter fncb = train.get_last_critical_block().next();
 
        arrival = ON_THE_WAY;
        reserving_route = routes.begin();
@@ -438,23 +438,24 @@ bool TrainRouter::create_lead_route()
        if(routes.empty() || !train.is_placed())
                return false;
 
-       BlockIter fncb = train.get_first_noncritical_block();
-       TrackIter next_track = fncb.track_iter();
+       BlockIter lcb = train.get_last_critical_block();
+       TrackIter last_track_rev = lcb.reverse().track_iter();
 
        unsigned count = 0;
-       for(TrackIter i=next_track.flip(); (i && i->get_block().get_train()==&train); i=i.next())
+       for(TrackIter i=last_track_rev; (i && i->get_block().get_train()==&train); i=i.next())
        {
                if(routes.front()->has_track(*i))
                        ++count;
                else if(count>0)
                {
                        if(count==routes.front()->get_tracks().size())
-                               next_track = i.flip();
+                               last_track_rev = i;
                        break;
                }
        }
 
-       if(!routes.front()->has_track(*next_track) && !routes.front()->has_track(*next_track.flip()))
+       TrackIter next_track = last_track_rev.flip();
+       if(!routes.front()->has_track(*last_track_rev) && !routes.front()->has_track(*next_track))
        {
                Route *pf = Route::find(next_track, *routes.front());
                if(!pf)
@@ -464,7 +465,7 @@ bool TrainRouter::create_lead_route()
        }
 
        Route *lead = 0;
-       for(TrackIter i=next_track.flip(); (i && i->get_block().get_train()==&train); i=i.next())
+       for(TrackIter i=last_track_rev; (i && i->get_block().get_train()==&train); i=i.next())
        {
                if(!lead && !routes.front()->has_track(*i))
                {