From 59bae8acd679127602cf35d22bcd37e316a5a056 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 4 Jun 2013 14:34:58 +0300 Subject: [PATCH] Handle sensors in a separate class --- source/engineer/engineer.cpp | 7 +++- source/libr2c2/block.cpp | 43 ++-------------------- source/libr2c2/block.h | 19 ++-------- source/libr2c2/blockallocator.cpp | 20 +++++++--- source/libr2c2/blockallocator.h | 4 +- source/libr2c2/layout.cpp | 35 +++++++++++++----- source/libr2c2/layout.h | 12 ++++-- source/libr2c2/sensor.cpp | 61 +++++++++++++++++++++++++++++++ source/libr2c2/sensor.h | 45 +++++++++++++++++++++++ source/libr2c2/timetable.cpp | 17 ++++++--- source/libr2c2/timetable.h | 5 ++- source/libr2c2/trackcircuit.cpp | 13 +++++++ source/libr2c2/trackcircuit.h | 23 ++++++++++++ source/libr2c2/train.cpp | 18 ++++++--- source/libr2c2/train.h | 5 ++- 15 files changed, 237 insertions(+), 90 deletions(-) create mode 100644 source/libr2c2/sensor.cpp create mode 100644 source/libr2c2/sensor.h create mode 100644 source/libr2c2/trackcircuit.cpp create mode 100644 source/libr2c2/trackcircuit.h diff --git a/source/engineer/engineer.cpp b/source/engineer/engineer.cpp index 69dc47b..b7b114b 100644 --- a/source/engineer/engineer.cpp +++ b/source/engineer/engineer.cpp @@ -17,6 +17,7 @@ #include #include #include "libr2c2/driver.h" +#include "libr2c2/trackcircuit.h" #include "libr2c2/tracktype.h" #include "3d/path.h" #include "3d/track.h" @@ -71,8 +72,10 @@ Engineer::Engineer(int argc, char **argv): layout.signal_train_added.connect(sigc::mem_fun(this, &Engineer::train_added)); 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)); + const set &blocks = layout.get_blocks(); + for(set::const_iterator i=blocks.begin(); i!=blocks.end(); ++i) + (*i)->get_sensor().signal_state_changed.connect(sigc::hide(sigc::bind(sigc::mem_fun(this, &Engineer::reset_block_color), sigc::ref(**i)))); if(FS::exists(options.state_fn)) DataFile::load(layout, options.state_fn); @@ -360,7 +363,7 @@ void Engineer::set_block_color(const Block &block, const GL::Color &color) void Engineer::reset_block_color(const Block &block) { - bool active = block.get_state()>Block::INACTIVE; + bool active = block.get_sensor().get_state()>Sensor::INACTIVE; if(block.get_train()) { diff --git a/source/libr2c2/block.cpp b/source/libr2c2/block.cpp index 386f237..6103509 100644 --- a/source/libr2c2/block.cpp +++ b/source/libr2c2/block.cpp @@ -4,6 +4,7 @@ #include "driver.h" #include "layout.h" #include "route.h" +#include "trackcircuit.h" #include "trackiter.h" #include "tracktype.h" @@ -17,7 +18,6 @@ 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); @@ -55,8 +55,7 @@ Block::Block(Layout &l, Track &start): find_paths(endpoints[i].track_iter(), path); } - if(sensor_id && layout.has_driver()) - layout.get_driver().signal_sensor.connect(sigc::mem_fun(this, &Block::sensor_event)); + sensor = new TrackCircuit(layout, *this); layout.add_block(*this); } @@ -76,6 +75,8 @@ Block::~Block() } layout.remove_block(*this); + + delete sensor; } bool Block::has_track(Track &t) const @@ -168,23 +169,6 @@ bool Block::reserve(Train *t) 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(const TrackIter &track, unsigned path) { unsigned mask = track.endpoint().paths; @@ -227,25 +211,6 @@ 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 23fb3c7..f71ee29 100644 --- a/source/libr2c2/block.h +++ b/source/libr2c2/block.h @@ -9,20 +9,13 @@ namespace R2C2 { class Layout; class Route; +class TrackCircuit; class TrackIter; class Train; -class Block: public sigc::trackable +class Block { public: - enum State - { - INACTIVE, - MAYBE_INACTIVE, - MAYBE_ACTIVE, - ACTIVE - }; - struct Endpoint { Track *track; @@ -36,15 +29,13 @@ public: }; 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; + TrackCircuit *sensor; std::set tracks; std::vector endpoints; Train *train; @@ -56,7 +47,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; } + TrackCircuit &get_sensor() const { return *sensor; } const std::set &get_tracks() const { return tracks; } bool has_track(Track &) const; const std::vector &get_endpoints() const { return endpoints; } @@ -68,11 +59,9 @@ public: Block *get_link(unsigned) const; bool reserve(Train *); Train *get_train() const { return train; } - void tick(const Msp::Time::TimeDelta &); private: void find_paths(const TrackIter &, unsigned); void determine_id(); - void sensor_event(unsigned, bool); }; } // namespace R2C2 diff --git a/source/libr2c2/blockallocator.cpp b/source/libr2c2/blockallocator.cpp index fc414cc..acb59ae 100644 --- a/source/libr2c2/blockallocator.cpp +++ b/source/libr2c2/blockallocator.cpp @@ -1,9 +1,11 @@ #include #include #include "blockallocator.h" +#include "block.h" #include "catalogue.h" #include "driver.h" #include "layout.h" +#include "trackcircuit.h" #include "trackiter.h" #include "train.h" #include "vehicle.h" @@ -22,7 +24,7 @@ BlockAllocator::BlockAllocator(Train &t): { Layout &layout = train.get_layout(); layout.signal_block_reserved.connect(sigc::mem_fun(this, &BlockAllocator::block_reserved)); - layout.signal_block_state_changed.connect(sigc::mem_fun(this, &BlockAllocator::block_state_changed)); + layout.signal_sensor_state_changed.connect(sigc::mem_fun(this, &BlockAllocator::sensor_state_changed)); const set &tracks = layout.get_tracks(); for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) @@ -304,12 +306,18 @@ void BlockAllocator::block_reserved(Block &block, const Train *tr) reserve_more(); } -void BlockAllocator::block_state_changed(Block &block, Block::State state) +void BlockAllocator::sensor_state_changed(Sensor &sensor, Sensor::State state) { - if(block.get_train()!=&train) + Block *block = 0; + if(TrackCircuit *tc = dynamic_cast(&sensor)) + block = &tc->get_block(); + else return; - if(state==Block::MAYBE_ACTIVE) + if(block->get_train()!=&train) + return; + + if(state==Sensor::MAYBE_ACTIVE) { // Find the first sensor block from our reserved blocks that isn't this sensor BlockList::iterator end; @@ -317,7 +325,7 @@ void BlockAllocator::block_state_changed(Block &block, Block::State state) for(end=cur_blocks_end; end!=blocks.end(); ++end) if((*end)->get_sensor_id()) { - if(&**end!=&block) + if(&**end!=block) { if(result==0) result = 2; @@ -340,7 +348,7 @@ void BlockAllocator::block_state_changed(Block &block, Block::State state) else if(result==3) train.get_layout().emergency("Sensor for "+train.get_name()+" triggered out of order"); } - else if(state==Block::INACTIVE) + else if(state==Sensor::INACTIVE) { const Vehicle &veh = train.get_vehicle(train.get_controller().get_reverse() ? 0 : train.get_n_vehicles()-1); const Block &veh_block = veh.get_track()->get_block(); diff --git a/source/libr2c2/blockallocator.h b/source/libr2c2/blockallocator.h index 39a327b..6eecbd4 100644 --- a/source/libr2c2/blockallocator.h +++ b/source/libr2c2/blockallocator.h @@ -3,8 +3,8 @@ #include #include -#include "block.h" #include "blockiter.h" +#include "sensor.h" namespace R2C2 { @@ -72,7 +72,7 @@ public: private: void turnout_path_changed(Track &); void block_reserved(Block &, const Train *); - void block_state_changed(Block &, Block::State); + void sensor_state_changed(Sensor &, Sensor::State); public: void save(std::list &) const; diff --git a/source/libr2c2/layout.cpp b/source/libr2c2/layout.cpp index 302f13a..1654295 100644 --- a/source/libr2c2/layout.cpp +++ b/source/libr2c2/layout.cpp @@ -13,6 +13,7 @@ #include "signal.h" #include "signaltype.h" #include "track.h" +#include "trackcircuit.h" #include "tracktype.h" #include "train.h" #include "vehicletype.h" @@ -143,11 +144,6 @@ 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 @@ -293,6 +289,20 @@ void Layout::remove_vehicle(Vehicle &v) signal_vehicle_removed.emit(v); } +void Layout::add_sensor(Sensor &s) +{ + if(sensors.insert(&s).second) + { + s.signal_state_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Layout::sensor_state_changed), sigc::ref(s))); + s.signal_state_changed.connect(sigc::bind<0>(signal_sensor_state_changed, sigc::ref(s))); + } +} + +void Layout::remove_sensor(Sensor &s) +{ + sensors.erase(&s); +} + void Layout::tick() { if(driver) @@ -304,7 +314,7 @@ void Layout::tick() dt = t-last_tick; last_tick = t; - for(set::iterator i=blocks.begin(); i!=blocks.end(); ++i) + for(set::iterator i=sensors.begin(); i!=sensors.end(); ++i) (*i)->tick(dt); for(set::iterator i=signals.begin(); i!=signals.end(); ++i) (*i)->tick(dt); @@ -382,10 +392,17 @@ void Layout::save_dynamic(const string &fn) const } } -void Layout::block_state_changed(Block &block, Block::State state) +void Layout::sensor_state_changed(Sensor &sensor, Sensor::State state) { - if(state==Block::ACTIVE && !block.get_train()) - emergency(format("Unreserved sensor %d triggered", block.get_sensor_id())); + if(state==Sensor::ACTIVE) + { + Block *block = 0; + if(TrackCircuit *tc = dynamic_cast(&sensor)) + block = &tc->get_block(); + + if(block && !block->get_train()) + emergency(format("Unreserved sensor %d triggered", sensor.get_address())); + } } diff --git a/source/libr2c2/layout.h b/source/libr2c2/layout.h index 8e44fb5..de5588c 100644 --- a/source/libr2c2/layout.h +++ b/source/libr2c2/layout.h @@ -5,14 +5,16 @@ #include #include #include -#include "block.h" #include "geometry.h" +#include "sensor.h" namespace R2C2 { class ArticleNumber; +class Block; class Catalogue; class Driver; +class Object; class Route; class Signal; class Track; @@ -58,7 +60,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_sensor_state_changed; sigc::signal signal_emergency; private: @@ -70,6 +72,7 @@ private: std::set routes; ZoneSet zones; std::set blocks; + std::set sensors; std::map trains; std::set vehicles; Msp::Time::TimeStamp last_tick; @@ -129,13 +132,16 @@ public: void add_vehicle(Vehicle &); void remove_vehicle(Vehicle &); + void add_sensor(Sensor &); + void remove_sensor(Sensor &); + void tick(); void emergency(const std::string &); void save(const std::string &) const; void save_dynamic(const std::string &) const; private: - void block_state_changed(Block &, Block::State); + void sensor_state_changed(Sensor &, Sensor::State); }; } // namespace R2C2 diff --git a/source/libr2c2/sensor.cpp b/source/libr2c2/sensor.cpp new file mode 100644 index 0000000..1b7e8cc --- /dev/null +++ b/source/libr2c2/sensor.cpp @@ -0,0 +1,61 @@ +#include "driver.h" +#include "layout.h" +#include "sensor.h" + +using namespace Msp; + +namespace R2C2 { + +Sensor::Sensor(Layout &l): + layout(l), + address(0), + state(INACTIVE) +{ + if(layout.has_driver()) + layout.get_driver().signal_sensor.connect(sigc::mem_fun(this, &Sensor::event)); + + layout.add_sensor(*this); +} + +Sensor::~Sensor() +{ + layout.remove_sensor(*this); +} + +void Sensor::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 Sensor::event(unsigned a, bool s) +{ + if(a==address) + { + if(s && stateMAYBE_INACTIVE) + { + state = MAYBE_INACTIVE; + state_confirm_timeout = 700*Time::msec; + signal_state_changed.emit(state); + } + } +} + +} // namespace R2C2 diff --git a/source/libr2c2/sensor.h b/source/libr2c2/sensor.h new file mode 100644 index 0000000..849f899 --- /dev/null +++ b/source/libr2c2/sensor.h @@ -0,0 +1,45 @@ +#ifndef LIBR2C2_SENSOR_H_ +#define LIBR2C2_SENSOR_H_ + +#include +#include + +namespace R2C2 { + +class Layout; + +class Sensor: public sigc::trackable +{ +public: + enum State + { + INACTIVE, + MAYBE_INACTIVE, + MAYBE_ACTIVE, + ACTIVE + }; + + sigc::signal signal_state_changed; + +protected: + Layout &layout; + unsigned address; + State state; + Msp::Time::TimeDelta state_confirm_timeout; + + Sensor(Layout &); +public: + virtual ~Sensor(); + + unsigned get_address() const { return address; } + State get_state() const { return state; } + + void tick(const Msp::Time::TimeDelta &); + +private: + void event(unsigned, bool); +}; + +} // namespace R2C2 + +#endif diff --git a/source/libr2c2/timetable.cpp b/source/libr2c2/timetable.cpp index 44e859e..5be3a03 100644 --- a/source/libr2c2/timetable.cpp +++ b/source/libr2c2/timetable.cpp @@ -5,6 +5,7 @@ #include "driver.h" #include "layout.h" #include "timetable.h" +#include "trackcircuit.h" #include "train.h" using namespace std; @@ -24,7 +25,7 @@ Timetable::Timetable(Train &t): train.signal_advanced.connect(sigc::mem_fun(this, &Timetable::train_advanced)); train.signal_ai_event.connect(sigc::mem_fun(this, &Timetable::event)); Layout &layout = train.get_layout(); - layout.signal_block_state_changed.connect(sigc::mem_fun(this, &Timetable::block_state_changed)); + layout.signal_sensor_state_changed.connect(sigc::mem_fun(this, &Timetable::sensor_state_changed)); layout.signal_block_reserved.connect(sigc::mem_fun(this, &Timetable::block_reserved)); } @@ -97,7 +98,7 @@ void Timetable::tick(const Time::TimeStamp &t, const Time::TimeDelta &) case TRAVEL_TO: { Block *block = &get_sensor(row.get_param(0)); - if(block->get_train()!=&train || block->get_state()get_train()!=&train || block->get_sensor().get_state()(0)); Block *block = &get_sensor(row.get_param(1)); - if(block->get_train()!=other_train || block->get_state()get_train()!=other_train || block->get_sensor().get_state()=Block::MAYBE_ACTIVE) + Block *block = 0; + if(TrackCircuit *tc = dynamic_cast(&sensor)) + block = &tc->get_block(); + else + return; + + if(block==pending_block && block->get_train()==pending_train && state>=Sensor::MAYBE_ACTIVE) { pending_block = 0; current_row = (current_row+1)%rows.size(); diff --git a/source/libr2c2/timetable.h b/source/libr2c2/timetable.h index 84a39cd..f8fc8a0 100644 --- a/source/libr2c2/timetable.h +++ b/source/libr2c2/timetable.h @@ -5,11 +5,12 @@ #include #include #include -#include "block.h" +#include "sensor.h" #include "trainai.h" namespace R2C2 { +class Block; class Track; class Train; class Zone; @@ -100,7 +101,7 @@ private: Block &get_sensor(unsigned); Track &get_turnout(unsigned); Zone &get_zone(const std::string &); - void block_state_changed(Block &, Block::State); + void sensor_state_changed(Sensor &, Sensor::State); void block_reserved(Block &, Train *); void train_advanced(Block &); void event(TrainAI &, const Message &); diff --git a/source/libr2c2/trackcircuit.cpp b/source/libr2c2/trackcircuit.cpp new file mode 100644 index 0000000..2bdfe8b --- /dev/null +++ b/source/libr2c2/trackcircuit.cpp @@ -0,0 +1,13 @@ +#include "block.h" +#include "trackcircuit.h" + +namespace R2C2 { + +TrackCircuit::TrackCircuit(Layout &l, Block &b): + Sensor(l), + block(b) +{ + address = block.get_sensor_id(); +} + +} // namespace R2C2 diff --git a/source/libr2c2/trackcircuit.h b/source/libr2c2/trackcircuit.h new file mode 100644 index 0000000..64e7462 --- /dev/null +++ b/source/libr2c2/trackcircuit.h @@ -0,0 +1,23 @@ +#ifndef LIBR2C2_TRACKCIRCUIT_H_ +#define LIBR2C2_TRACKCIRCUIT_H_ + +#include "sensor.h" + +namespace R2C2 { + +class Block; + +class TrackCircuit: public Sensor +{ +private: + Block █ + +public: + TrackCircuit(Layout &, Block &); + + Block &get_block() const { return block; } +}; + +} // namespace R2C2 + +#endif diff --git a/source/libr2c2/train.cpp b/source/libr2c2/train.cpp index 91387d8..7224247 100644 --- a/source/libr2c2/train.cpp +++ b/source/libr2c2/train.cpp @@ -6,6 +6,7 @@ #include #include #include "aicontrol.h" +#include "block.h" #include "catalogue.h" #include "driver.h" #include "layout.h" @@ -13,6 +14,7 @@ #include "simplecontroller.h" #include "speedquantizer.h" #include "timetable.h" +#include "trackcircuit.h" #include "trackiter.h" #include "tracktype.h" #include "train.h" @@ -60,7 +62,7 @@ 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_block_state_changed.connect(sigc::mem_fun(this, &Train::block_state_changed)); + 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)); @@ -428,9 +430,15 @@ void Train::loco_func_event(unsigned addr, unsigned func, bool state) } } -void Train::block_state_changed(Block &block, Block::State state) +void Train::sensor_state_changed(Sensor &sensor, Sensor::State state) { - if(block.get_train()==this && state==Block::MAYBE_ACTIVE) + Block *block = 0; + if(TrackCircuit *tc = dynamic_cast(&sensor)) + block = &tc->get_block(); + else + return; + + if(block->get_train()==this && state==Sensor::MAYBE_ACTIVE) { if(last_entry_block) { @@ -438,7 +446,7 @@ void Train::block_state_changed(Block &block, Block::State state) if(pure_speed && speed_quantizer && current_speed_step>0) travel_distance = 0; - for(BlockIter i=last_entry_block; &*i!=█ i=i.next()) + for(BlockIter i=last_entry_block; &*i!=block; i=i.next()) { if(i->get_sensor_id()) return; @@ -455,7 +463,7 @@ void Train::block_state_changed(Block &block, Block::State state) } } - last_entry_block = allocator.iter_for(block); + last_entry_block = allocator.iter_for(*block); last_entry_time = Time::now(); pure_speed = true; accurate_position = true; diff --git a/source/libr2c2/train.h b/source/libr2c2/train.h index 42bbc37..ece5b4b 100644 --- a/source/libr2c2/train.h +++ b/source/libr2c2/train.h @@ -5,14 +5,15 @@ #include #include #include -#include "block.h" #include "blockallocator.h" #include "controller.h" +#include "sensor.h" #include "trainai.h" namespace R2C2 { class ArticleNumber; +class Block; class SpeedQuantizer; class Vehicle; class VehicleType; @@ -130,7 +131,7 @@ private: void control_changed(const Controller::Control &); void loco_speed_event(unsigned, unsigned, bool); void loco_func_event(unsigned, unsigned, bool); - void block_state_changed(Block &, Block::State); + void sensor_state_changed(Sensor &, Sensor::State); void halt_event(bool); void block_reserved(const Block &, const Train *); float get_reserved_distance_until(const Block *) const; -- 2.43.0