]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/aicontrol.cpp
Fix a segfault in removing vehicles when creating a new train
[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, Controller *n):
19         train(t),
20         next_ctrl(n),
21         target_speed(Control::continuous("speed", 0, 1000)),
22         blocked(false),
23         approach(false)
24 {
25         target_speed.set(0);
26
27         train.signal_arrived.connect(sigc::mem_fun(this, &AIControl::arrived));
28         next_ctrl->signal_control_changed.connect(sigc::mem_fun(this, &AIControl::control_changed));
29 }
30
31 AIControl::~AIControl()
32 {
33         delete next_ctrl;
34 }
35
36 void AIControl::set_control(const string &n, float v)
37 {
38         if(n=="speed")
39         {
40                 if(v && !train.is_active())
41                         train.set_active(true);
42
43                 target_speed.set(v);
44                 if(!blocked)
45                 {
46                         float approach_speed = 5*train.get_layout().get_catalogue().get_scale();
47                         if(approach && target_speed.value>approach_speed)
48                                 next_ctrl->set_control("speed", approach_speed);
49                         else
50                                 next_ctrl->set_control("speed", target_speed.value);
51                 }
52
53                 signal_control_changed.emit(target_speed);
54         }
55         else
56                 next_ctrl->set_control(n, v);
57 }
58
59 const Controller::Control &AIControl::get_control(const string &n) const
60 {
61         if(n=="speed")
62                 return target_speed;
63         else
64                 return next_ctrl->get_control(n);
65 }
66
67 float AIControl::get_speed() const
68 {
69         return next_ctrl->get_speed();
70 }
71
72 bool AIControl::get_reverse() const
73 {
74         return next_ctrl->get_reverse();
75 }
76
77 float AIControl::get_braking_distance() const
78 {
79         return next_ctrl->get_braking_distance();
80 }
81
82 void AIControl::tick(const Time::TimeDelta &dt)
83 {
84         float scale = train.get_layout().get_catalogue().get_scale();
85         float rsv_dist = train.get_reserved_distance();
86         float brake_dist = next_ctrl->get_braking_distance();
87         float approach_margin = 50*scale;
88         float approach_speed = 5*scale;
89         float margin = 10*scale;
90
91         if(!blocked && rsv_dist<brake_dist+margin)
92         {
93                 blocked = true;
94                 next_ctrl->set_control("speed", 0);
95         }
96         else if((!approach && rsv_dist<brake_dist*1.3+approach_margin) || (blocked && rsv_dist>brake_dist+margin*2))
97         {
98                 blocked = false;
99                 approach = true;
100                 if(target_speed.value>approach_speed)
101                         next_ctrl->set_control("speed", approach_speed);
102                 else
103                         next_ctrl->set_control("speed", target_speed.value);
104         }
105         else if((blocked || approach) && rsv_dist>brake_dist*1.3+approach_margin*2)
106         {
107                 blocked = false;
108                 approach = false;
109                 next_ctrl->set_control("speed", target_speed.value);
110         }
111
112         next_ctrl->tick(dt);
113
114         if(!target_speed.value && !next_ctrl->get_speed() && train.is_active())
115                 train.set_active(false);
116 }
117
118 void AIControl::control_changed(const Control &ctrl)
119 {
120         if(ctrl.name!="speed")
121                 signal_control_changed.emit(ctrl);
122 }
123
124 void AIControl::arrived()
125 {
126         set_control("speed", 0);
127 }
128
129 } // namespace Marklin