]> git.tdb.fi Git - r2c2.git/commitdiff
Change the control system to separate speed and reverse
authorMikko Rasa <tdb@tdb.fi>
Sun, 26 Sep 2010 19:53:02 +0000 (19:53 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 26 Sep 2010 19:53:02 +0000 (19:53 +0000)
Don't emit signal_arrived until the train has stopped
Slow down for the last stretch at the end of reserved track

source/engineer/trainpanel.cpp
source/engineer/trainpanel.h
source/libmarklin/aicontrol.cpp
source/libmarklin/aicontrol.h
source/libmarklin/controlmodel.h
source/libmarklin/simplephysics.cpp
source/libmarklin/simplephysics.h
source/libmarklin/train.cpp
source/libmarklin/train.h

index 7177489be5e990574ed8be934b33ea169d0d863a..08af8cc0c2cccca519d8050c465d58addd52dd89 100644 (file)
@@ -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)
index 2f1453fcbaf00746e5aa4f8aa90a52cde109d025..9b2a54414618264e2e693ce26912a205da6cb4bf 100644 (file)
@@ -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);
index d5a29c0e540b2ceafbee82151db6e1153c5006ab..eefc7f87f230d586c2a083dbc0741ae0d4b1763d 100644 (file)
@@ -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_dist<brake_dist+margin)
        {
                blocked = true;
                next_model->set_control("speed", 0);
        }
-       else if(blocked && rsv_dist>brake_dist+margin*3)
+       else if((!approach && rsv_dist<brake_dist*1.3+approach_margin) || (blocked && rsv_dist>brake_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()
index 465d2ab95251f1c5a9fb184d9066886a734debff..bcd6cbba6405ea6fef17d2ae078c268f4c10cc71 100644 (file)
@@ -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();
 };
 
index 17bb72ba94253db0b82b73d6d85bbd22d00aa516..3032f6627abf0ba48a52a7d415910b86058e47d1 100644 (file)
@@ -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<void, const std::string &, float> signal_control_changed;
+       sigc::signal<void, const TrainControl &> 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;
index 284e5271b6ae9a06448857a663dbab146e2e2c73..3bcbd5774cf29f634be6d192213a9d53eb9634d4 100644 (file)
@@ -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);
 }
index 64d961b1b54f5dbcf3a97491db786ed83d2c2864..5da6bb89d4d58d2942bb2fc23c3e85c9d63d8c63 100644 (file)
@@ -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 &);
index c53f30f66e6de0f05cca61da9b24f20486579e13..93470997133a6e534736f6f6d71b256e0533bc13 100644 (file)
@@ -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<DataFile::Statement> &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");
index ee66e1d1ca29e0dc38df83e4fc86dc0a3f0b548a..f9ea6f17ae0001b39432e8cd83b57ac8fb4cf9ce 100644 (file)
@@ -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<Msp::DataFile::Statement> &) 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);