summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
7e27b31)
Match the speed of a preceding train to avoid oscillating
train(t),
next_ctrl(n),
target_speed(Control::continuous("speed", 0, 1000)),
train(t),
next_ctrl(n),
target_speed(Control::continuous("speed", 0, 1000)),
- blocked(false),
- approach(false)
train.set_active(true);
target_speed.set(v);
train.set_active(true);
target_speed.set(v);
{
float approach_speed = 5*train.get_layout().get_catalogue().get_scale();
{
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);
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;
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
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);
- }
class AIControl: public Controller, public sigc::trackable
{
private:
class AIControl: public Controller, public sigc::trackable
{
private:
+ enum State
+ {
+ NORMAL,
+ APPROACH,
+ BLOCKED,
+ FOLLOW
+ };
+
Train &train;
Controller *next_ctrl;
Control target_speed;
Train &train;
Controller *next_ctrl;
Control target_speed;
- bool blocked;
- bool approach;
public:
AIControl(Train &, Controller *);
public:
AIControl(Train &, Controller *);
protocol(p),
priority(0),
yielding_to(0),
protocol(p),
priority(0),
yielding_to(0),
cur_blocks_end(blocks.end()),
clear_blocks_end(blocks.end()),
pending_block(0),
cur_blocks_end(blocks.end()),
clear_blocks_end(blocks.end()),
pending_block(0),
BlockIter start = blocks.back();
pending_block = 0;
BlockIter start = blocks.back();
pending_block = 0;
// See how many sensor blocks and how much track we already have
unsigned nsens = 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())
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();
/* 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)
int other_prio = other_train->get_priority();
if(!entry_conflict && !exit_conflict && other_prio<priority)
std::string name;
int priority;
const Train *yielding_to;
std::string name;
int priority;
const Train *yielding_to;
+ const Train *preceding_train;
std::vector<Vehicle *> vehicles;
BlockList blocks;
BlockList::iterator cur_blocks_end;
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; }
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 &);
Controller &get_controller() const { return *controller; }
void add_vehicle(const VehicleType &);