]> git.tdb.fi Git - r2c2.git/commitdiff
Create a more generic version of Train::get_reserved_distance
authorMikko Rasa <tdb@tdb.fi>
Mon, 4 Oct 2010 19:59:30 +0000 (19:59 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 4 Oct 2010 19:59:30 +0000 (19:59 +0000)
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

source/libmarklin/train.cpp
source/libmarklin/train.h

index 0c1748ac7d4286a2d0f220fdbaa3d0a4c8bf259a..acf8aa51486de42adb8901b98f9c78f2d0b79ac0 100644 (file)
@@ -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)<controller->get_braking_distance()*1.3+margin)
+               return false;
+
        unsigned nsens = 0;
        for(list<BlockRef>::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<BlockRef>::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<BlockRef>::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<BlockRef>::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<BlockRef> contested_blocks;
-       while(good_sens<3 || !contested_blocks.empty())
+
+       SetFlag setf(reserving);
+
+       while(good_sens<3 || good_dist<min_dist || !contested_blocks.empty())
        {
                // Traverse to the next block
-               unsigned exit = last->block->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()<priority)
@@ -880,6 +819,7 @@ unsigned Train::reserve_more()
                        // Keep the blocks reserved so far, as either us or the other train can diverge
                        good = last;
                        good_sens = nsens;
+                       good_dist = dist;
 
                        // Figure out what path we'd like to take on the turnout
                        int path = -1;
@@ -914,6 +854,8 @@ unsigned Train::reserve_more()
                last = &rsv_blocks.back();
                if(last->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<BlockRef>::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)
index 2b082893b308f02782b5ba5d7415bde7b76e5ffb..f00d0fceec719d37b51242bddb6671394ab1c407 100644 (file)
@@ -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;