]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/train.cpp
Fix critical block logic
[r2c2.git] / source / libr2c2 / train.cpp
index 845232fa4d9cf442fc5dddc692c5873291c35302..b1fbc6a76ebb1bf4ad02f85d981f465fef1a1759 100644 (file)
@@ -5,15 +5,14 @@
 #include <msp/strings/format.h>
 #include <msp/time/units.h>
 #include <msp/time/utils.h>
-#include "aicontrol.h"
 #include "beamgate.h"
 #include "block.h"
 #include "catalogue.h"
 #include "driver.h"
 #include "layout.h"
-#include "route.h"
 #include "simplecontroller.h"
 #include "speedquantizer.h"
+#include "timetable.h"
 #include "trackcircuit.h"
 #include "trackiter.h"
 #include "tracktype.h"
@@ -21,7 +20,6 @@
 #include "trainrouter.h"
 #include "vehicle.h"
 #include "vehicletype.h"
-#include "zone.h"
 
 using namespace std;
 using namespace Msp;
@@ -62,11 +60,12 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p):
        layout.get_driver().signal_loco_speed.connect(sigc::mem_fun(this, &Train::loco_speed_event));
        layout.get_driver().signal_loco_function.connect(sigc::mem_fun(this, &Train::loco_func_event));
 
-       layout.signal_sensor_state_changed.connect(sigc::mem_fun(this, &Train::sensor_state_changed));
-
        layout.get_driver().signal_halt.connect(sigc::mem_fun(this, &Train::halt_event));
 
        controller->signal_control_changed.connect(sigc::mem_fun(this, &Train::control_changed));
+
+       allocator.signal_advanced.connect(sigc::mem_fun(this, &Train::advanced));
+       allocator.signal_rear_advanced.connect(signal_rear_advanced);
 }
 
 Train::~Train()
@@ -242,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;
@@ -277,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);
 }
@@ -299,12 +318,9 @@ void Train::tick(const Time::TimeDelta &dt)
 {
        if(stop_timeout)
        {
-               stop_timeout -= dt;
+               stop_timeout = max(stop_timeout-dt, Time::zero);
                if(stop_timeout<=Time::zero)
-               {
                        allocator.set_active(false);
-                       stop_timeout = Time::TimeDelta();
-               }
        }
 
        travel_time += dt;
@@ -357,7 +373,8 @@ void Train::tick(const Time::TimeDelta &dt)
                Vehicle &vehicle = *(reverse ? vehicles.back() : vehicles.front());
 
                float d = speed*(dt/Time::sec);
-               if(allocator.is_block_current(vehicle.get_placement().get_position(reverse ? VehiclePlacement::BACK_AXLE : VehiclePlacement::FRONT_AXLE)->get_block()))
+               Block &block = vehicle.get_placement().get_position(reverse ? VehiclePlacement::BACK_AXLE : VehiclePlacement::FRONT_AXLE)->get_block();
+               if(allocator.is_block_current(block))
                {
                        SetFlag setf(advancing);
                        vehicle.advance(reverse ? -d : d);
@@ -367,7 +384,7 @@ void Train::tick(const Time::TimeDelta &dt)
                        overshoot_dist += d;
                        if(overshoot_dist>40*layout.get_catalogue().get_scale())
                        {
-                               layout.emergency(name+" has not arrived at sensor");
+                               layout.emergency(&block, name+" has not arrived at sensor");
                                accurate_position = false;
                        }
                }
@@ -382,9 +399,10 @@ void Train::save(list<DataFile::Statement> &st) const
 {
        st.push_back((DataFile::Statement("name"), name));
 
+       const Catalogue &cat = layout.get_catalogue();
        for(vector<Vehicle *>::const_iterator i=vehicles.begin(); i!=vehicles.end(); ++i)
                if(i!=vehicles.begin())
-                       st.push_back((DataFile::Statement("vehicle"), (*i)->get_type().get_article_number()));
+                       st.push_back((DataFile::Statement("vehicle"), cat.get_name(&(*i)->get_type())));
 
        if(speed_quantizer)
        {
@@ -408,6 +426,12 @@ void Train::save(list<DataFile::Statement> &st) const
                        router->save(ss.sub);
                        st.push_back(ss);
                }
+               else if(Timetable *timetable = dynamic_cast<Timetable *>(*i))
+               {
+                       DataFile::Statement ss("timetable");
+                       timetable->save(ss.sub);
+                       st.push_back(ss);
+               }
        }
 }
 
