namespace Marklin {
-Train::Train(Layout &l, const VehicleType &t, unsigned a):
+Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p):
layout(l),
loco_type(t),
address(a),
+ protocol(p),
priority(0),
yielding_to(0),
cur_blocks_end(blocks.end()),
controller(new AIControl(*this, new SimpleController)),
timetable(0),
active(false),
- current_speed(0),
+ current_speed_step(0),
speed_changing(false),
reverse(false),
functions(0),
status("Unplaced"),
travel_dist(0),
pure_speed(false),
- real_speed(15),
+ real_speed(layout.get_driver().get_protocol_speed_steps(protocol)+1),
accurate_position(false),
overshoot_dist(false)
{
layout.add_train(*this);
- layout.get_driver().add_loco(address);
+ layout.get_driver().add_loco(address, protocol);
layout.get_driver().signal_loco_speed.connect(sigc::mem_fun(this, &Train::loco_speed_event));
layout.get_driver().signal_loco_function.connect(sigc::mem_fun(this, &Train::loco_func_event));
timetable->tick(t);
controller->tick(dt);
float speed = controller->get_speed();
- unsigned speed_notch = find_speed(speed);
+ unsigned speed_step = find_speed_step(speed);
if(controller->get_reverse()!=reverse)
{
reserve_more();
}
- if(speed_notch!=current_speed && !speed_changing && !driver.is_halted() && driver.get_power())
+ if(speed_step!=current_speed_step && !speed_changing && !driver.is_halted() && driver.get_power())
{
speed_changing = true;
- driver.set_loco_speed(address, speed_notch);
+ driver.set_loco_speed(address, speed_step);
pure_speed = false;
- if(speed_notch)
+ if(speed_step)
set_status(format("Traveling %d kmh", get_travel_speed()));
else
set_status("Waiting");
for(BlockList::const_iterator i=blocks.begin(); (!ok && i!=cur_blocks_end); ++i)
ok = (*i)->has_track(*track);
- float d = get_real_speed(current_speed)*(dt/Time::sec);
+ float d;
+ if(real_speed.size()>1)
+ d = get_real_speed(current_speed_step)*(dt/Time::sec);
+ else
+ d = speed*(dt/Time::sec);
if(ok)
{
SetFlag setf(advancing);
if(i!=vehicles.begin())
st.push_back((DataFile::Statement("vehicle"), (*i)->get_type().get_article_number()));
- for(unsigned i=0; i<=14; ++i)
+ for(unsigned i=0; i<real_speed.size(); ++i)
if(real_speed[i].weight)
st.push_back((DataFile::Statement("real_speed"), i, real_speed[i].speed, real_speed[i].weight));
{
if(addr==address)
{
- current_speed = speed;
+ current_speed_step = speed;
speed_changing = false;
pure_speed = false;
}
if(pure_speed)
{
- if(current_speed)
+ if(current_speed_step>0)
{
- RealSpeed &rs = real_speed[current_speed];
+ RealSpeed &rs = real_speed[current_speed_step];
rs.add(travel_dist/travel_time_secs, travel_time_secs);
}
set_status(format("Traveling %d kmh", get_travel_speed()));
float Train::get_real_speed(unsigned i) const
{
+ if(i==0)
+ return 0;
if(real_speed[i].weight)
return real_speed[i].speed;
for(low=i; low>0; --low)
if(real_speed[low].weight)
break;
- for(high=i; high<14; ++high)
+ for(high=i; high+1<real_speed.size(); ++high)
if(real_speed[high].weight)
break;
return 0;
}
-unsigned Train::find_speed(float real) const
+unsigned Train::find_speed_step(float real) const
{
- if(real<=real_speed[0].speed)
+ if(real_speed.size()<=1)
+ return 0;
+ if(real<=real_speed[1].speed*0.5)
return 0;
unsigned low = 0;
unsigned high = 0;
unsigned last = 0;
- for(unsigned i=0; (!high && i<=14); ++i)
+ for(unsigned i=0; (!high && i<real_speed.size()); ++i)
if(real_speed[i].weight)
{
last = i;
}
if(!high)
{
+ unsigned limit = real_speed.size()/5;
if(!low)
{
if(real)
- return 3;
+ return limit;
else
return 0;
}
- return min(min(static_cast<unsigned>(low*real/real_speed[low].speed), 14U), last+3);
+ return min(min(static_cast<unsigned>(low*real/real_speed[low].speed), real_speed.size()-1), last+limit);
}
float f = (real-real_speed[low].speed)/(real_speed[high].speed-real_speed[low].speed);
float Train::get_travel_speed() const
{
- float speed = get_real_speed(current_speed);
+ float speed = get_real_speed(current_speed_step);
float scale = layout.get_catalogue().get_scale();
return static_cast<int>(round(speed/scale*3.6/5))*5;
}
void Train::Loader::real_speed(unsigned i, float speed, float weight)
{
+ if(i>=obj.real_speed.size())
+ return;
obj.real_speed[i].speed = speed;
obj.real_speed[i].weight = weight;
}