From b14059de03324aecde3efc649293d98ce5b7aaf2 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 11 Apr 2011 19:35:26 +0000 Subject: [PATCH] Pass sensor events through blocks Add a hysteresis to activation as well Expose the transition states --- source/engineer/engineer.cpp | 22 +++------------- source/libr2c2/block.cpp | 44 ++++++++++++++++++++++++++++++- source/libr2c2/block.h | 19 +++++++++++-- source/libr2c2/centralstation.cpp | 21 +++------------ source/libr2c2/centralstation.h | 1 - source/libr2c2/layout.cpp | 29 ++++++++++---------- source/libr2c2/layout.h | 5 ++-- source/libr2c2/train.cpp | 12 ++++----- source/libr2c2/train.h | 2 +- 9 files changed, 91 insertions(+), 64 deletions(-) diff --git a/source/engineer/engineer.cpp b/source/engineer/engineer.cpp index e243651..40011ce 100644 --- a/source/engineer/engineer.cpp +++ b/source/engineer/engineer.cpp @@ -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 &blocks = layout.get_blocks(); - for(set::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(); diff --git a/source/libr2c2/block.cpp b/source/libr2c2/block.cpp index ca404de..57cb4d3 100644 --- a/source/libr2c2/block.cpp +++ b/source/libr2c2/block.cpp @@ -6,7 +6,9 @@ Distributed under the GPL */ #include +#include #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 && stateMAYBE_INACTIVE) + { + state = MAYBE_INACTIVE; + state_confirm_timeout = 700*Time::msec; + signal_state_changed.emit(state); + } + } +} + Block::Endpoint::Endpoint(Track *t, unsigned e): track(t), diff --git a/source/libr2c2/block.h b/source/libr2c2/block.h index e13e58b..3592992 100644 --- a/source/libr2c2/block.h +++ b/source/libr2c2/block.h @@ -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 signal_reserved; + sigc::signal signal_state_changed; + private: Layout &layout; unsigned id; unsigned sensor_id; unsigned turnout_id; + State state; + Msp::Time::TimeDelta state_confirm_timeout; std::set tracks; std::vector 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 &get_tracks() const { return tracks; } bool has_track(Track &) const; const std::vector &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 diff --git a/source/libr2c2/centralstation.cpp b/source/libr2c2/centralstation.cpp index 6a8de96..dd0cbcf 100644 --- a/source/libr2c2/centralstation.cpp +++ b/source/libr2c2/centralstation.cpp @@ -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<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::iterator i=blocks.begin(); i!=blocks.end(); ++i) + (*i)->tick(dt); for(map::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::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())); } diff --git a/source/libr2c2/layout.h b/source/libr2c2/layout.h index f0a292f..a404231 100644 --- a/source/libr2c2/layout.h +++ b/source/libr2c2/layout.h @@ -12,11 +12,11 @@ Distributed under the GPL #include #include #include +#include "block.h" namespace R2C2 { class ArticleNumber; -class Block; class Catalogue; class Driver; class Route; @@ -62,6 +62,7 @@ public: sigc::signal signal_vehicle_added; sigc::signal signal_vehicle_removed; sigc::signal signal_block_reserved; + sigc::signal signal_block_state_changed; sigc::signal 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 diff --git a/source/libr2c2/train.cpp b/source/libr2c2/train.cpp index 78c16c0..00730c8 100644 --- a/source/libr2c2/train.cpp +++ b/source/libr2c2/train.cpp @@ -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()); diff --git a/source/libr2c2/train.h b/source/libr2c2/train.h index 90b2a72..c60b8c0 100644 --- a/source/libr2c2/train.h +++ b/source/libr2c2/train.h @@ -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 *); -- 2.43.0