namespace Marklin {
-AIControl::AIControl(Train &t, ControlModel *n):
+AIControl::AIControl(Train &t, Controller *n):
train(t),
next_model(n),
target_speed(TrainControl::continuous("speed", 0, 1000)),
#define LIBMARKLIN_AICONTROL_H_
#include <sigc++/trackable.h>
-#include "controlmodel.h"
+#include "controller.h"
#include "traincontrol.h"
namespace Marklin {
class Train;
-class AIControl: public ControlModel, public sigc::trackable
+class AIControl: public Controller, public sigc::trackable
{
private:
Train &train;
- ControlModel *next_model;
+ Controller *next_model;
TrainControl target_speed;
bool blocked;
bool approach;
public:
- AIControl(Train &, ControlModel *);
+ AIControl(Train &, Controller *);
virtual ~AIControl();
virtual void set_control(const std::string &, float);
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef LIBMARKLIN_CONTROLLER_H_
+#define LIBMARKLIN_CONTROLLER_H_
+
+#include <string>
+#include <sigc++/signal.h>
+#include <msp/time/timedelta.h>
+
+namespace Marklin {
+
+struct TrainControl;
+
+/**
+Interface class for train controllers. Takes input through a uniform named
+control interface. Provides information about train movement on output.
+*/
+class Controller
+{
+public:
+ sigc::signal<void, const TrainControl &> signal_control_changed;
+
+protected:
+ Controller() { }
+public:
+ virtual ~Controller() { }
+
+ virtual void set_control(const std::string &, float) = 0;
+ virtual const TrainControl &get_control(const std::string &) const = 0;
+
+ /** Returns the current speed. Always non-negative. */
+ virtual float get_speed() const = 0;
+
+ /** Returns true if traveling in reverse. */
+ virtual bool get_reverse() const = 0;
+
+ /** Determines the distance required to come to a full stop. */
+ virtual float get_braking_distance() const = 0;
+
+ virtual void tick(const Msp::Time::TimeDelta &) = 0;
+};
+
+} // namespace Marklin
+
+#endif
+++ /dev/null
-/* $Id$
-
-This file is part of the MSP Märklin suite
-Copyright © 2010 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
-#ifndef LIBMARKLIN_CONTROLMODEL_H_
-#define LIBMARKLIN_CONTROLMODEL_H_
-
-#include <string>
-#include <sigc++/signal.h>
-#include <msp/time/timedelta.h>
-
-namespace Marklin {
-
-struct TrainControl;
-
-/**
-Interface class for train control models. Takes input through a uniform named
-control interface. Provides information about train movement on output.
-*/
-class ControlModel
-{
-public:
- sigc::signal<void, const TrainControl &> signal_control_changed;
-
-protected:
- ControlModel() { }
-public:
- virtual ~ControlModel() { }
-
- virtual void set_control(const std::string &, float) = 0;
- virtual const TrainControl &get_control(const std::string &) const = 0;
-
- /** Returns the current speed. Always non-negative. */
- virtual float get_speed() const = 0;
-
- /** Returns true if traveling in reverse. */
- virtual bool get_reverse() const = 0;
-
- /** Determines the distance required to come to a full stop. */
- virtual float get_braking_distance() const = 0;
-
- virtual void tick(const Msp::Time::TimeDelta &) = 0;
-};
-
-} // namespace Marklin
-
-#endif
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <msp/core/except.h>
+#include <msp/time/units.h>
+#include "simplecontroller.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace Marklin {
+
+SimpleController::SimpleController():
+ target_speed(TrainControl::continuous("speed", 0, 1000)),
+ reverse(TrainControl::binary("reverse")),
+ accel(0.07),
+ speed(0)
+{
+ target_speed.set(0);
+}
+
+void SimpleController::set_control(const string &name, float v)
+{
+ if(name=="speed")
+ {
+ target_speed.set(v);
+ signal_control_changed.emit(target_speed);
+ }
+ else if(name=="reverse")
+ {
+ if(target_speed.value || speed)
+ throw InvalidState("Must be stopped to change reverse");
+ reverse.set(v);
+ signal_control_changed.emit(reverse);
+ }
+}
+
+const TrainControl &SimpleController::get_control(const string &name) const
+{
+ if(name=="speed")
+ return target_speed;
+ else if(name=="reverse")
+ return reverse;
+ else
+ throw KeyError("Unknown control", name);
+}
+
+float SimpleController::get_braking_distance() const
+{
+ return speed*speed/(2*accel);
+}
+
+void SimpleController::tick(const Time::TimeDelta &dt)
+{
+ float secs = dt/Time::sec;
+ if(speed<target_speed.value)
+ {
+ speed += secs*accel;
+ if(speed>target_speed.value)
+ speed = target_speed.value;
+ }
+ else if(speed>target_speed.value)
+ {
+ speed -= secs*accel;
+ if(speed<target_speed.value)
+ speed = target_speed.value;
+ }
+}
+
+} // namespace Marklin
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef LIBMARKLIN_SIMPLECONTROLLER_H_
+#define LIBMARKLIN_SIMPLECONTROLLER_H_
+
+#include <string>
+#include "controller.h"
+#include "traincontrol.h"
+
+namespace Marklin {
+
+class SimpleController: public Controller
+{
+private:
+ TrainControl target_speed;
+ TrainControl reverse;
+ float accel;
+ float speed;
+
+public:
+ SimpleController();
+
+ virtual void set_control(const std::string &, float);
+ virtual const TrainControl &get_control(const std::string &) const;
+
+ virtual float get_speed() const { return speed; }
+ virtual bool get_reverse() const { return reverse.value; }
+ virtual float get_braking_distance() const;
+
+ virtual void tick(const Msp::Time::TimeDelta &);
+};
+
+} // namespace Marklin
+
+#endif
+++ /dev/null
-/* $Id$
-
-This file is part of the MSP Märklin suite
-Copyright © 2010 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
-#include <msp/core/except.h>
-#include <msp/time/units.h>
-#include "simplephysics.h"
-
-using namespace std;
-using namespace Msp;
-
-namespace Marklin {
-
-SimplePhysics::SimplePhysics():
- target_speed(TrainControl::continuous("speed", 0, 1000)),
- reverse(TrainControl::binary("reverse")),
- accel(0.07),
- speed(0)
-{
- target_speed.set(0);
-}
-
-void SimplePhysics::set_control(const string &name, float v)
-{
- if(name=="speed")
- {
- target_speed.set(v);
- signal_control_changed.emit(target_speed);
- }
- else if(name=="reverse")
- {
- if(target_speed.value || speed)
- throw InvalidState("Must be stopped to change reverse");
- reverse.set(v);
- signal_control_changed.emit(reverse);
- }
-}
-
-const TrainControl &SimplePhysics::get_control(const string &name) const
-{
- if(name=="speed")
- return target_speed;
- else if(name=="reverse")
- return reverse;
- else
- throw KeyError("Unknown control", name);
-}
-
-float SimplePhysics::get_braking_distance() const
-{
- return speed*speed/(2*accel);
-}
-
-void SimplePhysics::tick(const Time::TimeDelta &dt)
-{
- float secs = dt/Time::sec;
- if(speed<target_speed.value)
- {
- speed += secs*accel;
- if(speed>target_speed.value)
- speed = target_speed.value;
- }
- else if(speed>target_speed.value)
- {
- speed -= secs*accel;
- if(speed<target_speed.value)
- speed = target_speed.value;
- }
-}
-
-} // namespace Marklin
+++ /dev/null
-/* $Id$
-
-This file is part of the MSP Märklin suite
-Copyright © 2010 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
-#ifndef LIBMARKLIN_SIMPLEPHYSICS_H_
-#define LIBMARKLIN_SIMPLEPHYSICS_H_
-
-#include <string>
-#include "controlmodel.h"
-#include "traincontrol.h"
-
-namespace Marklin {
-
-class SimplePhysics: public ControlModel
-{
-private:
- TrainControl target_speed;
- TrainControl reverse;
- float accel;
- float speed;
-
-public:
- SimplePhysics();
-
- virtual void set_control(const std::string &, float);
- virtual const TrainControl &get_control(const std::string &) const;
-
- virtual float get_speed() const { return speed; }
- virtual bool get_reverse() const { return reverse.value; }
- virtual float get_braking_distance() const;
-
- virtual void tick(const Msp::Time::TimeDelta &);
-};
-
-} // namespace Marklin
-
-#endif
{
case GOTO:
train.go_to(**parse_location(row.strparam).get_tracks().begin());
- executing = false;
break;
case TRAVEL:
pending_block = &parse_location(row.strparam);
wait_timeout = t+row.intparam*Time::sec;
executing = false;
break;
+ case ARRIVE:
+ executing = false;
+ break;
case SPEED:
train.set_control("speed", row.intparam/3.6*train.get_layout().get_catalogue().get_scale());
break;
case WAIT:
st.push_back((DataFile::Statement("wait"), i->intparam));
break;
+ case ARRIVE:
+ st.push_back(DataFile::Statement("arrive"));
+ break;
case SPEED:
st.push_back((DataFile::Statement("speed"), i->intparam));
break;
void Timetable::train_arrived()
{
Row &row = rows[current_row];
- if(row.type==GOTO)
+ if(row.type==ARRIVE)
{
current_row = (current_row+1)%rows.size();
executing = true;
return "travel to "+strparam;
case WAIT:
return format("wait for %d seconds", intparam);
+ case ARRIVE:
+ return "wait for arrival";
case SPEED:
return format("set speed %d km/h", intparam);
case ROUTE:
++nondigit;
return Row(WAIT, lexical_cast<unsigned>(s.substr(9, nondigit-9)));
}
+ else if(s=="wait for arrival")
+ return Row(ARRIVE, 0);
else if(!s.compare(0, 10, "set speed "))
{
unsigned nondigit = 11;
- while(nondigit<s.size() && isdigit(s[nondigit]))
+ while(nondigit<s.size() && (isdigit(s[nondigit]) || s[nondigit]=='-'))
++nondigit;
- return Row(SPEED, lexical_cast<unsigned>(s.substr(10, nondigit-10)));
+ return Row(SPEED, lexical_cast<int>(s.substr(10, nondigit-10)));
}
else if(!s.compare(0, 10, "set route "))
return Row(ROUTE, s.substr(10));
Timetable::Loader::Loader(Timetable &tt):
DataFile::ObjectLoader<Timetable>(tt)
{
+ add("arrive", &Loader::arrive);
add("goto", &Loader::go_to);
add("route", &Loader::route);
add("speed", &Loader::speed);
add("wait", &Loader::wait);
}
+void Timetable::Loader::arrive()
+{
+ obj.rows.push_back(Row(ARRIVE, 0));
+}
+
void Timetable::Loader::go_to(const string &t)
{
obj.rows.push_back(Row(GOTO, t));
public:
Loader(Timetable &);
private:
+ void arrive();
void go_to(const std::string &);
void route(const std::string &);
void speed(int);
GOTO,
TRAVEL,
WAIT,
+ ARRIVE,
SPEED,
ROUTE
};
#include "driver.h"
#include "layout.h"
#include "route.h"
-#include "simplephysics.h"
+#include "simplecontroller.h"
#include "timetable.h"
#include "tracktype.h"
#include "train.h"
address(a),
priority(0),
pending_block(0),
- control(new AIControl(*this, new SimplePhysics)),
+ controller(new AIControl(*this, new SimpleController)),
timetable(0),
active(false),
current_speed(0),
layout.get_driver().signal_halt.connect(sigc::mem_fun(this, &Train::halt_event));
- control->signal_control_changed.connect(sigc::mem_fun(this, &Train::control_changed));
+ controller->signal_control_changed.connect(sigc::mem_fun(this, &Train::control_changed));
}
Train::~Train()
{
- delete control;
+ delete controller;
delete timetable;
for(vector<Vehicle *>::iterator i=vehicles.begin(); i!=vehicles.end(); ++i)
delete *i;
void Train::set_control(const string &n, float v)
{
- control->set_control(n, v);
+ controller->set_control(n, v);
}
void Train::set_active(bool a)
{
if(a==active)
return;
- if(!a && control->get_speed())
+ if(!a && controller->get_speed())
throw InvalidState("Can't deactivate while moving");
active = a;
float Train::get_control(const string &ctrl) const
{
- return control->get_control(ctrl).value;
+ return controller->get_control(ctrl).value;
}
float Train::get_speed() const
{
- return control->get_speed();
+ return controller->get_speed();
}
bool Train::get_function(unsigned func) const
void Train::place(Block &block, unsigned entry)
{
- if(control->get_speed())
+ if(controller->get_speed())
throw InvalidState("Must be stopped before placing");
release_blocks(rsv_blocks);
if(timetable)
timetable->tick(t);
- control->tick(dt);
- float speed = control->get_speed();
+ controller->tick(dt);
+ float speed = controller->get_speed();
unsigned speed_notch = find_speed(speed);
- if(control->get_reverse()!=reverse)
+ if(controller->get_reverse()!=reverse)
{
- reverse = control->get_reverse();
+ reverse = controller->get_reverse();
driver.set_loco_reverse(address, reverse);
release_blocks(rsv_blocks);
namespace Marklin {
-class ControlModel;
+class Controller;
class Route;
class Timetable;
class Vehicle;
std::list<BlockRef> cur_blocks;
std::list<BlockRef> rsv_blocks;
Block *pending_block;
- ControlModel *control;
+ Controller *controller;
Timetable *timetable;
bool active;
unsigned current_speed;
const std::string &get_name() const { return name; }
void set_priority(int);
int get_priority() const { return priority; }
- ControlModel &get_control_model() const { return *control; }
+ Controller &get_controller() const { return *controller; }
void add_vehicle(const VehicleType &);
void remove_vehicle(unsigned);