]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/aicontrol.cpp
Export AI control parameters over the network
[r2c2.git] / source / libr2c2 / aicontrol.cpp
1 #include "aicontrol.h"
2 #include "catalogue.h"
3 #include "layout.h"
4 #include "train.h"
5
6 using namespace std;
7 using namespace Msp;
8
9 namespace R2C2 {
10
11 AIControl::AIControl(Train &t):
12         TrainAI(t),
13         target_speed(0),
14         reverse(false),
15         pending_reverse(false),
16         state(NORMAL),
17         need_update(false)
18 {
19         train.signal_ai_event.connect(sigc::mem_fun(this, &AIControl::event));
20 }
21
22 void AIControl::set_target_speed(float s)
23 {
24         target_speed = s;
25         need_update = true;
26         signal_event.emit(Message("target-speed-changed", target_speed));
27 }
28
29 void AIControl::set_reverse(bool r)
30 {
31         pending_reverse = r;
32         if(r==reverse)
33                 return;
34
35         if(train.get_controller().get_speed())
36                 set_target_speed(0);
37         else
38         {
39                 reverse = r;
40                 train.set_control("reverse", reverse);
41                 signal_event.emit(Message("reverse-changed", reverse));
42         }
43 }
44
45 void AIControl::message(const Message &msg)
46 {
47         if(msg.type=="set-target-speed")
48                 set_target_speed(msg.value.value<float>());
49         else if(msg.type=="set-reverse")
50                 set_reverse(msg.value.value<bool>());
51         else if(msg.type=="toggle-reverse")
52                 set_reverse(!reverse);
53 }
54
55 void AIControl::tick(const Time::TimeDelta &)
56 {
57         float scale = train.get_layout().get_catalogue().get_scale();
58         float rsv_dist = train.get_reserved_distance();
59         float brake_dist = train.get_controller().get_braking_distance();
60         float approach_margin = 50*scale;
61         float approach_speed = 5*scale;
62         float margin = 1*scale;
63
64         State old_state = state;
65
66         if(state==FOLLOW && !train.get_preceding_train())
67                 state = NORMAL;
68
69         if(rsv_dist<brake_dist+margin)
70                 state = BLOCKED;
71         else if(rsv_dist>brake_dist+margin*2 && rsv_dist<brake_dist*1.3+approach_margin)
72                 state = APPROACH;
73         else if(rsv_dist>brake_dist*1.3+approach_margin*2)
74                 state = NORMAL;
75
76         if(state==NORMAL && train.get_preceding_train())
77                 state = FOLLOW;
78
79         if(state!=old_state || state==FOLLOW || need_update)
80         {
81                 float speed_limit = -1;
82                 if(state==BLOCKED)
83                         speed_limit = 0;
84                 else if(state==APPROACH)
85                         speed_limit = approach_speed;
86                 else if(state==FOLLOW && train.get_preceding_train()->get_block_allocator().is_active())
87                         speed_limit = train.get_preceding_train()->get_speed();
88
89                 if(speed_limit>=0 && target_speed>speed_limit)
90                         train.set_control("speed", speed_limit);
91                 else
92                         train.set_control("speed", target_speed);
93
94                 need_update = false;
95         }
96
97         if(pending_reverse!=reverse && !train.get_controller().get_speed())
98         {
99                 reverse = pending_reverse;
100                 train.set_control("reverse", reverse);
101         }
102 }
103
104 bool AIControl::has_intent_to_move() const
105 {
106         return target_speed;
107 }
108
109 void AIControl::event(TrainAI &, const Message &ev)
110 {
111         if(ev.type=="arrived")
112                 set_target_speed(0);
113 }
114
115 } // namespace R2C2