]> git.tdb.fi Git - r2c2.git/commitdiff
Make AIControl states clearer
authorMikko Rasa <tdb@tdb.fi>
Sun, 21 Nov 2010 21:07:37 +0000 (21:07 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 21 Nov 2010 21:07:37 +0000 (21:07 +0000)
Match the speed of a preceding train to avoid oscillating

source/libr2c2/aicontrol.cpp
source/libr2c2/aicontrol.h
source/libr2c2/train.cpp
source/libr2c2/train.h

index c2f16e38a898a0efbdc702bdfe14fabbe84d82dd..2d48bf764a3f498047a078a34965461fc2985c2d 100644 (file)
@@ -19,8 +19,7 @@ AIControl::AIControl(Train &t, Controller *n):
        train(t),
        next_ctrl(n),
        target_speed(Control::continuous("speed", 0, 1000)),
-       blocked(false),
-       approach(false)
+       state(NORMAL)
 {
        target_speed.set(0);
 
@@ -41,10 +40,10 @@ void AIControl::set_control(const string &n, float v)
                        train.set_active(true);
 
                target_speed.set(v);
-               if(!blocked)
+               if(state!=BLOCKED)
                {
                        float approach_speed = 5*train.get_layout().get_catalogue().get_scale();
-                       if(approach && target_speed.value>approach_speed)
+                       if(state==APPROACH && target_speed.value>approach_speed)
                                next_ctrl->set_control("speed", approach_speed);
                        else
                                next_ctrl->set_control("speed", target_speed.value);
@@ -88,26 +87,36 @@ void AIControl::tick(const Time::TimeDelta &dt)
        float approach_speed = 5*scale;
        float margin = 10*scale;
 
-       if(!blocked && rsv_dist<brake_dist+margin)
-       {
-               blocked = true;
-               next_ctrl->set_control("speed", 0);
-       }
-       else if((!approach && rsv_dist<brake_dist*1.3+approach_margin) || (blocked && rsv_dist>brake_dist+margin*2))
+       State old_state = state;
+
+       if(state==FOLLOW && !train.get_preceding_train())
+               state = NORMAL;
+
+       if(rsv_dist<brake_dist+margin)
+               state = BLOCKED;
+       else if(rsv_dist>brake_dist+margin*2 && rsv_dist<brake_dist*1.3+approach_margin)
+               state = APPROACH;
+       else if(rsv_dist>brake_dist*1.3+approach_margin*2)
+               state = NORMAL;
+
+       if(state==NORMAL && train.get_preceding_train())
+               state = FOLLOW;
+
+       if(state!=old_state || state==FOLLOW)
        {
-               blocked = false;
-               approach = true;
-               if(target_speed.value>approach_speed)
-                       next_ctrl->set_control("speed", approach_speed);
+               float speed_limit = -1;
+               if(state==BLOCKED)
+                       speed_limit = 0;
+               else if(state==APPROACH)
+                       speed_limit = approach_speed;
+               else if(state==FOLLOW)
+                       speed_limit = train.get_preceding_train()->get_speed();
+
+               if(speed_limit>=0 && target_speed.value>speed_limit)
+                       next_ctrl->set_control("speed", speed_limit);
                else
                        next_ctrl->set_control("speed", target_speed.value);
        }
-       else if((blocked || approach) && rsv_dist>brake_dist*1.3+approach_margin*2)
-       {
-               blocked = false;
-               approach = false;
-               next_ctrl->set_control("speed", target_speed.value);
-       }
 
        next_ctrl->tick(dt);
 
index 0d84218875848f69b111cb668ab25348f5150118..9e0808e1b821803179e627c9f1d7536c226b3c49 100644 (file)
@@ -18,11 +18,18 @@ class Train;
 class AIControl: public Controller, public sigc::trackable
 {
 private:
+       enum State
+       {
+               NORMAL,
+               APPROACH,
+               BLOCKED,
+               FOLLOW
+       };
+
        Train &train;
        Controller *next_ctrl;
        Control target_speed;
-       bool blocked;
-       bool approach;
+       State state;
 
 public:
        AIControl(Train &, Controller *);
index ffa436b1d6a0c07795bf876d304077bb08a80fcd..0cbe306234c09b11a9535f1e21fe71673e4bed2e 100644 (file)
@@ -48,6 +48,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p):
        protocol(p),
        priority(0),
        yielding_to(0),
+       preceding_train(0),
        cur_blocks_end(blocks.end()),
        clear_blocks_end(blocks.end()),
        pending_block(0),
@@ -841,6 +842,7 @@ void Train::reserve_more()
        BlockIter start = blocks.back();
 
        pending_block = 0;
+       preceding_train = 0;
 
        // See how many sensor blocks and how much track we already have
        unsigned nsens = 0;
@@ -952,10 +954,15 @@ void Train::reserve_more()
                        bool entry_conflict = (block.entry()==other_exit);
                        bool exit_conflict = (exit==static_cast<unsigned>(other_entry));
                        if(!entry_conflict && !last->get_turnout_id())
+                       {
                                /* The other train is not coming to the blocks we're holding, so we
                                can keep them. */
                                good_end = blocks.end();
 
+                               if(static_cast<unsigned>(other_entry)==block.entry())
+                                       preceding_train = other_train;
+                       }
+
                        int other_prio = other_train->get_priority();
 
                        if(!entry_conflict && !exit_conflict && other_prio<priority)
index 330eadd32e93f6f504963b8429eea4c1d8803334..81f0e2a9e86c700a92486fcdce88159fd8966da1 100644 (file)
@@ -80,6 +80,7 @@ private:
        std::string name;
        int priority;
        const Train *yielding_to;
+       const Train *preceding_train;
        std::vector<Vehicle *> vehicles;
        BlockList blocks;
        BlockList::iterator cur_blocks_end;
@@ -119,6 +120,7 @@ public:
        void set_priority(int);
        void yield_to(const Train &);
        int get_priority() const { return priority; }
+       const Train *get_preceding_train() const { return preceding_train; }
        Controller &get_controller() const { return *controller; }
 
        void add_vehicle(const VehicleType &);