From: Mikko Rasa Date: Sun, 26 Sep 2010 19:53:02 +0000 (+0000) Subject: Change the control system to separate speed and reverse X-Git-Url: https://git.tdb.fi/?a=commitdiff_plain;h=77f8c0e033b9b5e7085de5d22a62128a996a5b2a;p=r2c2.git Change the control system to separate speed and reverse Don't emit signal_arrived until the train has stopped Slow down for the last stretch at the end of reserved track --- diff --git a/source/engineer/trainpanel.cpp b/source/engineer/trainpanel.cpp index 7177489..08af8cc 100644 --- a/source/engineer/trainpanel.cpp +++ b/source/engineer/trainpanel.cpp @@ -106,24 +106,16 @@ TrainPanel::TrainPanel(Engineer &e, const GLtk::Resources &r, Train &t): btn->signal_clicked.connect(sigc::mem_fun(this, &TrainPanel::timetable_clicked)); } -void TrainPanel::speed_slider_changed(double value) -{ - float speed = value/3.6*engineer.get_layout().get_catalogue().get_scale(); - if(!tgl_forward->get_value()) - speed = -speed; - train.set_control("speed", speed); -} - void TrainPanel::train_control_changed(const string &control, float value) { if(control=="speed") { - float speed = abs(value)/engineer.get_layout().get_catalogue().get_scale()*3.6; + float speed = value/engineer.get_layout().get_catalogue().get_scale()*3.6; sld_speed->set_value(speed); lbl_speed->set_text(format("%3.0f", speed)); - if(value) - tgl_forward->set_value(value>0); } + else if(control=="reverse") + tgl_forward->set_value(value==0); } void TrainPanel::train_function_changed(unsigned func, bool value) @@ -188,9 +180,21 @@ void TrainPanel::timetable_clicked() dialog->set_position(geom.x+geom.w, geom.y+geom.h-dialog->get_geometry().h); } -void TrainPanel::forward_toggled(bool /*value*/) +void TrainPanel::speed_slider_changed(double value) { - train.set_control("speed", 0); + float speed = value/3.6*engineer.get_layout().get_catalogue().get_scale(); + train.set_control("speed", speed); +} + +void TrainPanel::forward_toggled(bool value) +{ + if(train.get_speed() || sld_speed->get_value()) + { + train.set_control("speed", 0); + tgl_forward->set_value(!train.get_control("reverse")); + } + else + train.set_control("reverse", !value); } void TrainPanel::func_toggled(bool value, unsigned func) diff --git a/source/engineer/trainpanel.h b/source/engineer/trainpanel.h index 2f1453f..9b2a544 100644 --- a/source/engineer/trainpanel.h +++ b/source/engineer/trainpanel.h @@ -36,7 +36,6 @@ private: public: TrainPanel(Engineer &, const Msp::GLtk::Resources &, Marklin::Train &); private: - void speed_slider_changed(double); void train_control_changed(const std::string &, float); void train_function_changed(unsigned, bool); void train_route_changed(const Marklin::Route *); @@ -46,6 +45,7 @@ private: void route_clicked(); void goto_clicked(); void timetable_clicked(); + void speed_slider_changed(double); void forward_toggled(bool); void func_toggled(bool, unsigned); void place(Marklin::Track *, unsigned); diff --git a/source/libmarklin/aicontrol.cpp b/source/libmarklin/aicontrol.cpp index d5a29c0..eefc7f8 100644 --- a/source/libmarklin/aicontrol.cpp +++ b/source/libmarklin/aicontrol.cpp @@ -18,12 +18,14 @@ namespace Marklin { AIControl::AIControl(Train &t, ControlModel *n): train(t), next_model(n), - target_speed(TrainControl::continuous("speed", -1000, 1000)), - blocked(false) + target_speed(TrainControl::continuous("speed", 0, 1000)), + blocked(false), + approach(false) { target_speed.set(0); train.signal_arrived.connect(sigc::mem_fun(this, &AIControl::arrived)); + next_model->signal_control_changed.connect(sigc::mem_fun(this, &AIControl::control_changed)); } AIControl::~AIControl() @@ -40,9 +42,15 @@ void AIControl::set_control(const string &n, float v) target_speed.set(v); if(!blocked) - next_model->set_control("speed", target_speed.value); - - signal_control_changed.emit(n, target_speed.value); + { + float approach_speed = 5*train.get_layout().get_catalogue().get_scale(); + if(approach && target_speed.value>approach_speed) + next_model->set_control("speed", approach_speed); + else + next_model->set_control("speed", target_speed.value); + } + + signal_control_changed.emit(target_speed); } else next_model->set_control(n, v); @@ -63,10 +71,7 @@ float AIControl::get_speed() const bool AIControl::get_reverse() const { - if(float ns = next_model->get_speed()) - return ns<0; - else - return target_speed.value<0; + return next_model->get_reverse(); } float AIControl::get_braking_distance() const @@ -76,17 +81,31 @@ float AIControl::get_braking_distance() const void AIControl::tick(const Time::TimeDelta &dt) { + float scale = train.get_layout().get_catalogue().get_scale(); float rsv_dist = train.get_reserved_distance(); - float brake_dist = next_model->get_braking_distance()*1.15; - float margin = 25*train.get_layout().get_catalogue().get_scale(); + float brake_dist = next_model->get_braking_distance(); + float approach_margin = 50*scale; + float approach_speed = 5*scale; + float margin = 10*scale; + if(!blocked && rsv_distset_control("speed", 0); } - else if(blocked && rsv_dist>brake_dist+margin*3) + else if((!approach && rsv_distbrake_dist+margin*2)) + { + blocked = false; + approach = true; + if(target_speed.value>approach_speed) + next_model->set_control("speed", approach_speed); + else + next_model->set_control("speed", target_speed.value); + } + else if((blocked || approach) && rsv_dist>brake_dist*1.3+approach_margin*2) { blocked = false; + approach = false; next_model->set_control("speed", target_speed.value); } @@ -96,10 +115,10 @@ void AIControl::tick(const Time::TimeDelta &dt) train.set_active(false); } -void AIControl::control_changed(const string &n, float v) +void AIControl::control_changed(const TrainControl &ctrl) { - if(n!="speed") - signal_control_changed.emit(n, v); + if(ctrl.name!="speed") + signal_control_changed.emit(ctrl); } void AIControl::arrived() diff --git a/source/libmarklin/aicontrol.h b/source/libmarklin/aicontrol.h index 465d2ab..bcd6cbb 100644 --- a/source/libmarklin/aicontrol.h +++ b/source/libmarklin/aicontrol.h @@ -23,6 +23,7 @@ private: ControlModel *next_model; TrainControl target_speed; bool blocked; + bool approach; public: AIControl(Train &, ControlModel *); @@ -38,7 +39,7 @@ public: virtual void tick(const Msp::Time::TimeDelta &); private: - void control_changed(const std::string &, float); + void control_changed(const TrainControl &); void arrived(); }; diff --git a/source/libmarklin/controlmodel.h b/source/libmarklin/controlmodel.h index 17bb72b..3032f66 100644 --- a/source/libmarklin/controlmodel.h +++ b/source/libmarklin/controlmodel.h @@ -14,12 +14,16 @@ Distributed under the GPL namespace Marklin { -class TrainControl; +struct TrainControl; +/** +Interface class for train control models. Takes input through a uniform named +control interface. Provides information about train movement on output. +*/ class ControlModel { public: - sigc::signal signal_control_changed; + sigc::signal signal_control_changed; protected: ControlModel() { } @@ -29,8 +33,13 @@ public: virtual void set_control(const std::string &, float) = 0; virtual const TrainControl &get_control(const std::string &) const = 0; + /** Returns the current speed. Always non-negative. */ virtual float get_speed() const = 0; + + /** Returns true if traveling in reverse. */ virtual bool get_reverse() const = 0; + + /** Determines the distance required to come to a full stop. */ virtual float get_braking_distance() const = 0; virtual void tick(const Msp::Time::TimeDelta &) = 0; diff --git a/source/libmarklin/simplephysics.cpp b/source/libmarklin/simplephysics.cpp index 284e527..3bcbd57 100644 --- a/source/libmarklin/simplephysics.cpp +++ b/source/libmarklin/simplephysics.cpp @@ -15,7 +15,8 @@ using namespace Msp; namespace Marklin { SimplePhysics::SimplePhysics(): - target_speed(TrainControl::continuous("speed", -1000, 1000)), + target_speed(TrainControl::continuous("speed", 0, 1000)), + reverse(TrainControl::binary("reverse")), accel(0.07), speed(0) { @@ -27,7 +28,14 @@ void SimplePhysics::set_control(const string &name, float v) if(name=="speed") { target_speed.set(v); - signal_control_changed.emit(name, target_speed.value); + signal_control_changed.emit(target_speed); + } + else if(name=="reverse") + { + if(target_speed.value || speed) + throw InvalidState("Must be stopped to change reverse"); + reverse.set(v); + signal_control_changed.emit(reverse); } } @@ -35,6 +43,8 @@ const TrainControl &SimplePhysics::get_control(const string &name) const { if(name=="speed") return target_speed; + else if(name=="reverse") + return reverse; else throw KeyError("Unknown control", name); } diff --git a/source/libmarklin/simplephysics.h b/source/libmarklin/simplephysics.h index 64d961b..5da6bb8 100644 --- a/source/libmarklin/simplephysics.h +++ b/source/libmarklin/simplephysics.h @@ -18,6 +18,7 @@ class SimplePhysics: public ControlModel { private: TrainControl target_speed; + TrainControl reverse; float accel; float speed; @@ -28,7 +29,7 @@ public: virtual const TrainControl &get_control(const std::string &) const; virtual float get_speed() const { return speed; } - virtual bool get_reverse() const { return speed<0; } + virtual bool get_reverse() const { return reverse.value; } virtual float get_braking_distance() const; virtual void tick(const Msp::Time::TimeDelta &); diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index c53f30f..9347099 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -66,7 +66,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a): layout.get_driver().signal_halt.connect(sigc::mem_fun(this, &Train::halt_event)); - control->signal_control_changed.connect(signal_control_changed); + control->signal_control_changed.connect(sigc::mem_fun(this, &Train::control_changed)); } Train::~Train() @@ -163,6 +163,16 @@ void Train::set_function(unsigned func, bool state) layout.get_driver().set_loco_function(address+1, func-4, state); } +float Train::get_control(const string &ctrl) const +{ + return control->get_control(ctrl).value; +} + +float Train::get_speed() const +{ + return control->get_speed(); +} + bool Train::get_function(unsigned func) const { return (functions>>func)&1; @@ -358,7 +368,7 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) timetable->tick(t); control->tick(dt); float speed = control->get_speed(); - unsigned speed_notch = find_speed(abs(speed)); + unsigned speed_notch = find_speed(speed); if(control->get_reverse()!=reverse) { @@ -408,8 +418,11 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) } } } - else if(end_of_route) + else if(end_of_route && rsv_blocks.empty()) + { + signal_arrived.emit(); set_route(0); + } if(!cur_blocks.empty() && !cur_blocks.front().block->get_sensor_id()) { @@ -501,6 +514,11 @@ void Train::save(list &st) const } } +void Train::control_changed(const TrainControl &ctrl) +{ + signal_control_changed.emit(ctrl.name, ctrl.value); +} + void Train::loco_speed_event(unsigned addr, unsigned speed, bool) { if(addr==address) @@ -609,11 +627,7 @@ void Train::sensor_event(unsigned addr, bool state) // Try to get more blocks if we're moving if(active) - { - unsigned nsens = reserve_more(); - if(!nsens && end_of_route) - signal_arrived.emit(); - } + reserve_more(); } else if(result==3) layout.emergency("Sensor for "+name+" triggered out of order"); diff --git a/source/libmarklin/train.h b/source/libmarklin/train.h index ee66e1d..f9ea6f1 100644 --- a/source/libmarklin/train.h +++ b/source/libmarklin/train.h @@ -20,6 +20,7 @@ class Route; class Timetable; class Vehicle; class VehicleType; +struct TrainControl; class Train: public sigc::trackable { @@ -109,7 +110,7 @@ public: const std::string &get_name() const { return name; } void set_priority(int); int get_priority() const { return priority; } - ControlModel &get_control() const { return *control; } + ControlModel &get_control_model() const { return *control; } void add_vehicle(const VehicleType &); void remove_vehicle(unsigned); @@ -121,6 +122,7 @@ public: void set_active(bool); void set_function(unsigned, bool); float get_control(const std::string &) const; + float get_speed() const; bool is_active() const { return active; } bool get_function(unsigned) const; unsigned get_functions() const { return functions; } @@ -143,6 +145,7 @@ public: void save(std::list &) const; private: + void control_changed(const TrainControl &); void loco_speed_event(unsigned, unsigned, bool); void loco_func_event(unsigned, unsigned, bool); void sensor_event(unsigned, bool);