]> git.tdb.fi Git - r2c2.git/commitdiff
Pass sensor events through blocks
authorMikko Rasa <tdb@tdb.fi>
Mon, 11 Apr 2011 19:35:26 +0000 (19:35 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 11 Apr 2011 19:35:26 +0000 (19:35 +0000)
Add a hysteresis to activation as well
Expose the transition states

source/engineer/engineer.cpp
source/libr2c2/block.cpp
source/libr2c2/block.h
source/libr2c2/centralstation.cpp
source/libr2c2/centralstation.h
source/libr2c2/layout.cpp
source/libr2c2/layout.h
source/libr2c2/train.cpp
source/libr2c2/train.h

index e24365150fd25ec159c46b20f78b53ea0de91dbe..40011ce9ce1e58768281f7c01a8e57203c51aba1 100644 (file)
@@ -82,9 +82,10 @@ Engineer::Engineer(int argc, char **argv):
        DataFile::load(layout, options.layout_fn);
 
        layout.signal_train_added.connect(sigc::mem_fun(this, &Engineer::train_added));
-       layout.signal_block_reserved.connect(sigc::mem_fun(this, &Engineer::block_reserved));
+       layout.signal_block_reserved.connect(sigc::hide<1>(sigc::mem_fun(this, &Engineer::reset_block_color)));
+       layout.signal_block_state_changed.connect(sigc::hide<1>(sigc::mem_fun(this, &Engineer::reset_block_color)));
        layout.signal_emergency.connect(sigc::mem_fun(this, &Engineer::set_status));
-       layout.get_driver().signal_sensor.connect(sigc::mem_fun(this, &Engineer::sensor_event));
+
        if(FS::exists(options.state_fn))
                DataFile::load(layout, options.state_fn);
 
@@ -382,9 +383,7 @@ void Engineer::set_block_color(const Block &block, const GL::Color &color)
 
 void Engineer::reset_block_color(const Block &block)
 {
-       bool active = false;
-       if(unsigned sid=block.get_sensor_id())
-               active = layout.get_driver().get_sensor(sid);
+       bool active = block.get_state()>Block::INACTIVE;
 
        if(block.get_train())
        {
@@ -404,19 +403,6 @@ void Engineer::reset_block_color(const Block &block)
                set_block_color(block, GL::Color(1));
 }
 
-void Engineer::sensor_event(unsigned addr, bool)
-{
-       const set<Block *> &blocks = layout.get_blocks();
-       for(set<Block *>::const_iterator i=blocks.begin(); i!=blocks.end(); ++i)
-               if((*i)->get_sensor_id()==addr)
-                       reset_block_color(**i);
-}
-
-void Engineer::block_reserved(const Block &block, const Train *)
-{
-       reset_block_color(block);
-}
-
 Track *Engineer::pick_track(int x, int y)
 {
        const GL::Vector3 &start = camera.get_position();
index ca404de569046f2a2824eb7641bbbbbc20425c8e..57cb4d30eb7fb62a3f0b15edb7d666f48b8bbdf8 100644 (file)
@@ -6,7 +6,9 @@ Distributed under the GPL
 */
 
 #include <algorithm>
+#include <msp/time/units.h>
 #include "block.h"
+#include "driver.h"
 #include "layout.h"
 #include "route.h"
 #include "trackiter.h"
@@ -22,6 +24,7 @@ Block::Block(Layout &l, Track &start):
        id(0),
        sensor_id(start.get_sensor_id()),
        turnout_id(start.get_turnout_id()),
+       state(INACTIVE),
        train(0)
 {
        tracks.insert(&start);
@@ -59,6 +62,9 @@ Block::Block(Layout &l, Track &start):
                find_paths(TrackIter(endpoints[i].track, endpoints[i].track_ep), path);
        }
 
+       if(sensor_id && layout.has_driver())
+               layout.get_driver().signal_sensor.connect(sigc::mem_fun(this, &Block::sensor_event));
+
        layout.add_block(*this);
 }
 
@@ -162,13 +168,30 @@ bool Block::reserve(Train *t)
        if(!t || !train)
        {
                train = t;
-               layout.signal_block_reserved.emit(*this, train);
+               signal_reserved.emit(train);
                return true;
        }
        else
                return false;
 }
 
+void Block::tick(const Time::TimeDelta &dt)
+{
+       if(state_confirm_timeout)
+       {
+               state_confirm_timeout -= dt;
+               if(state_confirm_timeout<=Time::zero)
+               {
+                       if(state==MAYBE_INACTIVE)
+                               state = INACTIVE;
+                       else if(state==MAYBE_ACTIVE)
+                               state = ACTIVE;
+                       state_confirm_timeout = Time::zero;
+                       signal_state_changed.emit(state);
+               }
+       }
+}
+
 void Block::find_paths(TrackIter track, unsigned path)
 {
        unsigned mask = track.endpoint().paths;
@@ -211,6 +234,25 @@ void Block::determine_id()
        }
 }
 
