00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00034
00279 #ifdef HAVE_CONFIG_H
00280 #include "config.h"
00281 #endif
00282
00283 #include <assert.h>
00284 #include <errno.h>
00285 #include <string.h>
00286 #include <math.h>
00287 #include <stdlib.h>
00288 #include <sys/types.h>
00289 #include <unistd.h>
00290 #include <sys/time.h>
00291
00292 #define PLAYER_ENABLE_TRACE 1
00293 #define PLAYER_ENABLE_MSG 1
00294
00295 #include <libplayercore/playercore.h>
00296 #include <libplayercore/error.h>
00297
00298 #include "amcl.h"
00299
00300 #include "amcl_odom.h"
00301 #include "amcl_laser.h"
00302
00303
00304
00305
00306 #define MAX_HYPS 8
00307
00309
00310 Driver* AdaptiveMCL_Init( ConfigFile* cf, int section)
00311 {
00312 return ((Driver*) (new AdaptiveMCL(cf, section)));
00313 }
00314
00315
00317
00318 void AdaptiveMCL_Register(DriverTable* table)
00319 {
00320 table->AddDriver("amcl", AdaptiveMCL_Init);
00321 return;
00322 }
00323
00325
00326 #define AMCL_DATASIZE MAX(sizeof(player_localize_data_t), sizeof(player_position_data_t))
00327
00328
00330
00331 AdaptiveMCL::AdaptiveMCL( ConfigFile* cf, int section)
00332 : Driver(cf, section)
00333 {
00334 int i;
00335 double u[3];
00336 AMCLSensor *sensor;
00337
00338 memset(&this->localize_addr, 0, sizeof(player_devaddr_t));
00339 memset(&this->position_addr, 0, sizeof(player_devaddr_t));
00340
00341
00342 if(cf->ReadDeviceAddr(&(this->localize_addr), section, "provides",
00343 PLAYER_LOCALIZE_CODE, -1, NULL) == 0)
00344 {
00345 if(this->AddInterface(this->localize_addr))
00346 {
00347 this->SetError(-1);
00348 return;
00349 }
00350 }
00351
00352
00353 if(cf->ReadDeviceAddr(&(this->position_addr), section, "provides",
00354 PLAYER_POSITION2D_CODE, -1, NULL) == 0)
00355 {
00356 if(this->AddInterface(this->position_addr))
00357 {
00358 this->SetError(-1);
00359 return;
00360 }
00361 }
00362
00363 this->init_sensor = -1;
00364 this->action_sensor = -1;
00365 this->sensor_count = 0;
00366
00367 player_devaddr_t odom_addr;
00368 player_devaddr_t laser_addr;
00369
00370
00371
00372 if(cf->ReadDeviceAddr(&odom_addr, section, "requires",
00373 PLAYER_POSITION2D_CODE, -1, "odometry") == 0)
00374 {
00375 this->action_sensor = this->sensor_count;
00376 if (cf->ReadInt(section, "odom_init", 1))
00377 this->init_sensor = this->sensor_count;
00378 sensor = new AMCLOdom(*this,odom_addr);
00379 sensor->is_action = 1;
00380 this->sensors[this->sensor_count++] = sensor;
00381 }
00382
00383
00384 if(cf->ReadDeviceAddr(&laser_addr, section, "requires",
00385 PLAYER_LASER_CODE, -1, NULL) == 0)
00386 {
00387 sensor = new AMCLLaser(*this,laser_addr);
00388 sensor->is_action = 0;
00389 this->sensors[this->sensor_count++] = sensor;
00390 }
00391
00392 #if 0
00393
00394 if(cf->ReadDeviceAddr(&fiducial_addr, section, "requires",
00395 PLAYER_FIDUCIAL_CODE, -1, NULL) == 0)
00396 {
00397 sensor = new AMCLFiducial(fiducial_addr);
00398 sensor->is_action = 0;
00399 this->sensors[this->sensor_count++] = sensor;
00400 }
00401 #endif
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 if(this->action_sensor < 0)
00419 {
00420 PLAYER_ERROR("No action sensor");
00421 this->SetError(-1);
00422 return;
00423 }
00424
00425
00426 for (i = 0; i < this->sensor_count; i++)
00427 this->sensors[i]->Load(cf, section);
00428
00429
00430 this->q_len = 0;
00431 this->q_start = 0;
00432 this->q_size = 20000;
00433 this->q_data = new AMCLSensorData*[this->q_size];
00434 memset(this->q_data,0,sizeof(AMCLSensorData*)*this->q_size);
00435
00436
00437 this->pf = NULL;
00438 this->pf_min_samples = cf->ReadInt(section, "pf_min_samples", 100);
00439 this->pf_max_samples = cf->ReadInt(section, "pf_max_samples", 10000);
00440
00441
00442 this->pf_err = cf->ReadFloat(section, "pf_err", 0.01);
00443 this->pf_z = cf->ReadFloat(section, "pf_z", 3);
00444
00445
00446 this->pf_init_pose_mean = pf_vector_zero();
00447 this->pf_init_pose_mean.v[0] = cf->ReadTupleLength(section, "init_pose", 0, 0);
00448 this->pf_init_pose_mean.v[1] = cf->ReadTupleLength(section, "init_pose", 1, 0);
00449 this->pf_init_pose_mean.v[2] = cf->ReadTupleAngle(section, "init_pose", 2, 0);
00450
00451
00452 u[0] = cf->ReadTupleLength(section, "init_pose_var", 0, 1);
00453 u[1] = cf->ReadTupleLength(section, "init_pose_var", 1, 1);
00454 u[2] = cf->ReadTupleAngle(section, "init_pose_var", 2, 2*M_PI);
00455 this->pf_init_pose_cov = pf_matrix_zero();
00456 this->pf_init_pose_cov.m[0][0] = u[0] * u[0];
00457 this->pf_init_pose_cov.m[1][1] = u[1] * u[1];
00458 this->pf_init_pose_cov.m[2][2] = u[2] * u[2];
00459
00460
00461 this->min_dr = cf->ReadTupleLength(section, "update_thresh", 0, 0.20);
00462 this->min_da = cf->ReadTupleAngle(section, "update_thresh", 1, M_PI/6);
00463
00464
00465 this->hyp_count = 0;
00466 this->hyp_alloc = 0;
00467 this->hyps = NULL;
00468 pthread_mutex_init(&this->best_hyp_lock,NULL);
00469
00470 #ifdef INCLUDE_RTKGUI
00471
00472 this->enable_gui = cf->ReadInt(section, "enable_gui", 0);
00473 #endif
00474
00475
00476 return;
00477 }
00478
00479
00481
00482 AdaptiveMCL::~AdaptiveMCL(void)
00483 {
00484 int i;
00485
00486
00487 delete[] this->q_data;
00488 free(hyps);
00489
00490
00491 for (i = 0; i < this->sensor_count; i++)
00492 {
00493 this->sensors[i]->Unload();
00494 delete this->sensors[i];
00495 }
00496 this->sensor_count = 0;
00497 pthread_mutex_destroy(&this->best_hyp_lock);
00498
00499 return;
00500 }
00501
00502
00504
00505 int AdaptiveMCL::Setup(void)
00506 {
00507 PLAYER_MSG0(2, "setup");
00508
00509
00510 assert(this->pf == NULL);
00511 this->pf = pf_alloc(this->pf_min_samples, this->pf_max_samples);
00512 this->pf->pop_err = this->pf_err;
00513 this->pf->pop_z = this->pf_z;
00514
00515
00516 for (int i = 0; i < this->sensor_count; i++)
00517 if (this->sensors[i]->Setup() < 0)
00518 {
00519 PLAYER_ERROR1 ("failed to setup sensor %d", i);
00520 return -1;
00521 }
00522
00523
00524
00525 PLAYER_MSG0(2, "running");
00526 this->StartThread();
00527
00528 return 0;
00529 }
00530
00531
00533
00534 int AdaptiveMCL::Shutdown(void)
00535 {
00536 int i;
00537
00538 PLAYER_MSG0(2, "shutting down");
00539
00540
00541 this->StopThread();
00542
00543
00544 for (i = 0; i < this->sensor_count; i++)
00545 this->sensors[i]->Shutdown();
00546
00547
00548 pf_free(this->pf);
00549 this->pf = NULL;
00550
00551 PLAYER_MSG0(2, "shutdown done");
00552 return 0;
00553 }
00554
00555
00557
00558 void AdaptiveMCL::UpdateSensorData(void)
00559 {
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 }
00592
00593
00595
00596 void AdaptiveMCL::Push(AMCLSensorData *data)
00597 {
00598 int i;
00599
00600 this->Lock();
00601
00602 if (this->q_len >= this->q_size)
00603 {
00604 this->Unlock();
00605 PLAYER_ERROR("queue overflow");
00606 return;
00607 }
00608 i = (this->q_start + this->q_len++) % this->q_size;
00609
00610 this->q_data[i] = data;
00611
00612 this->Unlock();
00613 return;
00614 }
00615
00616
00618
00619 AMCLSensorData *AdaptiveMCL::Peek(void)
00620 {
00621 int i;
00622
00623 this->Lock();
00624
00625 if (this->q_len == 0)
00626 {
00627 this->Unlock();
00628 return NULL;
00629 }
00630 i = this->q_start % this->q_size;
00631
00632 this->Unlock();
00633 return this->q_data[i];
00634 }
00635
00636
00638
00639 AMCLSensorData *AdaptiveMCL::Pop(void)
00640 {
00641 int i;
00642
00643 this->Lock();
00644
00645 if (this->q_len == 0)
00646 {
00647 this->Unlock();
00648 return NULL;
00649 }
00650 i = this->q_start++ % this->q_size;
00651 this->q_len--;
00652
00653 this->Unlock();
00654 return this->q_data[i];
00655 }
00656
00657
00659
00660 void AdaptiveMCL::Main(void)
00661 {
00662 this->q_len = 0;
00663
00664
00665
00666 this->pf_init = false;
00667
00668
00669 this->hyp_count = 0;
00670
00671
00672
00673 nice(10);
00674
00675 #ifdef INCLUDE_RTKGUI
00676 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
00677
00678
00679 if (this->enable_gui)
00680 this->SetupGUI();
00681 #endif
00682
00683 #ifdef INCLUDE_OUTFILE
00684
00685 this->outfile = fopen("amcl.out", "w+");
00686 #endif
00687
00688 while (true)
00689 {
00690 #ifdef INCLUDE_RTKGUI
00691 if (this->enable_gui)
00692 {
00693 rtk_canvas_render(this->canvas);
00694 rtk_app_main_loop(this->app);
00695 }
00696 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00697 #endif
00698
00699
00700 const struct timespec sleeptime = {0, 1000000L};
00701 nanosleep(&sleeptime, NULL);
00702
00703
00704
00705 pthread_testcancel();
00706
00707
00708 this->ProcessMessages();
00709
00710
00711 #ifdef INCLUDE_RTKGUI
00712 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
00713 #endif
00714
00715
00716 if (!this->pf_init)
00717 this->InitFilter();
00718
00719
00720 if (this->UpdateFilter())
00721 {
00722 #ifdef INCLUDE_OUTFILE
00723
00724 pf_vector_t mean;
00725 double var;
00726
00727 pf_get_cep_stats(pf, &mean, &var);
00728
00729 printf("amcl %.3f %.3f %f\n", mean.v[0], mean.v[1], mean.v[2] * 180 / M_PI);
00730
00731 fprintf(this->outfile, "%d.%03d unknown 6665 localize 01 %d.%03d ",
00732 0, 0, 0, 0);
00733 fprintf(this->outfile, "1.0 %e %e %e %e 0 0 0 0 0 0 0 0 \n",
00734 mean.v[0], mean.v[1], mean.v[2], var);
00735 fflush(this->outfile);
00736 #endif
00737 }
00738 }
00739 return;
00740 }
00741
00742
00744
00745 void AdaptiveMCL::MainQuit()
00746 {
00747 #ifdef INCLUDE_RTKGUI
00748
00749 if (this->enable_gui)
00750 this->ShutdownGUI();
00751 #endif
00752
00753 #ifdef INCLUDE_OUTFILE
00754
00755 fclose(this->outfile);
00756 #endif
00757
00758 return;
00759 }
00760
00761
00763
00764 void AdaptiveMCL::InitFilter(void)
00765 {
00766 ::pf_init(this->pf, this->pf_init_pose_mean, this->pf_init_pose_cov);
00767
00768 return;
00769 }
00770
00771
00773
00774 bool AdaptiveMCL::UpdateFilter(void)
00775 {
00776 int i;
00777 double ts;
00778 double weight;
00779 pf_vector_t pose, delta;
00780 pf_vector_t pose_mean;
00781 pf_matrix_t pose_cov;
00782 amcl_hyp_t *hyp;
00783 AMCLSensorData *data;
00784 bool update;
00785
00786
00787
00788
00789 data = this->Pop();
00790 if (data == NULL)
00791 return false;
00792 if (!data->sensor->is_action)
00793 {
00794 delete data;
00795 return false;
00796 }
00797
00798
00799 ts = data->time;
00800
00801
00802 pose = ((AMCLOdomData*) data)->pose;
00803 delta = pf_vector_zero();
00804 update = false;
00805
00806
00807
00808
00809
00810 if (this->pf_init)
00811 {
00812
00813 delta = pf_vector_coord_sub(pose, this->pf_odom_pose);
00814
00815
00816 update = fabs(delta.v[0]) > this->min_dr ||
00817 fabs(delta.v[1]) > this->min_dr ||
00818 fabs(delta.v[2]) > this->min_da;
00819 }
00820
00821
00822 if (!this->pf_init)
00823 {
00824
00825 delete data; data = NULL;
00826
00827
00828 this->pf_odom_pose = pose;
00829
00830
00831 this->pf_init = true;
00832
00833
00834 update = true;
00835
00836
00837
00838 }
00839
00840
00841 else if (this->pf_init && update)
00842 {
00843
00844
00845
00846
00847
00848
00849 ((AMCLOdomData*) data)->delta = delta;
00850
00851
00852 data->sensor->UpdateAction(this->pf, data);
00853 delete data; data = NULL;
00854
00855
00856
00857 }
00858 else
00859 {
00860
00861 delete data; data = NULL;
00862 }
00863
00864 bool processed_first_sensor = false;
00865
00866 if (update)
00867 {
00868
00869 while (1)
00870 {
00871 data = this->Peek();
00872 if ((data == NULL ) || (data->sensor->is_action))
00873 {
00874
00875
00876 if(!processed_first_sensor)
00877 {
00878 if(data)
00879 {
00880 data = this->Pop();
00881 assert(data);
00882 delete data;
00883 }
00884
00885
00886
00887 usleep(1000);
00888 ProcessMessages();
00889
00890 continue;
00891 }
00892 else
00893 break;
00894 }
00895 data = this->Pop();
00896 assert(data);
00897
00898
00899
00900 if(!processed_first_sensor)
00901 {
00902 data->sensor->UpdateSensor(this->pf, data);
00903 processed_first_sensor = true;
00904 this->pf_odom_pose = pose;
00905 }
00906
00907 #ifdef INCLUDE_RTKGUI
00908
00909 if (this->enable_gui)
00910 data->sensor->UpdateGUI(this->canvas, this->robot_fig, data);
00911 #endif
00912
00913
00914 delete data; data = NULL;
00915 }
00916
00917
00918 pf_update_resample(this->pf);
00919
00920
00921 double max_weight = 0.0;
00922 pf_vector_t max_weight_pose={{0.0,0.0,0.0}};
00923 this->hyp_count = 0;
00924
00925 for (i = 0; MAX_HYPS; i++)
00926 {
00927 if (!pf_get_cluster_stats(this->pf, i, &weight, &pose_mean, &pose_cov))
00928 break;
00929
00930
00931
00932 if (this->hyp_count +1 > this->hyp_alloc)
00933 {
00934 this->hyp_alloc = this->hyp_count+1;
00935 this->hyps = (amcl_hyp_t*)realloc(this->hyps, sizeof(amcl_hyp_t)*this->hyp_alloc);
00936 }
00937 hyp = this->hyps + this->hyp_count++;
00938 hyp->weight = weight;
00939 hyp->pf_pose_mean = pose_mean;
00940 hyp->pf_pose_cov = pose_cov;
00941
00942 if(hyp->weight > max_weight)
00943 {
00944 max_weight = hyp->weight;
00945 max_weight_pose = hyp->pf_pose_mean;
00946 }
00947 }
00948
00949 if(max_weight > 0.0)
00950 {
00951 pthread_mutex_lock(&this->best_hyp_lock);
00952 this->best_hyp = max_weight_pose;
00953 pthread_mutex_unlock(&this->best_hyp_lock);
00954 }
00955
00956 #ifdef INCLUDE_RTKGUI
00957
00958 if (this->enable_gui)
00959 this->UpdateGUI();
00960 #endif
00961
00962
00963 this->PutDataLocalize(ts);
00964 delta = pf_vector_zero();
00965 this->PutDataPosition(delta,ts);
00966
00967 return true;
00968 }
00969 else
00970 {
00971
00972 while (1)
00973 {
00974 data = this->Peek();
00975 if (data == NULL)
00976 break;
00977 if (data->sensor->is_action)
00978 break;
00979 data = this->Pop();
00980 assert(data);
00981 delete data; data = NULL;
00982 }
00983
00984
00985
00986 this->PutDataPosition(delta,ts);
00987
00988 return false;
00989 }
00990 }
00991
00992
00993
00994
00995 int
00996 hypoth_compare(const void* h1, const void* h2)
00997 {
00998 const player_localize_hypoth_t* hyp1 = (const player_localize_hypoth_t*)h1;
00999 const player_localize_hypoth_t* hyp2 = (const player_localize_hypoth_t*)h2;
01000 if(hyp1->alpha < hyp2->alpha)
01001 return(1);
01002 else if(hyp1->alpha == hyp2->alpha)
01003 return(0);
01004 else
01005 return(-1);
01006 }
01007
01008
01010
01011 void AdaptiveMCL::PutDataLocalize(double time)
01012 {
01013 int i;
01014 amcl_hyp_t *hyp;
01015 pf_vector_t pose;
01016 pf_matrix_t pose_cov;
01017
01018 player_localize_data_t data;
01019
01020
01021 data.pending_count = 0;
01022 data.pending_time = 0.0;
01023
01024
01025 data.hypoths_count = this->hyp_count;
01026 data.hypoths = new player_localize_hypoth_t[data.hypoths_count];
01027 for (i = 0; i < this->hyp_count; i++)
01028 {
01029 hyp = this->hyps + i;
01030
01031
01032 pose = hyp->pf_pose_mean;
01033 pose_cov = hyp->pf_pose_cov;
01034
01035
01036 if (!pf_vector_finite(pose))
01037 {
01038 pf_vector_fprintf(pose, stderr, "%e");
01039 assert(0);
01040 }
01041 if (!pf_matrix_finite(pose_cov))
01042 {
01043 pf_matrix_fprintf(pose_cov, stderr, "%e");
01044 assert(0);
01045 }
01046
01047 data.hypoths[i].alpha = hyp->weight;
01048
01049 data.hypoths[i].mean.px = pose.v[0];
01050 data.hypoths[i].mean.py = pose.v[1];
01051 data.hypoths[i].mean.pa = pose.v[2];
01052
01053 data.hypoths[i].cov[0] = pose_cov.m[0][0];
01054 data.hypoths[i].cov[1] = pose_cov.m[1][1];
01055 data.hypoths[i].cov[2] = pose_cov.m[2][2];
01056 }
01057
01058
01059 qsort((void*)data.hypoths,data.hypoths_count,
01060 sizeof(player_localize_hypoth_t),&hypoth_compare);
01061
01062
01063 this->Publish(this->localize_addr,
01064 PLAYER_MSGTYPE_DATA,
01065 PLAYER_LOCALIZE_DATA_HYPOTHS,
01066 (void*)&data);
01067 delete [] data.hypoths;
01068 }
01069
01070
01072
01073 void AdaptiveMCL::PutDataPosition(pf_vector_t delta, double time)
01074 {
01075 pf_vector_t pose;
01076 player_position2d_data_t data;
01077
01078 memset(&data,0,sizeof(data));
01079
01080
01081 pthread_mutex_lock(&this->best_hyp_lock);
01082 pose = this->best_hyp;
01083 pthread_mutex_unlock(&this->best_hyp_lock);
01084
01085
01086 pose = pf_vector_coord_add(delta, pose);
01087
01088 data.pos.px = pose.v[0];
01089 data.pos.py = pose.v[1];
01090 data.pos.pa = pose.v[2];
01091
01092
01093 this->Publish(this->position_addr,
01094 PLAYER_MSGTYPE_DATA,
01095 PLAYER_POSITION2D_DATA_STATE,
01096 (void*)&data,sizeof(data),&time);
01097 }
01098
01099
01100 int
01101 AdaptiveMCL::ProcessMessage(QueuePointer & resp_queue,
01102 player_msghdr * hdr,
01103 void * data)
01104 {
01105 player_localize_set_pose_t* setposereq;
01106
01107
01108 if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
01109 PLAYER_LOCALIZE_REQ_SET_POSE,
01110 this->localize_addr))
01111 {
01112 setposereq = (player_localize_set_pose_t*)data;
01113
01114 pf_vector_t pose;
01115 pf_matrix_t cov;
01116
01117 pose.v[0] = setposereq->mean.px;
01118 pose.v[1] = setposereq->mean.py;
01119 pose.v[2] = setposereq->mean.pa;
01120
01121 cov = pf_matrix_zero();
01122 cov.m[0][0] = setposereq->cov[0];
01123 cov.m[1][1] = setposereq->cov[1];
01124 cov.m[2][2] = setposereq->cov[2];
01125
01126
01127 this->pf_init_pose_mean = pose;
01128 this->pf_init_pose_cov = cov;
01129 this->pf_init = false;
01130
01131
01132 this->Publish(this->localize_addr, resp_queue,
01133 PLAYER_MSGTYPE_RESP_ACK,
01134 PLAYER_LOCALIZE_REQ_SET_POSE);
01135 return(0);
01136 }
01137
01138 else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
01139 PLAYER_LOCALIZE_REQ_GET_PARTICLES,
01140 this->localize_addr))
01141 {
01142 pf_vector_t mean;
01143 double var;
01144 player_localize_get_particles_t resp;
01145 pf_sample_set_t *set;
01146 pf_sample_t *sample;
01147 size_t i;
01148
01149 pf_get_cep_stats(this->pf, &mean, &var);
01150
01151 resp.mean.px = mean.v[0];
01152 resp.mean.py = mean.v[1];
01153 resp.mean.pa = mean.v[2];
01154 resp.variance = var;
01155
01156 set = this->pf->sets + this->pf->current_set;
01157
01158 resp.particles_count = set->sample_count;
01159 resp.particles = new player_localize_particle_t [resp.particles_count];
01160
01161
01162 for(i=0;i<resp.particles_count;i++)
01163 {
01164 sample = set->samples + i;
01165 resp.particles[i].pose.px = sample->pose.v[0];
01166 resp.particles[i].pose.py = sample->pose.v[1];
01167 resp.particles[i].pose.pa = sample->pose.v[2];
01168 resp.particles[i].alpha = sample->weight;
01169 }
01170
01171 this->Publish(this->localize_addr, resp_queue,
01172 PLAYER_MSGTYPE_RESP_ACK,
01173 PLAYER_LOCALIZE_REQ_GET_PARTICLES,
01174 (void*)&resp);
01175 delete [] resp.particles;
01176 return(0);
01177 } else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
01178 PLAYER_POSITION2D_REQ_GET_GEOM, device_addr))
01179 {
01180 assert(hdr->size == 0);
01181 ProcessGeom(resp_queue, hdr);
01182 return(0);
01183 }
01184
01185
01186 for (int i = 0; i < this->sensor_count; i++)
01187 {
01188 int ret = this->sensors[i]->ProcessMessage(resp_queue, hdr, data);
01189 if (ret >= 0)
01190 return ret;
01191 }
01192
01193 return(-1);
01194 }
01195
01196 void
01197 AdaptiveMCL::ProcessGeom(QueuePointer &resp_queue, player_msghdr_t* hdr)
01198 {
01199 player_position2d_geom_t geom={{0}};
01200
01201 geom.size.sl = 0.01;
01202 geom.size.sw = 0.01;
01203
01204 Publish(this->position_addr, resp_queue,
01205 PLAYER_MSGTYPE_RESP_ACK,
01206 PLAYER_POSITION2D_REQ_GET_GEOM,
01207 &geom, sizeof(geom), NULL);
01208 }
01209
01210 #ifdef INCLUDE_RTKGUI
01211
01213
01214 int AdaptiveMCL::SetupGUI(void)
01215 {
01216 int i;
01217
01218
01219 rtk_init(NULL, NULL);
01220
01221 this->app = rtk_app_create();
01222
01223 this->canvas = rtk_canvas_create(this->app);
01224 rtk_canvas_title(this->canvas, "AdaptiveMCL");
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234 {
01235 rtk_canvas_size(this->canvas, 400, 400);
01236 rtk_canvas_scale(this->canvas, 0.1, 0.1);
01237 }
01238
01239 this->map_fig = rtk_fig_create(this->canvas, NULL, -1);
01240 this->pf_fig = rtk_fig_create(this->canvas, this->map_fig, 5);
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 rtk_fig_line(this->map_fig, 0, -100, 0, +100);
01255 rtk_fig_line(this->map_fig, -100, 0, +100, 0);
01256
01257
01258 this->robot_fig = rtk_fig_create(this->canvas, NULL, 9);
01259
01260
01261 rtk_fig_color(this->robot_fig, 0.7, 0, 0);
01262 rtk_fig_rectangle(this->robot_fig, 0, 0, 0, 0.40, 0.20, 0);
01263
01264
01265
01266
01267
01268 for (i = 0; i < this->sensor_count; i++)
01269 this->sensors[i]->SetupGUI(this->canvas, this->robot_fig);
01270
01271 rtk_app_main_init(this->app);
01272
01273 return 0;
01274 }
01275
01276
01278
01279 int AdaptiveMCL::ShutdownGUI(void)
01280 {
01281 int i;
01282
01283
01284 for (i = 0; i < this->sensor_count; i++)
01285 this->sensors[i]->ShutdownGUI(this->canvas, this->robot_fig);
01286
01287 rtk_fig_destroy(this->robot_fig);
01288 rtk_fig_destroy(this->pf_fig);
01289 rtk_fig_destroy(this->map_fig);
01290
01291 rtk_canvas_destroy(this->canvas);
01292 rtk_app_destroy(this->app);
01293
01294 rtk_app_main_term(this->app);
01295
01296 return 0;
01297 }
01298
01299
01301
01302 void AdaptiveMCL::UpdateGUI(void)
01303 {
01304 rtk_fig_clear(this->pf_fig);
01305 rtk_fig_color(this->pf_fig, 0, 0, 1);
01306 pf_draw_samples(this->pf, this->pf_fig, 1000);
01307 pf_draw_cep_stats(this->pf, this->pf_fig);
01308
01309
01310
01311
01312
01313 this->DrawPoseEst();
01314
01315 return;
01316 }
01317
01318
01320
01321 void AdaptiveMCL::DrawPoseEst()
01322 {
01323 int i;
01324 double max_weight;
01325 amcl_hyp_t *hyp;
01326 pf_vector_t pose;
01327
01328 this->Lock();
01329
01330 max_weight = -1;
01331 for (i = 0; i < this->hyp_count; i++)
01332 {
01333 hyp = this->hyps + i;
01334
01335 if (hyp->weight > max_weight)
01336 {
01337 max_weight = hyp->weight;
01338 pose = hyp->pf_pose_mean;
01339 }
01340 }
01341
01342 this->Unlock();
01343
01344 if (max_weight < 0.0)
01345 return;
01346
01347
01348 rtk_fig_origin(this->robot_fig, pose.v[0], pose.v[1], pose.v[2]);
01349
01350 return;
01351 }
01352
01353 #endif
01354
01355