From 7839b7c3d782abb5c98a24d51cae109407068c02 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 22 May 2009 21:49:41 +0000 Subject: [PATCH] Allow intercepting and denying turnout route and locomotive speed changes Reroute train when a reserved turnout changes its route Various minor fixes --- source/engineer/engineer.cpp | 14 ++++++- source/libmarklin/block.cpp | 3 +- source/libmarklin/block.h | 4 +- source/libmarklin/control.h | 3 +- source/libmarklin/except.h | 31 ++++++++++++++ source/libmarklin/locomotive.cpp | 6 ++- source/libmarklin/locomotive.h | 3 +- source/libmarklin/train.cpp | 72 ++++++++++++++++++++++++++++++-- source/libmarklin/train.h | 2 + source/libmarklin/turnout.cpp | 3 +- source/libmarklin/turnout.h | 1 + 11 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 source/libmarklin/except.h diff --git a/source/engineer/engineer.cpp b/source/engineer/engineer.cpp index 581a301..be4c050 100644 --- a/source/engineer/engineer.cpp +++ b/source/engineer/engineer.cpp @@ -20,6 +20,7 @@ Distributed under the GPL #include #include #include +#include "libmarklin/except.h" #include "libmarklin/tracktype.h" #include "engineer.h" #include "mainpanel.h" @@ -99,7 +100,8 @@ Engineer::Engineer(int argc, char **argv): Engineer::~Engineer() { - trfc_mgr->save("engineer.state"); + if(!simulate) + trfc_mgr->save("engineer.state"); delete trfc_mgr; } @@ -352,7 +354,15 @@ void Engineer::button_press(int x, int y, unsigned btn, unsigned) if(unsigned tid=track->get_track().get_turnout_id()) { Turnout &turnout=control.get_turnout(tid); - turnout.set_route((turnout.get_route()+1)%track->get_track().get_type().get_n_routes()); + try + { + turnout.set_route((turnout.get_route()+1)%track->get_track().get_type().get_n_routes()); + main_panel->set_status_text(format("Turnout %d switched", turnout.get_address())); + } + catch(const TurnoutBusy &e) + { + main_panel->set_status_text(e.what()); + } } else if(simulate) { diff --git a/source/libmarklin/block.cpp b/source/libmarklin/block.cpp index 94be126..ee0a48c 100644 --- a/source/libmarklin/block.cpp +++ b/source/libmarklin/block.cpp @@ -21,6 +21,7 @@ Block::Block(TrafficManager &tm, Track &start): trfc_mgr(tm), id(next_id++), sensor_id(start.get_sensor_id()), + turnout_id(start.get_turnout_id()), train(0) { tracks.insert(&start); @@ -37,7 +38,7 @@ Block::Block(TrafficManager &tm, Track &start): for(unsigned i=0; iget_sensor_id()==sensor_id && !links[i]->get_turnout_id() && !track->get_turnout_id()) + if(links[i]->get_sensor_id()==sensor_id && links[i]->get_turnout_id()==turnout_id) { queue.push_back(links[i]); tracks.insert(links[i]); diff --git a/source/libmarklin/block.h b/source/libmarklin/block.h index bdbcc3f..68c57b8 100644 --- a/source/libmarklin/block.h +++ b/source/libmarklin/block.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa +Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -34,6 +34,7 @@ private: TrafficManager &trfc_mgr; unsigned id; unsigned sensor_id; + unsigned turnout_id; std::set tracks; std::vector endpoints; const Train *train; @@ -42,6 +43,7 @@ public: Block(TrafficManager &, Track &); unsigned get_sensor_id() const { return sensor_id; } + unsigned get_turnout_id() const { return turnout_id; } const std::set &get_tracks() const { return tracks; } const std::vector &get_endpoints() const { return endpoints; } int get_endpoint_by_link(const Block &) const; diff --git a/source/libmarklin/control.h b/source/libmarklin/control.h index 0ec3d5b..1d19263 100644 --- a/source/libmarklin/control.h +++ b/source/libmarklin/control.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa +Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -47,6 +47,7 @@ public: void set_power(bool); bool get_power() const { return power; } void set_debug(bool); + const std::map &get_turnouts() const { return turnouts; } const std::map &get_sensors() const { return sensors; } unsigned get_queue_length() const { return queue.size(); } void open(const std::string &); diff --git a/source/libmarklin/except.h b/source/libmarklin/except.h new file mode 100644 index 0000000..85fe431 --- /dev/null +++ b/source/libmarklin/except.h @@ -0,0 +1,31 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2009 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#ifndef LIBMARKLIN_EXCEPT_H_ +#define LIBMARKLIN_EXCEPT_H_ + +#include + +namespace Marklin { + +class Train; + +class TurnoutBusy: public Msp::Exception +{ +private: + Train *train; + +public: + TurnoutBusy(Train *t): Exception("Turnout is busy"), train(t) { } + virtual ~TurnoutBusy() throw() { } + + Train *get_train() const throw() { return train; } +}; + +} + +#endif diff --git a/source/libmarklin/locomotive.cpp b/source/libmarklin/locomotive.cpp index a42d8d7..32f2ecc 100644 --- a/source/libmarklin/locomotive.cpp +++ b/source/libmarklin/locomotive.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa +Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -33,8 +33,10 @@ Locomotive::Locomotive(const LocoType &t, Control &c, unsigned a): void Locomotive::set_speed(unsigned spd) { - speed=min(spd, 14U); + spd=min(spd, 14U); + signal_speed_changing.emit(spd); + speed=spd; send_command(false); signal_speed_changed.emit(speed); diff --git a/source/libmarklin/locomotive.h b/source/libmarklin/locomotive.h index e3cbf7d..89b275e 100644 --- a/source/libmarklin/locomotive.h +++ b/source/libmarklin/locomotive.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa +Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -30,6 +30,7 @@ private: unsigned funcs; public: + sigc::signal signal_speed_changing; sigc::signal signal_speed_changed; sigc::signal signal_function_changed; diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index f8ef171..7d6afba 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -10,6 +10,7 @@ Distributed under the GPL #include #include #include "control.h" +#include "except.h" #include "tracktype.h" #include "trafficmanager.h" #include "train.h" @@ -38,6 +39,13 @@ Train::Train(TrafficManager &tm, Locomotive &l): const map &sensors=trfc_mgr.get_control().get_sensors(); for(map::const_iterator i=sensors.begin(); i!=sensors.end(); ++i) i->second->signal_state_changed.connect(sigc::bind(sigc::mem_fun(this, &Train::sensor_event), i->second)); + + const map &turnouts=trfc_mgr.get_control().get_turnouts(); + for(map::const_iterator i=turnouts.begin(); i!=turnouts.end(); ++i) + { + i->second->signal_route_changing.connect(sigc::bind(sigc::mem_fun(this, &Train::turnout_route_changing), i->second)); + i->second->signal_route_changed.connect(sigc::bind(sigc::mem_fun(this, &Train::turnout_route_changed), i->second)); + } } void Train::set_name(const string &n) @@ -60,6 +68,8 @@ void Train::set_speed(unsigned speed) i->block->reserve(0); rsv_blocks.clear(); } + else + reserve_more(); update_speed(); pure_speed=false; @@ -93,16 +103,24 @@ void Train::place(Block *block, unsigned entry) bool Train::free_block(Block *block) { + unsigned nsens=0; for(list::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + { if(i->block==block) { + if(nsens<1) + return false; while(i!=rsv_blocks.end()) { i->block->reserve(0); i=rsv_blocks.erase(i); } + update_speed(); return true; } + else if(i->block->get_sensor_id()) + ++nsens; + } return false; } @@ -110,7 +128,10 @@ bool Train::free_block(Block *block) void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) { if(try_reserve && t>try_reserve) + { + reserve_more(); update_speed(); + } if(cur_track) { @@ -193,7 +214,10 @@ void Train::sensor_event(bool state, Sensor *sensor) set_position(i->block->get_endpoints()[i->entry]); if(target_speed) + { + reserve_more(); update_speed(); + } } else { @@ -212,6 +236,44 @@ void Train::sensor_event(bool state, Sensor *sensor) } } +void Train::turnout_route_changing(unsigned, Turnout *turnout) +{ + unsigned tid=turnout->get_address(); + for(list::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i) + if(i->block->get_turnout_id()==tid) + throw TurnoutBusy(this); + + unsigned nsens=0; + for(list::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + { + if(i->block->get_turnout_id()==tid) + { + if(nsens<1) + throw TurnoutBusy(this); + break; + } + else if(i->block->get_sensor_id()) + ++nsens; + } +} + +void Train::turnout_route_changed(unsigned, Turnout *turnout) +{ + unsigned tid=turnout->get_address(); + for(list::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + if(i->block->get_turnout_id()==tid) + { + while(i!=rsv_blocks.end()) + { + i->block->reserve(0); + i=rsv_blocks.erase(i); + } + reserve_more(); + update_speed(); + return; + } +} + unsigned Train::reserve_more() { BlockRef *last=0; @@ -274,15 +336,19 @@ void Train::update_speed() } else { - unsigned n=reserve_more(); - if(n==0) + unsigned nsens=0; + for(list::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + if(i->block->get_sensor_id()) + ++nsens; + + if(nsens==0) { loco.set_speed(0); pure_speed=false; try_reserve=Time::now()+2*Time::sec; set_status("Blocked"); } - else if(n==1) + else if(nsens==1 && target_speed>3) { loco.set_speed(3); pure_speed=false; diff --git a/source/libmarklin/train.h b/source/libmarklin/train.h index b84844a..d95d4c4 100644 --- a/source/libmarklin/train.h +++ b/source/libmarklin/train.h @@ -76,6 +76,8 @@ public: void save(std::list &) const; private: void sensor_event(bool, Sensor *); + void turnout_route_changing(unsigned, Turnout *); + void turnout_route_changed(unsigned, Turnout *); unsigned reserve_more(); void update_speed(); void set_status(const std::string &); diff --git a/source/libmarklin/turnout.cpp b/source/libmarklin/turnout.cpp index 60bab12..3e6e10d 100644 --- a/source/libmarklin/turnout.cpp +++ b/source/libmarklin/turnout.cpp @@ -41,8 +41,9 @@ Turnout::Turnout(Control &c, unsigned a, bool d): void Turnout::set_route(unsigned r) { - route=r; + signal_route_changing.emit(r); + route=r; command(true); control.set_timer(200*Time::msec).signal_timeout.connect(sigc::mem_fun(this, &Turnout::switch_timeout)); diff --git a/source/libmarklin/turnout.h b/source/libmarklin/turnout.h index ae68654..616a7fe 100644 --- a/source/libmarklin/turnout.h +++ b/source/libmarklin/turnout.h @@ -28,6 +28,7 @@ private: bool dual; public: + sigc::signal signal_route_changing; sigc::signal signal_route_changed; Turnout(Control &, unsigned, bool =false); -- 2.45.2