train(t),
next_ctrl(n),
target_speed(Control::continuous("speed", 0, 1000)),
- blocked(false),
- approach(false)
+ state(NORMAL)
{
target_speed.set(0);
delete next_ctrl;
}
+const char *AIControl::enumerate_controls(unsigned index) const
+{
+ if(index==0)
+ return target_speed.name.c_str();
+ else
+ {
+ for(--index;; ++index)
+ {
+ const char *ret = next_ctrl->enumerate_controls(index-1);
+ if(!ret || ret!=target_speed.name)
+ return ret;
+ }
+ }
+}
+
void AIControl::set_control(const string &n, float v)
{
- if(n=="speed")
+ if(n==target_speed.name)
{
if(v && !train.is_active())
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);
const Controller::Control &AIControl::get_control(const string &n) const
{
- if(n=="speed")
+ if(n==target_speed.name)
return target_speed;
else
return next_ctrl->get_control(n);
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);