19 struct point PATH[] = {
39 class ControlledRobot {
41 ModelPosition *pos = nullptr;
42 unsigned int tpi = 0; // target pose index
44 ControlledRobot(Model *m) : pos(dynamic_cast<ModelPosition *>(m))
46 assert(this->pos != nullptr);
47 this->pos->Subscribe();
49 ModelPosition *get_pos() const { return this->pos; }
50 unsigned int get_tpi() const { return this->tpi; }
51 void incr_tpi() { this->tpi = (this->tpi + 1) % PATH_LEN; }
54 struct pose point_to_pose(struct point const p)
56 return {p.x, p.y, 0.0};
59 double edist(struct pose const p1, struct pose const p2)
61 double dx = p2.x - p1.x;
62 double dy = p2.y - p1.y;
63 return sqrt(dx * dx + dy * dy);
66 double pp(struct pose const ep, struct pose const tp)
67 // see https://thomasfermi.github.io/Algorithms-for-Automated-Driving/Control/PurePursuit.html
69 double alpha = atan2(tp.y - ep.y, tp.x - ep.x);
71 return atan(2 * WHEELBASE * sin(alpha) / edist(ep, tp));
74 int steer(Model *m, ControlledRobot *r)
76 auto p = r->get_pos()->GetPose();
77 struct pose ep = {p.x, p.y, p.a};
78 assert(r->get_tpi() < PATH_LEN);
79 struct pose tp = point_to_pose(PATH[r->get_tpi()]);
80 if (edist(ep, tp) < MIN_LADIST) {
82 tp = point_to_pose(PATH[r->get_tpi()]);
83 m->GetWorld()->GetModel("tp")->SetPose({tp.x, tp.y, 0.0, 0.0});
85 r->get_pos()->SetTurnSpeed(pp(ep, tp));
89 extern "C" int Init(Model *model, CtrlArgs *)
91 auto r = new ControlledRobot(model);
92 r->get_pos()->AddCallback(Model::CB_UPDATE, model_callback_t(steer), r);
93 r->get_pos()->SetXSpeed(2.0);