+void Block::sensor_event(unsigned addr, bool s)
+{
+       if(addr==sensor_id)
+       {
+               if(s && state<MAYBE_ACTIVE)
+               {
+                       state = MAYBE_ACTIVE;
+                       state_confirm_timeout = 300*Time::msec;
+                       signal_state_changed.emit(state);
+               }
+               else if(!s && state>MAYBE_INACTIVE)
+               {
+                       state = MAYBE_INACTIVE;
+                       state_confirm_timeout = 700*Time::msec;
+                       signal_state_changed.emit(state);
+               }
+       }
+}
+
 
 Block::Endpoint::Endpoint(Track *t, unsigned e):
        track(t),
index e13e58b7da510703c57834a232619bd6f1076db3..3592992c03ca16d152b61566760c04a71ad0fe8d 100644 (file)
@@ -19,9 +19,17 @@ class Route;
 class TrackIter;
 class Train;
 
-class Block
+class Block: public sigc::trackable
 {
 public:
+       enum State
+       {
+               INACTIVE,
+               MAYBE_INACTIVE,
+               MAYBE_ACTIVE,
+               ACTIVE
+       };
+
        struct Endpoint
        {
                Track *track;
@@ -32,11 +40,16 @@ public:
                Endpoint(Track *, unsigned);
        };
 
+       sigc::signal<void, Train *> signal_reserved;
+       sigc::signal<void, State> signal_state_changed;
+
 private:
        Layout &layout;
        unsigned id;
        unsigned sensor_id;
        unsigned turnout_id;
+       State state;
+       Msp::Time::TimeDelta state_confirm_timeout;
        std::set<Track *> tracks;
        std::vector<Endpoint> endpoints;
        Train *train;
@@ -48,6 +61,7 @@ public:
        unsigned get_id() const { return id; }
        unsigned get_sensor_id() const { return sensor_id; }
        unsigned get_turnout_id() const { return turnout_id; }
+       State get_state() const { return state; }
        const std::set<Track *> &get_tracks() const { return tracks; }
        bool has_track(Track &) const;
        const std::vector<Endpoint> &get_endpoints() const { return endpoints; }
@@ -59,10 +73,11 @@ public:
        Block *get_link(unsigned) const;
        bool reserve(Train *);
        Train *get_train() const { return train; }
-       void print_debug();
+       void tick(const Msp::Time::TimeDelta &);
 private:
        void find_paths(TrackIter, unsigned);
        void determine_id();
+       void sensor_event(unsigned, bool);
 };
 
 } // namespace R2C2
