23 m /= size_m / (float)size_c;
24 return (
unsigned int)floor(m);
29 meters_t cell_size = size_m / (float)size_c;
33 return m + cell_size / 2.0;
44 Task(
Model *source,
Model *sink) : source(source), sink(sink), participants(0) {}
57 Edge(
Node *to,
double cost = 1.0) : to(to), cost(cost) {}
66 Node(
Pose pose,
double value = 0) : pose(pose), value(value), edges() {}
77 edges.push_back(edge);
98 const std::vector<Node *>::iterator &it = nodes.begin();
119 Node *best_node = NULL;
124 double dist = hypot(node->
pose.
x - pose.
x, node->
pose.
y - pose.
y);
128 if (dist < range && (best_node == NULL || node->
value < best_node->
value)) {
133 if (best_node == NULL) {
134 fprintf(stderr,
"FASR warning: no nodes in range");
139 heading_result = atan2(best_node->
pose.
y - pose.
y, best_node->
pose.
x - pose.
x);
143 heading_result =
normalize(heading_result + 0.25);
157 if (*graphpp == NULL)
192 double charger_bearing;
193 double charger_range;
194 double charger_heading;
224 : wait_started_at(-1),
228 fiducial((
ModelFiducial *)pos->GetUnusedModelOfType(
"fiducial")),
229 task(random() % tasks.size()),
242 goal(tasks[task].source),
251 force_recharge(false)
261 pos->
SetColor(tasks[task].source->GetColor());
263 tasks[task].participants++;
273 if (map_data == NULL) {
274 map_data =
new uint8_t[map_width * map_height * 2];
278 memset(map_data, 0,
sizeof(uint8_t) * map_width * map_height);
285 map_model->
Rasterize(map_data, map_width, map_height, g.
size.
x / (
float)map_width,
286 g.
size.
y / (
float)map_height);
290 unsigned int sz = map_width * map_height;
291 for (
unsigned int i = 0; i < sz; i++) {
292 if (map_data[i] == 0)
294 else if (map_data[i] == 1)
297 printf(
"FASR: bad value %d in map at index %d\n", (
int)map_data[i], (
int)i);
299 assert((map_data[i] == 1) || (map_data[i] == 9));
328 uint64_t x = pt.
x / 1;
329 uint64_t y = pt.
y / 1;
331 return (x << 32) + y;
336 std::pair<uint64_t, uint64_t> key(Pt64(start), Pt64(goal));
337 plancache[key] = graph;
342 std::pair<uint64_t, uint64_t> key(Pt64(start), Pt64(goal));
343 return plancache[key];
374 graphp = LookupPlan(start, goal);
378 static float misses = 0;
381 std::vector<ast::point_t> path;
382 bool result =
ast::astar(map_data, map_width, map_height, start, goal, path);
385 printf(
"FASR2 warning: plan failed to find path from (%.2f,%.2f) to (%.2f,%.2f)\n", pose.
x,
388 graphp =
new Graph();
390 unsigned int dist = 0;
392 Node *last_node = NULL;
394 for (std::vector<ast::point_t>::reverse_iterator rit = path.rbegin(); rit != path.rend();
410 CachePlan(start, goal, graphp);
412 static float hits = 0;
423 const meters_t creep_distance = 0.5;
428 const double orient =
normalize(M_PI - (charger_bearing - charger_heading));
429 const double a_goal =
normalize(charger_bearing - 2.0 * orient);
431 if (charger_range > creep_distance) {
432 if (!ObstacleAvoid()) {
441 if (charger_range < 0.08)
454 EnableFiducial(
false);
464 EnableFiducial(
true);
465 force_recharge =
false;
472 tasks[task].participants++;
477 const meters_t back_off_distance = 0.2;
478 const meters_t back_off_speed = -0.02;
479 const radians_t undock_rotate_speed = 0.3;
481 const unsigned int BACK_SENSOR_FIRST = 10;
482 const unsigned int BACK_SENSOR_LAST = 13;
486 assert(fiducial_sub);
488 if (charger_range < back_off_distance) {
494 const std::vector<ModelRanger::Sensor> &sensors = sonar->
GetSensors();
496 for (
unsigned int s = BACK_SENSOR_FIRST;
s <= BACK_SENSOR_LAST; ++
s)
497 if (sensors[
s].ranges.size() < 1 || sensors[
s].ranges[0] < wait_distance) {
498 pos->
Say(
"Waiting...");
506 if (fabs(heading_error) > 0.05) {
517 SetTask(random() % tasks.size());
518 SetGoal(tasks[task].source);
520 SetGoal(tasks[task].sink);
522 EnableFiducial(
false);
530 bool obstruction =
false;
535 double minleft = 1e6;
536 double minright = 1e6;
541 const std::vector<meters_t> &scan = laser->
GetSensors()[0].ranges;
543 uint32_t sample_count = scan.size();
545 for (uint32_t i = 0; i < sample_count; i++) {
547 printf(
"%.3f ", scan[i]);
549 if ((i > (sample_count / 4)) && (i < (sample_count - (sample_count / 4)))
552 puts(
" obstruction!");
562 if (i > sample_count / 2)
563 minleft = std::min(minleft, scan[i]);
565 minright = std::min(minright, scan[i]);
570 printf(
"minleft %.3f \n", minleft);
571 printf(
"minright %.3f\n ", minright);
574 if (obstruction || stop || (avoidcount > 0)) {
576 printf(
"Avoid %d\n", avoidcount);
582 if (avoidcount < 1) {
587 if (minleft < minright) {
590 printf(
"turning right %.2f\n", -
avoidturn);
594 printf(
"turning left %2f\n", +
avoidturn);
608 if (goal != this->goal) {
617 if (!ObstacleAvoid()) {
629 if (graphp == NULL || (graphp->
GoodDirection(pose, 5.0, a_goal) == 0)
638 cached_goal_pose = goal->
GetPose();
643 EnableFiducial(
true);
646 printf(
"%s replanning in Work()\n", pos->
Token());
653 const double a_error =
normalize(a_goal - pose.
a);
665 if (strcmp(pos->
Token(),
"position:0") == 0) {
666 static int seconds = 0;
670 if (timenow - seconds > 5) {
686 charger_ahoy =
false;
690 std::vector<ModelFiducial::Fiducial> &fids = fiducial->
GetFiducials();
692 if (fids.size() > 0) {
695 for (
unsigned int i = 0; i < fids.size(); i++) {
703 && (closest == NULL || f->
range < closest->
range))
712 charger_bearing = closest->
bearing;
713 charger_range = closest->
range;
714 charger_heading = closest->
geom.
a;
725 if (goal == tasks[task].source) {
730 meters_t dest_dist = hypot(sourcepose.
x - pose.
x, sourcepose.
y - pose.
y);
733 if (dest_dist < sourcegeom.
size.
x / 2.0)
734 if (wait_started_at < 0 && pos->GetFlagCount() == 0) {
739 if (wait_started_at > 0) {
743 if (drand48() < 0.0005) {
747 force_recharge =
true;
748 tasks[task].participants--;
749 wait_started_at = -1;
755 if (dest_dist < sourcegeom.size.x / 2.0 && pos->GetFlagCount() <
PAYLOAD) {
761 wait_started_at = -1;
765 SetGoal(tasks[task].sink);
767 }
else if (goal == tasks[task].sink) {
772 if (hypot(sinkpose.
x - pose.
x, sinkpose.
y - pose.
y) < sinkgeom.
size.
x / 2.0
782 SetGoal(tasks[task].source);
785 assert(goal == fuel_zone);
804 default: printf(
"unrecognized mode %d\n",
int(mode));
812 printf(
"model %s collected flag\n", mod->
Token());
818 printf(
"model %s dropped flag\n", mod->
Token());
836 glVertex2f(pose.x, pose.y);
837 glVertex2f((*it)->to->pose.x, (*it)->to->pose.y);
853 void split(
const std::string &text,
const std::string &separators, std::vector<std::string> &words)
855 const int n = text.length();
856 int start = text.find_first_not_of(separators);
857 while ((start >= 0) && (start < n)) {
858 int stop = text.find_first_of(separators, start);
859 if ((stop < 0) || (stop > n))
861 words.push_back(text.substr(start, stop - start));
862 start = text.find_first_not_of(separators, stop + 1);
874 std::vector<std::string> words;
877 assert(words.size() > 1);
882 for (
unsigned int s = 1;
s < words.size();
s++)
884 Robot::Task(w->GetModel(words[
s] +
"_source"), w->GetModel(words[
s] +
"_sink")));
void SetTurnSpeed(double a)
meters_t range
range to the target
virtual void PushColor(Color col)
static meters_t CellToMeters(unsigned int c, meters_t size_m, unsigned int size_c)
static void UpdateCallback(WorldGui *world)
void EnableSonar(bool on)
Task(Model *source, Model *sink)
unsigned int GetFlagCount() const
static const bool verbose
Pose GetGlobalPose() const
PowerPack * FindPowerPack() const
The Stage library uses its own namespace.
std::vector< Fiducial > & GetFiducials()
fiducial detector?
Node(Pose pose, double value=0)
virtual void Visualize(Model *mod, Camera *)
static const double minfrontdistance
void EnableLaser(bool on)
void Init(int *argc, char **argv[])
Robot(ModelPosition *pos, Model *fuel)
unsigned int participants
int(* model_callback_t)(Model *mod, void *user)
void Rasterize(uint8_t *data, unsigned int width, unsigned int height, meters_t cellwidth, meters_t cellheight)
bool GoodDirection(const Pose &pose, meters_t range, radians_t &heading_result)
static const double avoidturn
void SetColor(const Color &col)
static unsigned int MetersToCell(meters_t m, meters_t size_m, unsigned int size_c)
void EnableFiducial(bool on)
void Say(const std::string &str)
const std::vector< Sensor > & GetSensors() const
static const unsigned int map_width
void pose_inverse_shift(const Pose &pose)
double normalize(double a)
void AddCallback(callback_type_t type, model_callback_t cb, void *user)
static const unsigned int map_height
radians_t bearing
bearing to the target
meters_t Distance(const Pose &other) const
void PushFlag(Flag *flag)
uint64_t Pt64(const ast::point_t &pt)
static const unsigned int avoidduration
void SetGoal(Model *goal)
Edge(Node *to, double cost=1.0)
static int FlagIncr(Model *mod, Robot *)
void SetTask(unsigned int t)
usec_t SimTimeNow(void) const
void AddVisualizer(Visualizer *custom_visual, bool on_by_default)
Graph * LookupPlan(const ast::point_t &start, const ast::point_t &goal)
static const double avoidspeed
static pthread_mutex_t planner_mutex
static std::vector< Task > tasks
double ProportionRemaining() const
std::vector< Edge * > edges
static const double cruisespeed
void Enable(Stg::Model *model, bool &sub, bool on)
std::vector< Node * > nodes
static int UpdateCallback(ModelRanger *, Robot *robot)
bool astar(uint8_t *map, uint32_t width, uint32_t height, const point_t &start, const point_t &goal, std::vector< point_t > &path)
Pose geom
size and relative angle of the target
static uint8_t * map_data
static int FlagDecr(Model *mod, Robot *)
static const unsigned int PAYLOAD
void split(const std::string &text, const std::string &separators, std::vector< std::string > &words)
radians_t a
rotation about the z axis.
GraphVis(Graph **graphpp)
static const double stopdist
Model * GetModel(const std::string &name) const
static std::map< std::pair< uint64_t, uint64_t >, Graph * > plancache
void CachePlan(const ast::point_t &start, const ast::point_t &goal, Graph *graph)
const char * Token() const