@@ -444,29 +468,21 @@ void Train::loco_func_event(unsigned id, unsigned func, bool state)
        }
 }
 
-void Train::sensor_state_changed(Sensor &sensor, Sensor::State state)
+void Train::advanced(Block &block, Sensor *sensor)
 {
-       if(!current_speed_step || state!=Sensor::MAYBE_ACTIVE)
-               return;
+       if(!sensor || sensor==block.get_sensor())
+               signal_advanced.emit(block);
 
-       Block *block = sensor.get_block();
-       if(!block || block->get_train()!=this)
+       if(!sensor)
                return;
 
-       if(last_entry_block && &*last_entry_block!=block)
-       {
-               for(BlockIter i=last_entry_block.next(); (i && &*i!=block); i=i.next())
-                       if(i->get_train()!=this || i->get_sensor_address())
-                               return;
-       }
-
-       if(dynamic_cast<TrackCircuit *>(&sensor))
+       if(sensor==block.get_sensor())
        {
                if(last_entry_block && pure_speed && speed_quantizer)
                {
                        float travel_distance = 0;
 
-                       for(BlockIter i=last_entry_block; &*i!=block; i=i.next())
+                       for(BlockIter i=last_entry_block; &*i!=&block; i=i.next())
                                travel_distance += i->get_path_length(i.entry());
 
                        if(travel_distance>0)
@@ -478,10 +494,13 @@ void Train::sensor_state_changed(Sensor &sensor, Sensor::State state)
                        }
                }
 
-               last_entry_block = allocator.iter_for(*block);
+               last_entry_block = allocator.iter_for(block);
                travel_time = Time::zero;
-               pure_speed = true;
-               accurate_position = true;
+               if(!layout.get_driver().is_halted())
+               {
+                       pure_speed = true;
+                       accurate_position = true;
+               }
                overshoot_dist = 0;
 
                if(!advancing && vehicles.front()->is_placed())
@@ -496,12 +515,12 @@ void Train::sensor_state_changed(Sensor &sensor, Sensor::State state)
                                vehicles.front()->place(track, VehiclePlacement::FRONT_AXLE);
                }
        }
-       else if(BeamGate *gate = dynamic_cast<BeamGate *>(&sensor))
+       else if(BeamGate *gate = dynamic_cast<BeamGate *>(sensor))
        {
                if(!advancing && vehicles.front()->is_placed())
                {
-                       TrackIter track = allocator.iter_for(*block).track_iter();
-                       for(; (track && &track->get_block()==block); track=track.next())
+                       TrackIter track = allocator.iter_for(block).track_iter();
+                       for(; (track && &track->get_block()==&block); track=track.next())
                                if(track.track()==gate->get_track())
                                {
                                        if(reverse)
@@ -577,6 +596,7 @@ Train::Loader::Loader(Train &t):
        add("name",        &Loader::name);
        add("quantized_speed",  &Loader::quantized_speed);
        add("router",      &Loader::router);
+       add("timetable",   &Loader::timetable);
        add("vehicle",     &Loader::vehicle);
 }
 
@@ -612,9 +632,15 @@ void Train::Loader::router()
        load_sub(*rtr);
 }
 
-void Train::Loader::vehicle(ArticleNumber art_nr)
+void Train::Loader::timetable()
+{
+       Timetable *ttbl = new Timetable(obj);
+       load_sub(*ttbl, obj.layout);
+}
+
+void Train::Loader::vehicle(const string &n)
 {
-       const VehicleType &vtype = obj.layout.get_catalogue().get<VehicleType>(art_nr);
+       const VehicleType &vtype = obj.layout.get_catalogue().get<VehicleType>(n);
        Vehicle *veh = new Vehicle(obj.layout, vtype);
        obj.vehicles.back()->attach_back(*veh);
        obj.vehicles.push_back(veh);