index 6a8de96694f3d9ada60020ff06dc4a018a676de6..dd0cbcf58ef13709cd25989324090cd19a0cf5db 100644 (file)
@@ -250,15 +250,6 @@ bool CentralStation::get_sensor(unsigned addr) const
 
 void CentralStation::tick()
 {
-       Time::TimeStamp t = Time::now();
-       for(SensorMap::iterator i=sensors.begin(); i!=sensors.end(); ++i)
-               if(i->second.off_timeout && t>i->second.off_timeout)
-               {
-                       i->second.state = false;
-                       i->second.off_timeout = Time::TimeStamp();
-                       signal_sensor.emit(i->first, i->second.state);
-               }
-
        while(Message msg = receive())
        {
                if(msg.footer.code)
@@ -599,17 +590,11 @@ void CentralStation::process_object(unsigned id, const Message::AttribMap &attri
                                        unsigned addr = base*16+j+1;
                                        Sensor &sensor = sensors[addr];
                                        bool s = state&(1<<j);
-                                       if(s)
+                                       if(s!=sensor.state)
                                        {
-                                               sensor.off_timeout = Time::TimeStamp();
-                                               if(!sensor.state)
-                                               {
-                                                       sensor.state = true;
-                                                       signal_sensor.emit(addr, sensor.state);
-                                               }
+                                               sensor.state = s;
+                                               signal_sensor.emit(addr, sensor.state);
                                        }
-                                       else if(sensor.state)
-                                               sensor.off_timeout = Time::now()+700*Time::msec;
                                }
                        }
                }
index ce5253b1abe97f44a16e582ee3b133b20d33b589..fea882be1011230fa9d6f8c86fc77a7dfbc6288d 100644 (file)
@@ -96,7 +96,6 @@ private:
        struct Sensor
        {
                bool state;
-               Msp::Time::TimeStamp off_timeout;
 
                Sensor();
        };
index 5c4cf9e1d82d26f604fbb4f5a20736cf944937d6..df6989d3320cd3c7cbf4fb0f850915920f8ff431 100644 (file)
@@ -41,14 +41,13 @@ Layout::Layout(Catalogue &c, Driver *d):
        catalogue(c),
        driver(d),
        next_turnout_id(0x800)
-{
-       if(driver)
-               driver->signal_sensor.connect(sigc::mem_fun(this, &Layout::sensor_event));
-}
+{ }
 
 Layout::~Layout()
 {
        delete driver;
+       driver = 0;
+
        while(!trains.empty())
                delete trains.begin()->second;
        while(!routes.empty())
@@ -113,6 +112,12 @@ unsigned Layout::allocate_turnout_id()
 void Layout::add_block(Block &b)
 {
        blocks.insert(&b);
+       b.signal_reserved.connect(sigc::bind<0>(signal_block_reserved, sigc::ref(b)));
+       if(b.get_sensor_id())
+       {
+               b.signal_state_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Layout::block_state_changed), sigc::ref(b)));
+               b.signal_state_changed.connect(sigc::bind<0>(signal_block_state_changed, sigc::ref(b)));
+       }
 }
 
 Block &Layout::get_block(unsigned id) const
@@ -275,6 +280,8 @@ void Layout::tick()
                dt = t-last_tick;
        last_tick = t;
 
+       for(set<Block *>::iterator i=blocks.begin(); i!=blocks.end(); ++i)
+               (*i)->tick(dt);
        for(map<unsigned, Train *>::iterator i=trains.begin(); i!=trains.end(); ++i)
                i->second->tick(t, dt);
 }
@@ -341,18 +348,10 @@ void Layout::save_dynamic(const string &fn) const
        }
 }
 
-void Layout::sensor_event(unsigned addr, bool state)
+void Layout::block_state_changed(Block &block, Block::State state)
 {
-       if(state)
-       {
-               for(set<Block *>::iterator i=blocks.begin(); i!=blocks.end(); ++i)
-                       if((*i)->get_sensor_id()==addr)
-                       {
-                               if(!(*i)->get_train())
-                                       emergency(format("Unreserved sensor %d triggered", addr));
-                               break;
-                       }
-       }
+       if(state==Block::ACTIVE && !block.get_train())
+               emergency(format("Unreserved sensor %d triggered", block.get_sensor_id()));
 }
 
 
