train(t),
next_ctrl(n),
target_speed(Control::continuous("speed", 0, 1000)),
- blocked(false),
- approach(false)
+ state(NORMAL)
{
target_speed.set(0);
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);
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);
protocol(p),
priority(0),
yielding_to(0),
+ preceding_train(0),
cur_blocks_end(blocks.end()),
clear_blocks_end(blocks.end()),
pending_block(0),
BlockIter start = blocks.back();
pending_block = 0;
+ preceding_train = 0;
// See how many sensor blocks and how much track we already have
unsigned nsens = 0;
bool entry_conflict = (block.entry()==other_exit);
bool exit_conflict = (exit==static_cast<unsigned>(other_entry));
if(!entry_conflict && !last->get_turnout_id())
+ {
/* The other train is not coming to the blocks we're holding, so we
can keep them. */
good_end = blocks.end();
+ if(static_cast<unsigned>(other_entry)==block.entry())
+ preceding_train = other_train;
+ }
+
int other_prio = other_train->get_priority();
if(!entry_conflict && !exit_conflict && other_prio<priority)
std::string name;
int priority;
const Train *yielding_to;
+ const Train *preceding_train;
std::vector<Vehicle *> vehicles;
BlockList blocks;
BlockList::iterator cur_blocks_end;
void set_priority(int);
void yield_to(const Train &);
int get_priority() const { return priority; }
+ const Train *get_preceding_train() const { return preceding_train; }
Controller &get_controller() const { return *controller; }
void add_vehicle(const VehicleType &);