11 AIControl::AIControl(Train &t):
15 pending_reverse(false),
19 train.signal_ai_event.connect(sigc::mem_fun(this, &AIControl::event));
22 void AIControl::set_target_speed(float s)
24 if(s && !train.is_active())
25 train.set_active(true);
29 signal_event.emit(Message("target-speed-changed", target_speed));
32 void AIControl::set_reverse(bool r)
35 if(train.get_controller().get_speed())
40 train.set_control("reverse", reverse);
41 signal_event.emit(Message("reverse-changed", reverse));
45 void AIControl::message(const Message &msg)
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);
55 void AIControl::tick(const Time::TimeStamp &, const Time::TimeDelta &)
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;
64 State old_state = state;
66 if(state==FOLLOW && !train.get_preceding_train())
69 if(rsv_dist<brake_dist+margin)
71 else if(rsv_dist>brake_dist+margin*2 && rsv_dist<brake_dist*1.3+approach_margin)
73 else if(rsv_dist>brake_dist*1.3+approach_margin*2)
76 if(state==NORMAL && train.get_preceding_train())
79 if(state!=old_state || state==FOLLOW || need_update)
81 float speed_limit = -1;
84 else if(state==APPROACH)
85 speed_limit = approach_speed;
86 else if(state==FOLLOW && train.get_preceding_train()->is_active())
87 speed_limit = train.get_preceding_train()->get_speed();
89 if(speed_limit>=0 && target_speed>speed_limit)
90 train.set_control("speed", speed_limit);
92 train.set_control("speed", target_speed);
97 if(pending_reverse!=reverse && !train.get_controller().get_speed())
99 reverse = pending_reverse;
100 train.set_control("reverse", reverse);
103 if(!target_speed && !train.get_controller().get_speed() && train.is_active())
104 train.set_active(false);
107 void AIControl::event(TrainAI &, const Message &ev)
109 if(ev.type=="arrived")