]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/aicontrol.cpp
b97b0374add45037a986ca047d7e9354c0d4a528
[r2c2.git] / source / libmarklin / aicontrol.cpp
1 /* $Id$
2
3 This file is part of the MSP Märklin suite
4 Copyright © 2010  Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
6 */
7
8 #include "aicontrol.h"
9 #include "catalogue.h"
10 #include "layout.h"
11 #include "train.h"
12
13 using namespace std;
14 using namespace Msp;
15
16 namespace Marklin {
17
18 AIControl::AIControl(Train &t, ControlModel *n):
19         train(t),
20         next_model(n),
21         target_speed(TrainControl::continuous("speed", -1000, 1000)),
22         blocked(false)
23 {
24         target_speed.set(0);
25
26         train.signal_arrived.connect(sigc::mem_fun(this, &AIControl::arrived));
27 }
28
29 AIControl::~AIControl()
30 {
31         delete next_model;
32 }
33
34 void AIControl::set_control(const string &n, float v)
35 {
36         if(n=="speed")
37         {
38                 if(v && !train.is_active())
39                         train.set_active(true);
40
41                 target_speed.set(v);
42                 if(!blocked)
43                         next_model->set_control("speed", target_speed.value);
44
45                 signal_control_changed.emit(n, target_speed.value);
46         }
47         else
48                 next_model->set_control(n, v);
49 }
50
51 const TrainControl &AIControl::get_control(const string &n) const
52 {
53         if(n=="speed")
54                 return target_speed;
55         else
56                 return next_model->get_control(n);
57 }
58
59 float AIControl::get_speed() const
60 {
61         return next_model->get_speed();
62 }
63
64 float AIControl::get_braking_distance() const
65 {
66         return next_model->get_braking_distance();
67 }
68
69 void AIControl::tick(const Time::TimeDelta &dt)
70 {
71         float rsv_dist = train.get_reserved_distance();
72         float brake_dist = next_model->get_braking_distance()*1.15;
73         float margin = 25*train.get_layout().get_catalogue().get_scale();
74         if(!blocked && rsv_dist<brake_dist+margin)
75         {
76                 blocked = true;
77                 next_model->set_control("speed", 0);
78         }
79         else if(blocked && rsv_dist>brake_dist+margin*3)
80         {
81                 blocked = false;
82                 next_model->set_control("speed", target_speed.value);
83         }
84
85         next_model->tick(dt);
86
87         if(!target_speed.value && !next_model->get_speed() && train.is_active())
88                 train.set_active(false);
89 }
90
91 void AIControl::control_changed(const string &n, float v)
92 {
93         if(n!="speed")
94                 signal_control_changed.emit(n, v);
95 }
96
97 void AIControl::arrived()
98 {
99         set_control("speed", 0);
100 }
101
102 } // namespace Marklin