index f0a292f580e9847507a57f3acb49c64d175b54eb..a4042316bbdc61d1af6b5f6357a7dbfaadd35cd8 100644 (file)
@@ -12,11 +12,11 @@ Distributed under the GPL
 #include <sigc++/sigc++.h>
 #include <msp/datafile/loader.h>
 #include <msp/time/timestamp.h>
+#include "block.h"
 
 namespace R2C2 {
 
 class ArticleNumber;
-class Block;
 class Catalogue;
 class Driver;
 class Route;
@@ -62,6 +62,7 @@ public:
        sigc::signal<void, Vehicle &> signal_vehicle_added;
        sigc::signal<void, Vehicle &> signal_vehicle_removed;
        sigc::signal<void, Block &, Train *> signal_block_reserved;
+       sigc::signal<void, Block &, Block::State> signal_block_state_changed;
        sigc::signal<void, const std::string &> signal_emergency;
 
 private:
@@ -125,7 +126,7 @@ public:
        void save(const std::string &) const;
        void save_dynamic(const std::string &) const;
 private:
-       void sensor_event(unsigned, bool);
+       void block_state_changed(Block &, Block::State);
 };
 
 } // namespace R2C2
index 78c16c072809ce74f2df57edac7b313d22826342..00730c8e15e08fd048b35b137d51c7adcac51d91 100644 (file)
@@ -85,7 +85,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p):
        layout.get_driver().signal_loco_function.connect(sigc::mem_fun(this, &Train::loco_func_event));
 
        layout.signal_block_reserved.connect(sigc::mem_fun(this, &Train::block_reserved));
-       layout.get_driver().signal_sensor.connect(sigc::mem_fun(this, &Train::sensor_event));
+       layout.signal_block_state_changed.connect(sigc::mem_fun(this, &Train::block_state_changed));
 
        layout.get_driver().signal_halt.connect(sigc::mem_fun(this, &Train::halt_event));
 
@@ -734,9 +734,9 @@ void Train::loco_func_event(unsigned addr, unsigned func, bool state)
        }
 }
 
-void Train::sensor_event(unsigned addr, bool state)
+void Train::block_state_changed(Block &block, Block::State state)
 {
-       if(state)
+       if(state==Block::MAYBE_ACTIVE)
        {
                // Find the first sensor block from our reserved blocks that isn't this sensor
                BlockList::iterator end;
@@ -744,7 +744,7 @@ void Train::sensor_event(unsigned addr, bool state)
                for(end=cur_blocks_end; end!=blocks.end(); ++end)
                        if((*end)->get_sensor_id())
                        {
-                               if((*end)->get_sensor_id()!=addr)
+                               if(&**end!=&block)
                                {
                                        if(result==0)
                                                result = 2;
@@ -770,7 +770,7 @@ void Train::sensor_event(unsigned addr, bool state)
                        {
                                travel_dist += (*j)->get_path_length(j->entry());
 
-                               if((*j)->get_sensor_id()==addr && !advancing)
+                               if(&**j==&block && !advancing)
                                {
                                        TrackIter track = j->track_iter();
                                        if(reverse)
@@ -813,7 +813,7 @@ void Train::sensor_event(unsigned addr, bool state)
                else if(result==3)
                        layout.emergency("Sensor for "+name+" triggered out of order");
        }
-       else
+       else if(state==Block::INACTIVE)
        {
                const Vehicle &veh = *(reverse ? vehicles.front() : vehicles.back());
 
index 90b2a72dc5ce94e3795d2a3d232d932fed22d484..c60b8c044ce743549b5b78eb638183e1fcda189a 100644 (file)
@@ -158,7 +158,7 @@ private:
        void control_changed(const Controller::Control &);
        void loco_speed_event(unsigned, unsigned, bool);
        void loco_func_event(unsigned, unsigned, bool);
-       void sensor_event(unsigned, bool);
+       void block_state_changed(Block &, Block::State);
        void turnout_path_changed(Track &);
        void halt_event(bool);
        void block_reserved(const Block &, const Train *);