From 8c28dd9b6e14226d7fc9e34f3a1fddcd3c466db3 Mon Sep 17 00:00:00 2001 From: William Chen <billyskc@ucla.edu> Date: Tue, 4 Sep 2018 16:09:28 -0700 Subject: [PATCH] added CoLo-AT module --- CoLo-AT/README.md | 133 ++++ CoLo-AT/RunningCoLo.png | Bin 0 -> 291775 bytes CoLo-AT/__init__.py | 1 + CoLo-AT/data_analysis/.DS_Store | Bin 0 -> 6148 bytes CoLo-AT/data_analysis/__init__.py | 1 + CoLo-AT/data_analysis/__init__.pyc | Bin 0 -> 219 bytes .../__pycache__/__init__.cpython-35.pyc | Bin 0 -> 203 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 201 bytes .../__pycache__/data_analyzer.cpython-35.pyc | Bin 0 -> 5900 bytes .../__pycache__/data_analyzer.cpython-36.pyc | Bin 0 -> 5482 bytes .../__pycache__/realtime_plot.cpython-35.pyc | Bin 0 -> 6555 bytes .../__pycache__/realtime_plot.cpython-36.pyc | Bin 0 -> 5905 bytes CoLo-AT/data_analysis/analysis.py | 330 ++++++++ CoLo-AT/data_analysis/animate_plot | 2 + CoLo-AT/data_analysis/animate_plot.py | 32 + CoLo-AT/data_analysis/data_analyzer.py | 243 ++++++ CoLo-AT/data_analysis/data_analyzer.pyc | Bin 0 -> 7036 bytes CoLo-AT/data_analysis/dataset_analyzer.py | 35 + CoLo-AT/data_analysis/realtime_plot.py | 217 +++++ CoLo-AT/data_analysis/realtime_plot.pyc | Bin 0 -> 8238 bytes CoLo-AT/data_analysis/results_graphs.py | 300 +++++++ CoLo-AT/dataset_manager/.DS_Store | Bin 0 -> 8196 bytes CoLo-AT/dataset_manager/__init__.py | 1 + .../__pycache__/__init__.cpython-35.pyc | Bin 0 -> 205 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 203 bytes .../existing_dataset.cpython-35.pyc | Bin 0 -> 14400 bytes .../existing_dataset.cpython-36.pyc | Bin 0 -> 12920 bytes CoLo-AT/dataset_manager/existing_dataset.py | 465 +++++++++++ CoLo-AT/dataset_manager/existing_dataset.py~ | 740 ++++++++++++++++++ CoLo-AT/dataset_manager/testing_dataset.py | 65 ++ CoLo-AT/localization_algos/.DS_Store | Bin 0 -> 10244 bytes CoLo-AT/localization_algos/__init__.py | 1 + .../centralized_ekf.cpython-35.pyc | Bin 0 -> 3999 bytes .../centralized_ekf.cpython-36.pyc | Bin 0 -> 3669 bytes .../centralized_ekf2.cpython-35.pyc | Bin 0 -> 4951 bytes .../centralized_ekf2.cpython-36.pyc | Bin 0 -> 4565 bytes .../__pycache__/ekf_gs_bound.cpython-35.pyc | Bin 0 -> 4460 bytes .../__pycache__/ekf_gs_bound.cpython-36.pyc | Bin 0 -> 4085 bytes .../__pycache__/ekf_gs_ci.cpython-36.pyc | Bin 0 -> 2862 bytes .../__pycache__/ekf_gs_ci2.cpython-35.pyc | Bin 0 -> 4625 bytes .../__pycache__/ekf_gs_ci2.cpython-36.pyc | Bin 0 -> 4224 bytes .../__pycache__/ekf_gs_sci.cpython-36.pyc | Bin 0 -> 5282 bytes .../__pycache__/ekf_gs_sci2.cpython-36.pyc | Bin 0 -> 5033 bytes .../__pycache__/ekf_ls_bda.cpython-35.pyc | Bin 0 -> 5386 bytes .../__pycache__/ekf_ls_bda.cpython-36.pyc | Bin 0 -> 4819 bytes .../__pycache__/ekf_ls_ci.cpython-36.pyc | Bin 0 -> 3877 bytes .../__pycache__/ekf_ls_ci2.cpython-36.pyc | Bin 0 -> 5074 bytes ...localization_algo_framework.cpython-35.pyc | Bin 0 -> 2419 bytes ...localization_algo_framework.cpython-36.pyc | Bin 0 -> 2362 bytes .../__pycache__/simple_ekf.cpython-35.pyc | Bin 0 -> 3483 bytes .../__pycache__/simple_ekf.cpython-36.pyc | Bin 0 -> 3239 bytes .../__pycache__/simple_ekf_2.cpython-36.pyc | Bin 0 -> 3794 bytes .../simple_ekf_meas_only.cpython-35.pyc | Bin 0 -> 3333 bytes .../simple_ekf_meas_only.cpython-36.pyc | Bin 0 -> 3130 bytes CoLo-AT/localization_algos/cal_test.py | 44 ++ CoLo-AT/localization_algos/centralized_ekf.py | 137 ++++ CoLo-AT/localization_algos/ekf_gs_bound.py | 143 ++++ CoLo-AT/localization_algos/ekf_gs_ci.py | 148 ++++ CoLo-AT/localization_algos/ekf_gs_sci2.py | 205 +++++ CoLo-AT/localization_algos/ekf_ls_bda.py | 175 +++++ CoLo-AT/localization_algos/ekf_ls_ci.py | 137 ++++ CoLo-AT/localization_algos/gs_ci_bound.py | 141 ++++ .../localization_algo_framework.py | 44 ++ CoLo-AT/localization_algos/simple_ekf.py | 100 +++ .../centralized_ekf2.py | 158 ++++ .../under_developing_algos/ekf_gs_ci2.py | 146 ++++ .../under_developing_algos/ekf_ls_bda2.py | 161 ++++ .../under_developing_algos/ekf_ls_ci2.py | 177 +++++ CoLo-AT/requests/__init__.py | 1 + .../request_response.cpython-35.pyc | Bin 0 -> 3051 bytes .../request_response.cpython-36.pyc | Bin 0 -> 2889 bytes CoLo-AT/requests/request_response.py | 53 ++ CoLo-AT/robots/__init__.py | 1 + CoLo-AT/robots/__init__.pyc | Bin 0 -> 212 bytes .../__pycache__/__init__.cpython-35.pyc | Bin 0 -> 196 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 194 bytes .../robot_centralized.cpython-35.pyc | Bin 0 -> 3327 bytes .../robot_centralized.cpython-36.pyc | Bin 0 -> 3106 bytes .../robot_distributive.cpython-35.pyc | Bin 0 -> 5159 bytes .../robot_distributive.cpython-36.pyc | Bin 0 -> 4822 bytes .../robot_parameters.cpython-35.pyc | Bin 0 -> 417 bytes .../robot_parameters.cpython-36.pyc | Bin 0 -> 397 bytes .../__pycache__/robot_system.cpython-35.pyc | Bin 0 -> 4050 bytes .../__pycache__/robot_system.cpython-36.pyc | Bin 0 -> 3636 bytes CoLo-AT/robots/robot_centralized.py | 73 ++ CoLo-AT/robots/robot_centralized.pyc | Bin 0 -> 4426 bytes CoLo-AT/robots/robot_distributive.py | 132 ++++ CoLo-AT/robots/robot_distributive.pyc | Bin 0 -> 7181 bytes CoLo-AT/robots/robot_parameters.py | 11 + CoLo-AT/robots/robot_parameters.pyc | Bin 0 -> 441 bytes CoLo-AT/robots/robot_system.py | 149 ++++ CoLo-AT/robots/robot_system.pyc | Bin 0 -> 4903 bytes CoLo-AT/robots/test_robot.py | 28 + CoLo-AT/ros_compatibility.py | 55 ++ CoLo-AT/ros_demo.py | 50 ++ CoLo-AT/sim_demo.py | 114 +++ CoLo-AT/simulation_process/.DS_Store | Bin 0 -> 6148 bytes CoLo-AT/simulation_process/__init__.py | 1 + .../__pycache__/__init__.cpython-35.pyc | Bin 0 -> 208 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 206 bytes .../__pycache__/sim_manager.cpython-35.pyc | Bin 0 -> 4267 bytes .../__pycache__/sim_manager.cpython-36.pyc | Bin 0 -> 3882 bytes .../__pycache__/state_recorder.cpython-35.pyc | Bin 0 -> 5019 bytes .../__pycache__/state_recorder.cpython-36.pyc | Bin 0 -> 4620 bytes CoLo-AT/simulation_process/data_generation.py | 56 ++ .../estimation_process_centralized.py | 162 ++++ .../estimation_process_cont_multirobot.py | 201 +++++ .../old_code/estimation_process_multirobot.py | 175 +++++ .../estimation_process_self_generated_data.py | 148 ++++ .../old_code/simumlation_process.py | 28 + CoLo-AT/simulation_process/sim_manager.py | 150 ++++ CoLo-AT/simulation_process/state_recorder.py | 139 ++++ CoLo-AT/simulation_process/test_recorder.py | 67 ++ CoLo-AT/test_simulation.py | 102 +++ CoLo-AT/verifications/.DS_Store | Bin 0 -> 6148 bytes 115 files changed, 6378 insertions(+) create mode 100755 CoLo-AT/README.md create mode 100644 CoLo-AT/RunningCoLo.png create mode 100755 CoLo-AT/__init__.py create mode 100644 CoLo-AT/data_analysis/.DS_Store create mode 100644 CoLo-AT/data_analysis/__init__.py create mode 100644 CoLo-AT/data_analysis/__init__.pyc create mode 100644 CoLo-AT/data_analysis/__pycache__/__init__.cpython-35.pyc create mode 100644 CoLo-AT/data_analysis/__pycache__/__init__.cpython-36.pyc create mode 100644 CoLo-AT/data_analysis/__pycache__/data_analyzer.cpython-35.pyc create mode 100644 CoLo-AT/data_analysis/__pycache__/data_analyzer.cpython-36.pyc create mode 100644 CoLo-AT/data_analysis/__pycache__/realtime_plot.cpython-35.pyc create mode 100644 CoLo-AT/data_analysis/__pycache__/realtime_plot.cpython-36.pyc create mode 100755 CoLo-AT/data_analysis/analysis.py create mode 100644 CoLo-AT/data_analysis/animate_plot create mode 100644 CoLo-AT/data_analysis/animate_plot.py create mode 100644 CoLo-AT/data_analysis/data_analyzer.py create mode 100644 CoLo-AT/data_analysis/data_analyzer.pyc create mode 100644 CoLo-AT/data_analysis/dataset_analyzer.py create mode 100644 CoLo-AT/data_analysis/realtime_plot.py create mode 100644 CoLo-AT/data_analysis/realtime_plot.pyc create mode 100755 CoLo-AT/data_analysis/results_graphs.py create mode 100644 CoLo-AT/dataset_manager/.DS_Store create mode 100644 CoLo-AT/dataset_manager/__init__.py create mode 100644 CoLo-AT/dataset_manager/__pycache__/__init__.cpython-35.pyc create mode 100644 CoLo-AT/dataset_manager/__pycache__/__init__.cpython-36.pyc create mode 100644 CoLo-AT/dataset_manager/__pycache__/existing_dataset.cpython-35.pyc create mode 100644 CoLo-AT/dataset_manager/__pycache__/existing_dataset.cpython-36.pyc create mode 100755 CoLo-AT/dataset_manager/existing_dataset.py create mode 100755 CoLo-AT/dataset_manager/existing_dataset.py~ create mode 100644 CoLo-AT/dataset_manager/testing_dataset.py create mode 100755 CoLo-AT/localization_algos/.DS_Store create mode 100755 CoLo-AT/localization_algos/__init__.py create mode 100644 CoLo-AT/localization_algos/__pycache__/centralized_ekf.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/centralized_ekf.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/centralized_ekf2.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/centralized_ekf2.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_gs_bound.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_gs_bound.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_gs_ci.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_gs_ci2.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_gs_ci2.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_gs_sci.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_gs_sci2.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_ls_bda.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_ls_bda.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_ls_ci.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/ekf_ls_ci2.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/localization_algo_framework.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/localization_algo_framework.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/simple_ekf.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/simple_ekf.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/simple_ekf_2.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/simple_ekf_meas_only.cpython-35.pyc create mode 100644 CoLo-AT/localization_algos/__pycache__/simple_ekf_meas_only.cpython-36.pyc create mode 100644 CoLo-AT/localization_algos/cal_test.py create mode 100755 CoLo-AT/localization_algos/centralized_ekf.py create mode 100644 CoLo-AT/localization_algos/ekf_gs_bound.py create mode 100644 CoLo-AT/localization_algos/ekf_gs_ci.py create mode 100644 CoLo-AT/localization_algos/ekf_gs_sci2.py create mode 100644 CoLo-AT/localization_algos/ekf_ls_bda.py create mode 100644 CoLo-AT/localization_algos/ekf_ls_ci.py create mode 100644 CoLo-AT/localization_algos/gs_ci_bound.py create mode 100644 CoLo-AT/localization_algos/localization_algo_framework.py create mode 100644 CoLo-AT/localization_algos/simple_ekf.py create mode 100644 CoLo-AT/localization_algos/under_developing_algos/centralized_ekf2.py create mode 100644 CoLo-AT/localization_algos/under_developing_algos/ekf_gs_ci2.py create mode 100644 CoLo-AT/localization_algos/under_developing_algos/ekf_ls_bda2.py create mode 100644 CoLo-AT/localization_algos/under_developing_algos/ekf_ls_ci2.py create mode 100755 CoLo-AT/requests/__init__.py create mode 100644 CoLo-AT/requests/__pycache__/request_response.cpython-35.pyc create mode 100644 CoLo-AT/requests/__pycache__/request_response.cpython-36.pyc create mode 100644 CoLo-AT/requests/request_response.py create mode 100755 CoLo-AT/robots/__init__.py create mode 100644 CoLo-AT/robots/__init__.pyc create mode 100644 CoLo-AT/robots/__pycache__/__init__.cpython-35.pyc create mode 100644 CoLo-AT/robots/__pycache__/__init__.cpython-36.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_centralized.cpython-35.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_centralized.cpython-36.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_distributive.cpython-35.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_distributive.cpython-36.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_parameters.cpython-35.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_parameters.cpython-36.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_system.cpython-35.pyc create mode 100644 CoLo-AT/robots/__pycache__/robot_system.cpython-36.pyc create mode 100755 CoLo-AT/robots/robot_centralized.py create mode 100644 CoLo-AT/robots/robot_centralized.pyc create mode 100755 CoLo-AT/robots/robot_distributive.py create mode 100644 CoLo-AT/robots/robot_distributive.pyc create mode 100644 CoLo-AT/robots/robot_parameters.py create mode 100644 CoLo-AT/robots/robot_parameters.pyc create mode 100644 CoLo-AT/robots/robot_system.py create mode 100644 CoLo-AT/robots/robot_system.pyc create mode 100644 CoLo-AT/robots/test_robot.py create mode 100644 CoLo-AT/ros_compatibility.py create mode 100644 CoLo-AT/ros_demo.py create mode 100644 CoLo-AT/sim_demo.py create mode 100644 CoLo-AT/simulation_process/.DS_Store create mode 100644 CoLo-AT/simulation_process/__init__.py create mode 100644 CoLo-AT/simulation_process/__pycache__/__init__.cpython-35.pyc create mode 100644 CoLo-AT/simulation_process/__pycache__/__init__.cpython-36.pyc create mode 100644 CoLo-AT/simulation_process/__pycache__/sim_manager.cpython-35.pyc create mode 100644 CoLo-AT/simulation_process/__pycache__/sim_manager.cpython-36.pyc create mode 100644 CoLo-AT/simulation_process/__pycache__/state_recorder.cpython-35.pyc create mode 100644 CoLo-AT/simulation_process/__pycache__/state_recorder.cpython-36.pyc create mode 100644 CoLo-AT/simulation_process/data_generation.py create mode 100755 CoLo-AT/simulation_process/old_code/estimation_process_centralized.py create mode 100755 CoLo-AT/simulation_process/old_code/estimation_process_cont_multirobot.py create mode 100755 CoLo-AT/simulation_process/old_code/estimation_process_multirobot.py create mode 100644 CoLo-AT/simulation_process/old_code/estimation_process_self_generated_data.py create mode 100644 CoLo-AT/simulation_process/old_code/simumlation_process.py create mode 100644 CoLo-AT/simulation_process/sim_manager.py create mode 100644 CoLo-AT/simulation_process/state_recorder.py create mode 100644 CoLo-AT/simulation_process/test_recorder.py create mode 100644 CoLo-AT/test_simulation.py create mode 100644 CoLo-AT/verifications/.DS_Store diff --git a/CoLo-AT/README.md b/CoLo-AT/README.md new file mode 100755 index 0000000..b2cb09a --- /dev/null +++ b/CoLo-AT/README.md @@ -0,0 +1,133 @@ +# LEMUR-CoLo-Sim + + + +## Synopsis + +Cooperative localization is still a challenging task for cooperative robot control. CoLo is a robotic simulation environment for cooperative localization or cooperative simultaneous localization and mapping (SLAM) using real world dataset[1] or simulated data. The goal of this project to let users to create and test their own algorithms with some existing algorithms. Compared with other popular robotic simulation environments[2], it has fewer dependencies and more convenient to add localization algorithms without worry much about the robot settings. Moreover, it is able to use both real world data and simulated data to test the robustness and liabilities of these algorithms, whereas other simulation environments use only simulated data. +https://drive.google.com/file/d/1NlUM2QXT_KfZkVOJu3Xsm8_QL8OSy6hz/view?usp=sharing +## Features + +Real world dataset +Flexible control on the real world dataset +Easy to add and modify algorithms +Preloaded with several existing algorithms +Modularized simulation environment +Basic statistical analytic tools for algorithms + + + +## Installation + +1. Clone this repository: + +``` +git clone git@git.uclalemur.com:billyskc/Simulation-Environment-for-Cooperative-Localization.git +``` + +## How to run the simulation environment + +1. Install all dependencies + +2. Create a python script for the environment(ex: test_simulation.py) +a. Create a dataset_manager with proper setting +b. Load a localization algorithm in to robots +c. Create simulation manager, recorder and analyzer in CoLo +d. Put all these part in simulation manager + +3. Run CoLo +In MAC terminal: +``` +python Localization_envir.py +``` + + + +## Available Aglorithm: +1. LS-Cen +2. LS-CI +3. LS-BDA +4. GS-SCI +5. GS-CI + + + +## Dataset: +UTIAS dataset: +- MRCLAM_Dataset1 +- MRCLAM_Dataset2 +- MRCLAM_Dataset3 +- MRCLAM_Dataset4 +- MRCLAM_Dataset5 +- MRCLAM_Dataset6 +- MRCLAM_Dataset7 +- MRCLAM_Dataset8 +- MRCLAM_Dataset9 +details info: [UTIAS Dataset](http://asrl.utias.utoronto.ca/datasets/mrclam/). + + + +## Authors + +Shengkang Chen +Cade Mallett +Kyle Wong + + + + +## Analytical Tool: + +Plots: +1. Estimation deviation error vs. time +2. Trace of state variance vs. time +3. Landmark observation vs. time +4. Relative observation vs .time + +Values: +1. Avg. location deviation errors +2. Avg. trace of state variance + +## How to add new localization algorithm to the environment +1. Create the algorithm in the predefined algorithm framework +``` +def propagation_update(self, robot_data, sensor_data): +[s, orinetations, sigma_s, index] = robot_data +... +return [s, orinetations, sigma_s] + +def absolute_obser_update(self, robot_data, sensor_data): +[s, orinetations, sigma_s, index] = robot_data +... +return [s, orinetations, sigma_s] + +def relative_obser_update(self, robot_data, sensor_data): +[s, orinetations, sigma_s, index] = robot_data +... +return [s, orinetations, sigma_s] + +def communication(self, robot_data, sensor_data): +[s, orinetations, sigma_s, index] = robot_data +... +return [s, orinetations, sigma_s] +``` +4. Add it to the algorithm library + + +## Files and folders includes within the project + +### Datasets Folder: +Store the UTIAS datasets which has odometry, measurement and groundtruth data for each robot + +### Functions Folder: +Contains all the python scripts +Folders: +simulation process +robots +requests +localization algos +dataset_manager +data_analysis + + + diff --git a/CoLo-AT/RunningCoLo.png b/CoLo-AT/RunningCoLo.png new file mode 100644 index 0000000000000000000000000000000000000000..dee957ebfe608ef64baef13cc76268f2d87845bd GIT binary patch literal 291775 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%0Ae4Mwm^e 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 HaNK_YQ`Y6e literal 0 HcmV?d00001 diff --git a/CoLo-AT/__init__.py b/CoLo-AT/__init__.py new file mode 100755 index 0000000..b6e690f --- /dev/null +++ b/CoLo-AT/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/CoLo-AT/data_analysis/.DS_Store b/CoLo-AT/data_analysis/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**<q8>++&mCkOWA81W14cNZ<zv;LbK1Poaz?KmsK2CSc!( z0ynLxE!0092;Krf2c+FF_Fe*7ECH>lEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0<F0fCPF1$Cyrb|F7^5{eNG?83~ZUUlGt@xh*qZDeu<Z%US-OSsOPv j)R!Z4KLME7ReXlK;d!wEw5GODWMKRea10D2@KpjYNUI8I literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/__init__.py b/CoLo-AT/data_analysis/__init__.py new file mode 100644 index 0000000..b6e690f --- /dev/null +++ b/CoLo-AT/data_analysis/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/CoLo-AT/data_analysis/__init__.pyc b/CoLo-AT/data_analysis/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26489d0bba1beeb8dc793427dcb6ae25076e944f GIT binary patch literal 219 zcmY+8%?iRW41l}sB7#205NcmQWFWhVmwEG0%GzO|ZN}P7=D`Q`HGBb6^<qfA{F4-~ z)$;MIFD?5?PQD@wYl0@tm}Ts&bJmmvl^`RO2{B=F`o<Kp@*lxaF0SZ|xPi5xoM^y} zRz*P1Yd^t&-WeZxhXX$#_GX~oWcU$VW#RrA6y50Cv=M|>QAy>ModX0RC3uKZZu>bd Q=+e%i9<AA@uR{9d4T5(yL;wH) literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/__pycache__/__init__.cpython-35.pyc b/CoLo-AT/data_analysis/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b50e6bc72aa57d159806ba314e68b284a5e34db3 GIT binary patch literal 203 zcmX|*Jqp4=5QQgdAwtB;J49Ib0wRK>6PwssEK9P%f&B@)NhB8D$1A0^@(NZ?QaH@} z7~Z^rS;z6>*{9bP0K7^6n$UD0g(ab&jz9xkiV0-N^b?VpM18b56X6AZM#hM*;x}g$ zzoXVD4bRXtTGr?+OKpqZS)**tO6S?pxk`E3wThiwE;T;JATJx64;O(KvX(+xsk?xI X3xO7EA+}Z5&v(WZjaK{Nl|X_YwTC!b literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/__pycache__/__init__.cpython-36.pyc b/CoLo-AT/data_analysis/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c63692804c06816026ad58cdf8da4db3ee6706e3 GIT binary patch literal 201 zcmX|*zY4-Y42N^-AY#GSs8DZk6%nMHxYW(zIC@tM+@I2GD|PUFe5I~VzJil!2Ls<n z_$7gCqiFH$)9VTV-o(Eq)E$VhBq>nLzy;JKgLwL36veD(>oXZ%P|YY9_0|05t>$+$ z2Bqa0+Q!Hly-QNpV&$FHu1*SHB}eZ|UD2%7$;s!^;A33mMdR|}B5);ZDWsF83mCW% V=&%-IQ+EA)XT55S-Vd(?0)E1#ICTI3 literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/__pycache__/data_analyzer.cpython-35.pyc b/CoLo-AT/data_analysis/__pycache__/data_analyzer.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce6de0632fa7a1a0d7e09c19fa612bd312bd0984 GIT binary patch literal 5900 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/__pycache__/data_analyzer.cpython-36.pyc b/CoLo-AT/data_analysis/__pycache__/data_analyzer.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56fb8249090c574284edf5a20dfca7d00694b64c GIT binary patch literal 5482 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 TnvLQW%3~tZRq-Qtbi48&&{9D0 literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/__pycache__/realtime_plot.cpython-35.pyc b/CoLo-AT/data_analysis/__pycache__/realtime_plot.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d9551659bc133328d33f6bc01e68622869d0d57 GIT binary patch literal 6555 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/__pycache__/realtime_plot.cpython-36.pyc b/CoLo-AT/data_analysis/__pycache__/realtime_plot.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..366ecb8d007190f9aa9ccc357bae5995364e12c0 GIT binary patch literal 5905 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 VPKE2b9!d^n+ReKTsLQDH{|587XJ-Ha literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/analysis.py b/CoLo-AT/data_analysis/analysis.py new file mode 100755 index 0000000..786273d --- /dev/null +++ b/CoLo-AT/data_analysis/analysis.py @@ -0,0 +1,330 @@ + +import numpy as np +import math +import os + +def find_nearest_time_idx(array, start_idx, value): + #array[i][0] is the time + i = start_idx + if array[i]['time'] < value: + while array[i]['time'] < value: + i = i+1 + if array[i]['time']-value < value-array[i-1]['time']: + return i + else: + return i-1 + else: + return i + +class DataAnalyzer(): + def __init__(self, name): + self.name = name + + + def estimation_time_analysis_single(est_data): + #calcaulate the root-mean-square deviation (RMSD) between estimation and ground truth and the trace of state variance at each time step. + + robot_num = str(robot_num) + file="/Datasets/"+dataset_name+"/Robot"+robot_num+"_Groundtruth.dat" + path=os.getcwd()+file + groundtruth_file=open(path,'r+'); + + file="/Results_files/estimation_results/"+estimation_file_name+".txt" + path=os.getcwd()+file + est_result_file = open(path, "r+") + + file="/Results_files/analysis_results/"+analysis_result_name+".txt" + path=os.getcwd()+file + analysis_file = open(path, "w") + + + s_ground = groundtruth_file.readline() + s_ground = groundtruth_file.readline() + s_ground = groundtruth_file.readline() + s_ground = groundtruth_file.readline() + + s_ground = groundtruth_file.readline() + t_ground = float(s_ground.split()[0]) + + s_est = est_result_file.readline() + t_est = float(s_est.split()[0]) + + while(s_est): + s = [float(s_est.split()[1]), float(s_est.split()[2]), float(s_est.split()[3])] + + while t_ground <= t_est: + s_ground = groundtruth_file.readline() + t_ground = float(s_ground.split()[0]) + if t_ground >= t_est: + s_g = [float(s_ground.split()[1]), float(s_ground.split()[2])] + break + + err_sq =[(s_g[0]-s[0])*(s_g[0]-s[0]), (s_g[1]-s[1])*(s_g[1]-s[1])] + #err_sq[2] = min((s_g[2]-s[2])*(s_g[2]-s[2]), (s_g[2]+2*math.pi-s[2])*(s_g[2]+2*math.pi-s[2]), (s_g[2]-2*math.pi-s[2])*(s_g[2]-2*math.pi-s[2])) + err_sqrt = math.sqrt(sum(err_sq)) + err_x = s_g[1]-s[1] + analysis_file.write(str(t_est)+ '\t' + str(err_sqrt) + '\t' + str(s_est.split()[3]) + '\t' + str(err_x) +'\n') # s_est.split()[3] is the trace of sigma_S + + s_est = est_result_file.readline() + if(s_est): + t_est = float(s_est.split()[0]) + + groundtruth_file.close() + est_result_file.close() + analysis_file.close() + + return 1 + + + def estimation_time_analysis_multirobot(dataset_name, general_estimation_file_name, general_analysis_result_name, robot_list): + for i, robot in enumerate(robot_list): + robot_num = robot.get_label() + estimation_file_name = general_estimation_file_name +'%d' %robot_num + analysis_result_name = general_analysis_result_name + '%d' %robot_num + estimation_time_analysis_single(dataset_name, robot_num, estimation_file_name, analysis_result_name) + + + def avg_MSE_and_trace(analysis_result_name): + + #initialization for all the lists for plotting + dev_l_t = [] + dev_l_RMSE = [] + dev_l_trace = [] + + file="/Results_files/analysis_results/"+analysis_result_name+".txt" + path=os.getcwd()+file + with open(path,'r') as analysis_file: + s_dev = analysis_file.readline() + while (s_dev): + dev_l_t.append(float(s_dev.split( )[0])) + dev_l_RMSE.append(float(s_dev.split( )[1])) + dev_l_trace.append(float(s_dev.split( )[2])) + s_dev = analysis_file.readline() + + avg_RMSE = float(sum(dev_l_RMSE)) / max(len(dev_l_RMSE), 1) + avg_trace = float(sum(dev_l_trace)) / max(len(dev_l_trace), 1) + print '******Analysis Results******' + print 'Avg. RMSE: ' + str(avg_RMSE) + print 'Avg. trace of state covariance: ' + str(avg_trace) + print '*************\n' + + return [avg_RMSE, avg_trace] + + + + def average_correctness_analysis_per_run(dataset_name, dataset_labels, groundtruth_data, est_result_array): + # #calcaulate the avg. root-mean-square deviation (RMSD) between estimation and groundtruth, and the avg. trace of state variance in each time interval(1s) for all robots. + + num_robot = len(dataset_labels) + analysis_result_array = [[] for i in range(num_robot)] + + time_arr = [] + avg_RMSE_arr = [] + avg_trace_arr = [] + + analysis_file_arr = [] + + for i, robot_label in enumerate(dataset_labels): #analysis for each robot + j = 0 + g_idx = 0 + while j < len(est_result_array[i]): + est_t = est_result_array[i][j]['time'] + g_idx = find_nearest_time_idx(groundtruth_data[i], g_idx, est_t) + + gt_x_pos = groundtruth_data[i][g_idx]['x_pos'] + gt_y_pos = groundtruth_data[i][g_idx]['y_pos'] + est_x_pos = est_result_array[i][j]['x_pos'] + est_y_pos = est_result_array[i][j]['y_pos'] + sigma_s_trace = est_result_array[i][j]['sigma_s_trace'] + + err_sq =[(est_x_pos-gt_x_pos)*(est_x_pos-gt_x_pos), (est_y_pos-gt_y_pos)*(est_y_pos-gt_y_pos)] + err_sqrt = math.sqrt(sum(err_sq)) + + analysis_result = {'time':est_t, 'err_sqrt':err_sqrt, 'sigma_s_trace':sigma_s_trace} + analysis_result_array[i].append(analysis_result) + + #analysis_file_arr[i].write(str(est_t)+ '\t' + str(err_sqrt) + '\t' + str(sigma_s_trace) +'\n') + + j = j+1 + + start_time = est_result_array[0][0]['time'] + 1/2 + + + mean_err = [] + mean_time = [] + mean_STD = [] + + loc_dic = {} + for i, robot_label in enumerate(dataset_labels): + start_loc = 0 + loc_dic[i] = start_loc + + avg_trace = np.zeros(num_robot) + avg_err = np.zeros(num_robot) + + while(len(loc_dic) != 0): + for i, robot_label in enumerate(dataset_labels): + try: + loc = loc_dic[i] + except KeyError: + continue + try: + time_interval_start = analysis_result_array[i][loc]['time'] + except IndexError: + del loc_dic[i] + continue + + time_interval = 0.5 # in [s] for each time interval + num_analyized_result = 0 + sum_trace = 0 + sum_err = 0 + while analysis_result_array[i][loc]['time'] < time_interval_start + time_interval: + sum_trace += analysis_result_array[i][loc]['sigma_s_trace'] + sum_err += analysis_result_array[i][loc]['err_sqrt'] + num_analyized_result += 1 + + loc +=1 + + try: + analysis_result_array[i][loc] + except IndexError: + del loc_dic[i] + break + + loc_dic[i] = loc + avg_trace[i] = sum_trace/num_analyized_result + avg_err[i] = sum_err/num_analyized_result + + + all_robot_avg_err = sum(avg_err)/num_robot + all_robot_avg_trace = sum(avg_trace)/num_robot + avg_STD = math.sqrt(all_robot_avg_trace) + + mean_time.append(time_interval_start+1/2 - start_time) + mean_err.append(all_robot_avg_err) + mean_STD.append(avg_STD) + + return [mean_time, mean_err, mean_STD] + + def recording_data(algos_set, all_mean_time, all_mean_err, all_mean_STD, dataset_name): + + + for i, algo_name in enumerate(algos_set): + algo_analysis_file_name = dataset_name +'_algo_'+algo_name + file="/Results_files/analysis_results/"+algo_analysis_file_name+".txt" + path=os.getcwd()+file + algo_analysis_file = open(path, "w") + algo_analysis_file.write('#time[s] \t\t actual error[m] \t state STD[m] \n') + + for j in range(len(all_mean_time[i])): + algo_analysis_file.write(str(all_mean_time[i][j])+ '\t' + str(all_mean_err[i][j]) + '\t' + str(all_mean_STD[i][j]) +'\n') + + algo_analysis_file.close() + + + return 1 + + def average_correctness_analysis_per_run_w_bound(dataset_name, dataset_labels, groundtruth_data, est_result_array): + # #calcaulate the avg. root-mean-square deviation (RMSD) between estimation and groundtruth, and the avg. trace of state variance in each time interval(1s) for all robots. + + num_robot = len(dataset_labels) + analysis_result_array = [[] for i in range(num_robot)] + + time_arr = [] + avg_RMSE_arr = [] + avg_trace_arr = [] + + analysis_file_arr = [] + + for i, robot_label in enumerate(dataset_labels): #analysis for each robot + j = 0 + g_idx = 0 + while j < len(est_result_array[i]): + est_t = est_result_array[i][j]['time'] + g_idx = find_nearest_time_idx(groundtruth_data[i], g_idx, est_t) + + gt_x_pos = groundtruth_data[i][g_idx]['x_pos'] + gt_y_pos = groundtruth_data[i][g_idx]['y_pos'] + est_x_pos = est_result_array[i][j]['x_pos'] + est_y_pos = est_result_array[i][j]['y_pos'] + sigma_s_trace = est_result_array[i][j]['sigma_s_trace'] + bound = est_result_array[i][j]['bound'] + + + err_sq =[(est_x_pos-gt_x_pos)*(est_x_pos-gt_x_pos), (est_y_pos-gt_y_pos)*(est_y_pos-gt_y_pos)] + err_sqrt = math.sqrt(sum(err_sq)) + + analysis_result = {'time':est_t, 'err_sqrt':err_sqrt, 'sigma_s_trace':sigma_s_trace, 'bound': bound} + analysis_result_array[i].append(analysis_result) + #analysis_file_arr[i].write(str(est_t)+ '\t' + str(err_sqrt) + '\t' + str(sigma_s_trace) +'\n') + + j = j+1 + + start_time = est_result_array[0][0]['time'] + 1/2 + + + mean_err = [] + mean_time = [] + mean_STD = [] + mean_bound_sq = [] + + loc_dic = {} + for i, robot_label in enumerate(dataset_labels): + start_loc = 0 + loc_dic[i] = start_loc + + avg_trace = np.array(np.zeros(num_robot)) + avg_bound = np.array(np.zeros(num_robot)) + avg_err = np.array(np.zeros(num_robot)) + + + while(len(loc_dic) != 0): + for i, robot_label in enumerate(dataset_labels): + try: + loc = loc_dic[i] + except KeyError: + continue + try: + time_interval_start = analysis_result_array[i][loc]['time'] + except IndexError: + del loc_dic[i] + continue + + time_interval = 0.5 # in [s] for each time interval + num_analyized_result = 0 + sum_trace = 0 + sum_bound = 0 + sum_err = 0 + while analysis_result_array[i][loc]['time'] < time_interval_start + time_interval: + sum_trace += analysis_result_array[i][loc]['sigma_s_trace'] + sum_bound += analysis_result_array[i][loc]['bound'] + sum_err += analysis_result_array[i][loc]['err_sqrt'] + num_analyized_result += 1 + + loc +=1 + try: + analysis_result_array[i][loc] + except IndexError: + del loc_dic[i] + break + + loc_dic[i] = loc + avg_trace[i] = sum_trace/num_analyized_result + avg_bound[i] = sum_bound/num_analyized_result + avg_err[i] = sum_err/num_analyized_result + + + all_robot_avg_err = sum(avg_err)/num_robot + all_robot_avg_trace = sum(avg_trace)/num_robot + all_robot_avg_bound = sum(avg_bound)/num_robot + avg_STD = math.sqrt(all_robot_avg_trace) + avg_bound_sq = math.sqrt(all_robot_avg_bound) + + mean_time.append(time_interval_start+1/2 - start_time) + mean_err.append(all_robot_avg_err) + mean_STD.append(avg_STD) + mean_bound_sq.append(avg_bound_sq) + + return [mean_time, mean_err, mean_STD, mean_bound_sq] + + diff --git a/CoLo-AT/data_analysis/animate_plot b/CoLo-AT/data_analysis/animate_plot new file mode 100644 index 0000000..9429dd1 --- /dev/null +++ b/CoLo-AT/data_analysis/animate_plot @@ -0,0 +1,2 @@ +import matplotlib.pyplot as plt +import matplotlib.animation as animation \ No newline at end of file diff --git a/CoLo-AT/data_analysis/animate_plot.py b/CoLo-AT/data_analysis/animate_plot.py new file mode 100644 index 0000000..23653ca --- /dev/null +++ b/CoLo-AT/data_analysis/animate_plot.py @@ -0,0 +1,32 @@ +import matplotlib.pyplot as plt +import matplotlib.animation as animation + + + + + + +class Animator(): + """docstring for animate_plot""" + def __init__(self, dataset_labels, data_recorder, analyzer): + self.name = "Animator" + self.dataset_labels = dataset_labels + self.robot_loc_time_unit = analyzer.robot_location_at_unit_time_interval(state_recorder) + + + def get_robot_locations(self, robot_loc_time_unit, mode): + arr = [] + # robots in dataset are labeled from 1 to num_robots + for robot_label in self.dataset_labels: + # declare a mapping of x, y coordinate lists + m = {'x': robot_loc_time_unit[i][mode + '_x'], 'y': robot_loc_time_unit[i][mode + '_y']} + arr.append(m) + return arr + + def update(self, ): + pass + + def animate_plot(dataset_labels, data_recorder, analyzer, lm = None): + self.robot_locations_gt = get_robot_locations(num_robots, self.robot_loc_time_unit, 'gt') + self.robot_locations_est = get_robot_locations(num_robots, self.robot_loc_time_unit, 'est') + ani = animation.FuncAnimation(fig, update, fargs = (num_robots, fig, init_path_est, init_path_gt, init_points_est, init_points_gt, robot_locations_est, robot_locations_gt, times, time_func, min_time_arr, arr_err, arr_var, loc_err, trace_sigma), frames=min_length(times), interval=50, blit=False) \ No newline at end of file diff --git a/CoLo-AT/data_analysis/data_analyzer.py b/CoLo-AT/data_analysis/data_analyzer.py new file mode 100644 index 0000000..2eb2c31 --- /dev/null +++ b/CoLo-AT/data_analysis/data_analyzer.py @@ -0,0 +1,243 @@ +import numpy as np +import math +import os +import matplotlib.pyplot as plt + + +def find_nearest_time_idx(array, start_idx, value): + #array[i][0] is the time + i = start_idx + if array[i]['time'] < value: + while array[i]['time'] < value: + i = i+1 + if array[i]['time']-value < value-array[i-1]['time']: + return i + else: + return i-1 + else: + return i + +class Analyzer(): + def __init__(self, name, dataset_labels): + self.name = name + self.dataset_labels = dataset_labels + + def set_dataset_label(self, dataset_labels): + self.dataset_labels = dataset_labels + + def plot_loc_err_and_trace(self, loc_err, trace, time_arr, measurement_count): + fig = plt.figure() + plt.suptitle('Correctness analysis') + fig1 = fig.add_subplot(311) + fig2 = fig.add_subplot(312) + fig3 = fig.add_subplot(313) + + fig1.plot(time_arr, loc_err) + fig2.plot(time_arr, trace) + fig3.bar(time_arr, measurement_count) + + + fig1.set_title('Estimation deviation error') + fig1.set_xlabel('Time[s]') + fig1.set_ylabel('RMS[m]') + #fig1.set_ylim(0, 6) + fig1.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + + fig2.set_title('Trace of state variance') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('Sigma_s [m^2]') + #fig2.set_ylim(0, 0.08) + fig2.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + + + fig3.set_title('Observation counts') + fig3.set_xlabel('Time[s]') + fig3.set_ylabel('Num of obser') + #fig1.set_ylim(0, 6) + fig3.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + + fig.subplots_adjust(hspace = 1.2) + plt.show() + + + + def calculate_loc_err_and_trace_state_variance_per_run(self, data_recorder, unit_time_interval = 0.5, plot_graphs = True): + #recorded_dataline = [time, robot_label, est_x_pos, est_y_pos, trace_state_var, gt_x_pos, gt_y_pos, loc_err, update type] + data = data_recorder.get_recorded_data() + update_in_time_order = data_recorder.get_updata_type_in_time_order() + data_in_time_order = data_recorder.get_data_in_time_order() + + time_index = 0 + time = data_in_time_order[time_index][0] + interval_start_time = time + finish_flag = False + + loc_err_per_run = [] + measurement_num = [] + trace_per_run = [] + time_arr = [] + + while True: + loc_err_per_time_iterval = 0 + trace_per_time_iterval = 0 + num_dataline_per_time_iterval = 0 + measurement_count = 0 + + while interval_start_time <= time < interval_start_time+unit_time_interval: + try: + data_in_time_order[time_index] + except IndexError: + finish_flag = True + break + time = data_in_time_order[time_index][0] + + if update_in_time_order[time_index] == 'landmark observation' or update_in_time_order[time_index] == 'relative observation': + measurement_count +=1 + + loc_err_per_time_iterval+= data_in_time_order[time_index][7] + trace_per_time_iterval += data_in_time_order[time_index][4] + num_dataline_per_time_iterval+=1 + + time_index += 1 + + if finish_flag: + break + + if num_dataline_per_time_iterval != 0: + loc_err_per_run.append(loc_err_per_time_iterval/num_dataline_per_time_iterval) + trace_per_run.append(trace_per_time_iterval/num_dataline_per_time_iterval) + + else: + loc_err_per_run.append(0) + trace_per_run.append(0) + + measurement_num.append(measurement_count) + time_arr.append((interval_start_time+unit_time_interval+interval_start_time)/2) + interval_start_time = interval_start_time+unit_time_interval + + + print(data_recorder.name,': ') + print('Avg location deviation errors per run: ', sum(loc_err_per_run)/len(loc_err_per_run)) + print('Avg trace of state variances per run: ', sum(trace_per_run)/len(trace_per_run)) + + if plot_graphs: + self.plot_loc_err_and_trace(loc_err_per_run, trace_per_run, time_arr, measurement_count = measurement_num) + + return loc_err_per_run, trace_per_run, time_arr + + def robot_location_at_unit_time_interval(self, data_recorder, unit_time_interval = 0.2): + #recorded_dataline = [time, robot_label, est_x_pos, est_y_pos, trace_state_var, gt_x_pos, gt_y_pos, loc_err] + data = data_recorder.get_recorded_data() + update_in_time_order = data_recorder.get_updata_type_in_time_order() + data_in_time_order = data_recorder.get_data_in_time_order() + + time_index = 0 + time = data_in_time_order[time_index][0] + interval_start_time = time + finish_flag = False + + robot_loc_time_unit = {} + for i, label in enumerate(self.dataset_labels): + robot_loc_time_unit[label] = {'time': [], 'est_x': [], 'est_y': [], 'gt_x': [], 'gt_y': []} + + while True: + robot_sum_loc_per_time_unit = {} + measurement_update = False + for i, label in enumerate(self.dataset_labels): + robot_sum_loc_per_time_unit[label] = {'est_x': 0, 'est_y': 0, 'gt_x': 0, 'gt_y': 0, 'num': 0} + + while interval_start_time <= time < interval_start_time+unit_time_interval: + + try: + data_in_time_order[time_index] + except IndexError: + finish_flag = True + break + + time = data_in_time_order[time_index][0] + + if update_in_time_order[time_index] == 'measurement': + measurement_update = True + + robot_label = data_in_time_order[time_index][1] + #get sum for est_x, est_y, gt_x, gt_y and num for each robor per time interval + robot_sum_loc_per_time_unit[robot_label]['est_x'] += data_in_time_order[time_index][2] + robot_sum_loc_per_time_unit[robot_label]['est_y'] += data_in_time_order[time_index][3] + robot_sum_loc_per_time_unit[robot_label]['gt_x'] += data_in_time_order[time_index][5] + robot_sum_loc_per_time_unit[robot_label]['gt_y'] += data_in_time_order[time_index][6] + robot_sum_loc_per_time_unit[robot_label]['num'] += 1 + + time_index += 1 + + if finish_flag: + break + + for i, robot_label in enumerate(self.dataset_labels): + for j in ['est_x', 'est_y', 'gt_x', 'gt_y']: + if robot_sum_loc_per_time_unit[robot_label]['num'] != 0: + robot_loc_time_unit[robot_label][j].append(robot_sum_loc_per_time_unit[robot_label][j]/robot_sum_loc_per_time_unit[robot_label]['num']) + else: + robot_loc_time_unit[robot_label][j].append(robot_loc_time_unit[robot_label][j][-1]) # use the previous value + + robot_loc_time_unit[robot_label]['time'].append((interval_start_time+unit_time_interval+interval_start_time)/2) + + interval_start_time = interval_start_time+unit_time_interval + + return robot_loc_time_unit + + + def algos_comparison_graph(self, arr_loc_err, arr_trace): + fig = plt.figure() + fig1 = fig.add_subplot(211) + fig2 = fig.add_subplot(212) + + for loc_err in arr_loc_err: + fig1.plot(loc_err[0], loc_err[1], label = loc_err[2]) + + for trace in arr_trace: + fig2.plot(trace[0], trace[1], label = trace[2]) + + fig1.set_title('Estimation deviation error') + fig1.set_xlabel('Time[s]') + fig1.set_ylabel('RMS[m]') + #fig1.set_ylim(0, 6) + fig1.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + + fig2.set_title('Trace of state variance') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('Sigma_s [m^2]') + #fig2.set_ylim(0, 0.08) + fig2.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + plt.subplots_adjust(hspace=.6) + plt.show() + + + + def algos_comparison(self, arr_data_recorder, only_trace=None): + arr_loc_err = [] + arr_trace = [] + for data_recorder in arr_data_recorder: + loc_err_per_run, trace_per_run, time_stamps = self.calculate_loc_err_and_trace_state_variance_per_run(data_recorder, plot_graphs = True) + if data_recorder.name not in only_trace: + arr_loc_err.append([time_stamps, loc_err_per_run, data_recorder.name]) + arr_trace.append([time_stamps, trace_per_run, data_recorder.name] ) + + print('Plotting Comparison Graphs') + self.algos_comparison_graph(arr_loc_err, arr_trace) + return arr_loc_err, arr_trace + + + + + + + + + + + + + + + + diff --git a/CoLo-AT/data_analysis/data_analyzer.pyc b/CoLo-AT/data_analysis/data_analyzer.pyc new file mode 100644 index 0000000000000000000000000000000000000000..44b59bceea581694a219af7ee3b8c4aa2ee15c96 GIT binary patch literal 7036 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 RU>}v?rb(EiXG^vEe*kDT7X1JK literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/dataset_analyzer.py b/CoLo-AT/data_analysis/dataset_analyzer.py new file mode 100644 index 0000000..a9e77f8 --- /dev/null +++ b/CoLo-AT/data_analysis/dataset_analyzer.py @@ -0,0 +1,35 @@ +import numpy as np +import os + +import initialization_datasets + +def dataset_analysis(dataset_name, duration, sampling_period): + # this function is to find the characteristic of the dataset. Given name of the dataset and period of sampling (in second), + # it will output v_max, r_max of for each robot during each period, also the mean and the STD of observation time interval + dataset_labels = [1,2,3,4,5] #all robots + [landmark_map, start_time, start_state_arr, measurement_data, odometry_data, groundtruth_data] = initialization_datasets.initialization_MRCLAMDatasets_multirobots(dataset_name, dataset_labels, duration) + + print 'robot\t\tv_max\t\tr_mean\t\tr_std\tnum_obser\ttime' + + for i, label in enumerate(dataset_labels): + t = start_time + while t <= start_time+duration-sampling_period: + v_seq = [obs['velocity'] for obs in odometry_data[i] if t+sampling_period > obs['time'] >= t] # create a list of velocity data for each sampling period + v_max = max(v_seq) + + r_seq = [obs['measurment_range'] for obs in measurement_data[i] if t+sampling_period > obs['time'] >= t] # create a list of measurement_range data for each sampling period + try: + r_max = max(r_seq) + r_mean = np.mean(r_seq) + r_std = np.std(r_seq) + + if r_std < 0.8: + print str(label)+'\t'+ str(v_max) + '\t\t'+ str(r_max) +'\t' +str(r_std) + '\t'+ str(len(r_seq)) + '\t' + str(t-start_time) + 's~' + str(t+sampling_period-start_time) +'s' + + except ValueError: + print '\tempty array' + + t = t + sampling_period + + return 1 + diff --git a/CoLo-AT/data_analysis/realtime_plot.py b/CoLo-AT/data_analysis/realtime_plot.py new file mode 100644 index 0000000..436e6fc --- /dev/null +++ b/CoLo-AT/data_analysis/realtime_plot.py @@ -0,0 +1,217 @@ +from matplotlib import pyplot as plt +from matplotlib import animation +from matplotlib.font_manager import FontProperties +from matplotlib import gridspec +import numpy as np +import time +import sys +""" +author: Kyle +""" +# update point: function handling the logic of animating the dot, denoting the current +# position of the robot +# 2 modes: est for estimate, gt for groundtruth +# not used in the implementation +def update_point(i, fig, scat, robot_loc_time_unit, dataset_labels, robotNum, mode): + label = robotNum + x = robot_loc_time_unit[label][mode + '_x'][i] + y = robot_loc_time_unit[label][mode + '_y'][i] + loc = [x, y] + scat.set_offsets(loc) + return scat, +# update path: function handling the logic of animating a path trail left by the robot +# 2 modes: est for estimate, gt for groundtruth +# not used in the implementation +def update_path(i, fig, l, robot_loc_time_unit, dataset_labels, robotNum, mode): + label = robotNum + x = robot_loc_time_unit[label][mode + '_x'] + y = robot_loc_time_unit[label][mode + '_y'] + l.set_data(x[:i], y[:i]) + return l, +# get the list of x, y locations of each robot and return those as a list +# 2 modes: est for estimate, gt for groundtruth +def get_robot_locations(num_robots, robot_loc_time_unit, mode): + arr = [] + # robots in dataset are labeled from 1 to num_robots + for i in range(1, num_robots + 1): + # declare a mapping of x, y coordinate lists + m = {'x': robot_loc_time_unit[i][mode + '_x'], 'y': robot_loc_time_unit[i][mode + '_y']} + arr.append(m) + return arr +# initialize initial positions of each robot for dots +def initialize_robots(num_robots, locations, colors): + arr = [] + for i in range(0, num_robots): + scat = plt.scatter(locations[i]['x'], locations[i]['y'], c=colors[i]) + arr.append(scat) + return arr +# initialize starting point of the robot path trial +# 2 modes: est for estimate, gt for groundtruth +def initialize_path(num_robots, ax, locations, colors, mode): + s = "" + mode_str = "" + # define path marker, based on mode + # define label representation, based on mode + if mode == 'est': + s = ':' + mode_str = 'estimate' + else: + s = '-' + mode_str = 'groundtruth' + arr = [] + for i in range(0, num_robots): + line, = ax.plot(locations[i]['x'], locations[i]['y'], colors[i]+s, label='Robot ' + str(i+1) + ' ' + mode_str) + arr.append(line) + return arr +# initialize graphs to be incrementally constructed based on animation over time +def initialize_graphs(num_robots, ax_err, ax_var, loc_err, trace_sigma, time_func, colors): + arr_err = [] + arr_var = [] + for i in range(0, num_robots): + time_arr = time_func(i + 1) + line, = ax_err.plot(time_arr, loc_err[i+1], colors[i]+'-', label='Robot ' + str(i+1)) + line2, = ax_var.plot(time_arr, trace_sigma[i+1], colors[i]+'-', label='Robot ' + str(i+1)) + arr_err.append(line) + arr_var.append(line2) + return [arr_err, arr_var] +# get the time array for each robot +def get_robot_times(num_robots, robot_loc_time_unit): + arr = [] + for i in range(1, num_robots + 1): + arr.append(robot_loc_time_unit[i]['time']) + return arr +# return the time array of minimum time duration +def min_robot_times(times): + res = [] + m = 2**63 - 1 + for arr in times: + if m > len(arr): + res = list(arr) + m = len(arr) + return res +# update function for aggregate animation +def update(i, num_robots, fig, l_est, l_gt, scat_est, scat_gt, location_est, location_gt, times, time_func, min_time_arr, arr_err, arr_var, loc_err, trace_sigma): + # aggregate of both scatterplot point and path trails + res = [] + for txt in fig.texts: + txt.set_visible(False) + tmp = fig.text(0.8, 0.03, "Time: " + str(round(times[0][i], 1)), fontsize=12) + for robotNum in range(0, num_robots): + # factor out common variables + est_x = location_est[robotNum]['x'] + est_y = location_est[robotNum]['y'] + gt_x = location_gt[robotNum]['x'] + gt_y = location_gt[robotNum]['y'] + # scatter + s1 = scat_est[robotNum] + s2 = scat_gt[robotNum] + s1.set_offsets([est_x[i], est_y[i]]) + s2.set_offsets([gt_x[i], gt_y[i]]) + res.append(s1,) + res.append(s2,) + # path + l1 = l_est[robotNum] + l2 = l_gt[robotNum] + l1.set_data(est_x[:i], est_y[:i]) + l2.set_data(gt_x[:i], gt_y[:i]) + res.append(l1,) + res.append(l2,) + # graph + time_arr = time_func(robotNum + 1) + ind = find_index_time(time_arr, min_time_arr[i]) + l3 = arr_err[robotNum] + l4 = arr_var[robotNum] + l3.set_data(time_arr[:ind], loc_err[robotNum+1][:ind]) + l4.set_data(time_arr[:ind], trace_sigma[robotNum+1][:ind]) + #return res +# to prevent subscript out of bounds, determine minimum length timestamp array to be used +# for animation +def min_length(times): + m = 2**63 - 1 # 64-bit max int upper bound + for arr in times: + m = min(m, len(arr)) + return m +# return the index of the array that is less than or equal to t, the current time +def find_index_time(arr, t): + ind = 0 + for i in arr: + if i >= t: + return ind + ind += 1 + return ind +# precondition: dataset should have sufficient information for N robots +# postcondition: dataset is not manipulated; the function simply mutates the data for +# simpler data processing internally +# This function handles the plot animation graph functionalities +def animate_plot(dataset_labels, data_recorder, analyzer, lm = None): + + time_func = data_recorder.get_time_arr + loc_err = data_recorder.get_loc_err_arr() + trace_sigma = data_recorder.get_trace_sigma_s_arr() + + # obtain data + robot_loc_time_unit = analyzer.robot_location_at_unit_time_interval(data_recorder) + # determine number of robots under consideration for this animation + num_robots = int(len(dataset_labels)) + # initialize graphs: error, demo, state variance + fig = plt.figure(figsize=(12, 9), tight_layout=True) + fig.subplots_adjust(top=0.88) + gs = gridspec.GridSpec(3, 2) + fig.suptitle('CoLo Robot Demo Simulation', fontsize=14) + ax_err = plt.subplot(gs[0, 0]) + ax_var = plt.subplot(gs[0, 1]) + ax = plt.subplot(gs[1:, :]) + #ax.set_xlim([-2, 2]) + #ax.set_ylim([-2, 2]) + # configure graph + # set bounds + #fig.set_size_inches((18,18)) + #ax = plt.axes(xlim=(-6, 6), ylim=(-6, 8)) + #ax_err = plt.axes(xlim=(0, 100), ylim=(0, 0.4)) + # assign labels + ax.set_title('CoLo Demo') + ax.set_xlabel('x-axis[m]') + ax.set_ylabel('y-axis[m]') + ax_err.set_title('Estimation deviation error') + ax_err.set_xlabel('Time[s]') + ax_err.set_ylabel('RMS[m]') + ax_var.set_title('Trace of state variance') + ax_var.set_xlabel('Time [s]') + ax_var.set_ylabel('Sigma_s [m^2]') + # obtain robot locations from dataset + robot_locations_est = get_robot_locations(num_robots, robot_loc_time_unit, 'est') + robot_locations_gt = get_robot_locations(num_robots, robot_loc_time_unit, 'gt') + # hardcoded for now, to be passed as parameter in test_simulation call + colors = ['b', 'g', 'r', 'c', 'k'] + # initialize graph initial positions + init_points_est = initialize_robots(num_robots, robot_locations_est, colors) + init_points_gt = initialize_robots(num_robots, robot_locations_gt, colors) + init_path_est = initialize_path(num_robots, ax, robot_locations_est, colors, 'est') + init_path_gt = initialize_path(num_robots, ax, robot_locations_gt, colors, 'gt') + ig = initialize_graphs(num_robots, ax_err, ax_var, loc_err, trace_sigma, time_func, colors) + arr_err = ig[0] + arr_var = ig[1] + + if lm != None: + lm_x = [] + lm_y = [] + for landmark_id, [x, y] in lm.items(): + lm_x.append(x) + lm_y.append(y) + ax.scatter(lm_x, lm_y, s=120, marker=(5,0), label='Landmark') + + # obtain robot timestamps + times = get_robot_times(num_robots, robot_loc_time_unit) + min_time_arr = min_robot_times(times) + # initialize animation, passing in frame update function + # robot animation + ani = animation.FuncAnimation(fig, update, fargs = (num_robots, fig, init_path_est, init_path_gt, init_points_est, init_points_gt, robot_locations_est, robot_locations_gt, times, time_func, min_time_arr, arr_err, arr_var, loc_err, trace_sigma), frames=min_length(times), interval=50, blit=False) + # Show legend + fontP = FontProperties() + fontP.set_size('small') + ax.legend(prop=fontP, bbox_to_anchor=(1.1, 1.0), loc=9, ncol=1) + ax_var.legend(prop=fontP, bbox_to_anchor=(1.2, 1.0), loc=9, ncol=1) + # Show graph + plt.show() + # (optional) save as GIF, comment the following line if you don't want this + ani.save('full_test9.gif', writer="imagemagick", fps=60) diff --git a/CoLo-AT/data_analysis/realtime_plot.pyc b/CoLo-AT/data_analysis/realtime_plot.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0873796d526d99aa6a6f0b56e08abaa3fe4fc654 GIT binary patch literal 8238 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/data_analysis/results_graphs.py b/CoLo-AT/data_analysis/results_graphs.py new file mode 100755 index 0000000..7ecd4ab --- /dev/null +++ b/CoLo-AT/data_analysis/results_graphs.py @@ -0,0 +1,300 @@ +import numpy as np +import os +import matplotlib.pyplot as plt +import math +import sys +def find_nearest_time_idx(array, start_idx, value): + #array[i][0] is the time + i = start_idx + if array[i]['time'] < value: + while array[i]['time'] < value: + i = i+1 + if array[i]['time']-value < value-array[i-1]['time']: + return i + else: + return i-1 + else: + return i +def plots_MSE_and_trace(dataset_labels, analysis_result_name, dataset_name, algo_name): + + fig = plt.figure() + plt.suptitle('Correctness analysis Algo: ' + algo_name + ' Dataset: ' + dataset_name ) + fig1 = fig.add_subplot(211) + fig2 = fig.add_subplot(212) + for i, label in enumerate(dataset_labels): + #initialization for all the lists for plotting + dev_l_t = [] + dev_l_RMSE = [] + dev_l_trace = [] + file="/Results_files/analysis_results/"+analysis_result_name+str(label)+".txt" + path=os.getcwd()+file + with open(path,'r') as analysis_file: + s_dev = analysis_file.readline() + starting_time = float(s_dev.split( )[0]) + print starting_time + while (s_dev): + dev_l_t.append(float(s_dev.split( )[0]) - starting_time) + dev_l_RMSE.append(float(s_dev.split( )[1])) + dev_l_trace.append(float(s_dev.split( )[2])) + s_dev = analysis_file.readline() + fig1.plot(dev_l_t, dev_l_RMSE, label= 'Robot %d' %label) + fig2.plot(dev_l_t, dev_l_trace, label= 'Robot %d' %label) + + fig1.set_title('Root mean square error') + fig1.set_xlabel('Time[s]') + fig1.set_ylabel('RMS[m]') + #fig1.set_ylim(0, 6) + fig1.legend(loc=2) + + fig2.set_title('Trace of state variance') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('Sigma_s [m^2]') + #fig2.set_ylim(0, 0.08) + fig2.legend(loc=2) + + fig.subplots_adjust(hspace = 0.8) + plt.show() + + return 1 + + + +def plots_mean_MSE_and_trace(mean_time, mean_err, mean_trace, dataset_name, algo_name): + + fig = plt.figure() + plt.suptitle('Correctness analysis Algo: ' + algo_name + ' Dataset: ' + dataset_name ) + fig1 = fig.add_subplot(211) + fig2 = fig.add_subplot(212) + + + fig1.plot(mean_time, mean_err) + fig2.plot(mean_time, mean_trace) + + fig1.set_title('Avg. Root mean square error') + fig1.set_xlabel('Time[s]') + fig1.set_ylabel('RMS[m]') + #fig1.set_ylim(0, 6) + + + fig2.set_title('Avg. Trace of state variance') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('Sigma_s [m^2]') + #fig2.set_ylim(0, 0.08) + + fig.subplots_adjust(hspace = 0.8) + plt.show() + + return 1 + + +def plots_mean_MSE_and_trace_for_multiple_algos(figure_name, algos_set, all_mean_time, all_mean_err, all_mean_STD, dataset_name, comm_fail_rate): + + fig = plt.figure() + plt.suptitle('Correctness analysis' + ' Dataset: ' + dataset_name + ' comm failure rate: ' + str(comm_fail_rate)) + fig1 = fig.add_subplot(211) + fig2 = fig.add_subplot(212) + + for i, algo_name in enumerate(algos_set): + print algo_name + if algo_name == 'GS-CI': + fig1.plot(all_mean_time[i], all_mean_err[i], label = algo_name, linewidth=3.0) + fig2.plot(all_mean_time[i], all_mean_STD[i], label = algo_name, linewidth=3.0) + else: + fig1.plot(all_mean_time[i], all_mean_err[i], label = algo_name) + fig2.plot(all_mean_time[i], all_mean_STD[i], label = algo_name) + + + fig1.set_title('Actual location error') + fig1.set_xlabel('Time [s]') + fig1.set_ylabel('RMS [m]') + #fig1.set_ylim(0, 3) + fig1.legend(loc=2) + #plt.legend(bbox_to_anchor=(0, 1), loc='upper left', ncol=1) + + + + fig2.set_title('Trace of state deviation') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('STD [m]') + #fig2.set_ylim(0, 1) + fig2.legend(loc=2) + + fig.subplots_adjust(hspace = 0.8) + figure_name = figure_name +'.png' + print figure_name + plt.savefig(figure_name) + + plt.show() + + return 1 + + +def plots_mean_MSE_and_trace_for_multiple_algos_w_bound(figure_name, algos_set, all_mean_time, all_mean_err, all_mean_STD, all_mean_bound, dataset_name, comm_fail_rate): + + fig = plt.figure() + plt.suptitle('Correctness analysis' + ' Dataset: ' + dataset_name + ' comm failure rate: ' + str(comm_fail_rate)) + fig1 = fig.add_subplot(211) + fig2 = fig.add_subplot(212) + + for i, algo_name in enumerate(algos_set): + print algo_name + if algo_name == 'GS-CI': + fig1.plot(all_mean_time[i], all_mean_err[i], label = algo_name, linewidth=3.0) + fig2.plot(all_mean_time[i], all_mean_STD[i], label = algo_name, linewidth=3.0) + fig2.plot(all_mean_time[i], all_mean_bound[i], label = 'bound', linewidth=3.0) + else: + fig1.plot(all_mean_time[i], all_mean_err[i], label = algo_name) + fig2.plot(all_mean_time[i], all_mean_STD[i], label = algo_name) + + + fig1.set_title('Actual location error') + fig1.set_xlabel('Time [s]') + fig1.set_ylabel('RMS [m]') + #fig1.set_ylim(0, 3) + fig1.legend(loc=2) + #plt.legend(bbox_to_anchor=(0, 1), loc='upper left', ncol=1) + + + + fig2.set_title('Trace of state deviation') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('STD [m]') + #fig2.set_ylim(0, 1) + fig2.legend(loc=2) + + fig.subplots_adjust(hspace = 0.8) + figure_name = figure_name +'.png' + print figure_name + plt.savefig(figure_name) + + plt.show() + + return 1 + +def plot_err_x(starting_time, dataset_labels, analysis_result_name, dataset_name): + plt.figure(1) + + for i, label in enumerate(dataset_labels): + list_t = [] + list_err_x = [] + file="/Results_files/analysis_results/"+analysis_result_name+str(label)+".txt" + path=os.getcwd()+file + with open(path,'r') as analysis_file: + s_dev = analysis_file.readline() + while (s_dev): + list_t.append(float(s_dev.split( )[0])-starting_time) + list_err_x.append(float(s_dev.split( )[3])) + s_dev = analysis_file.readline() + plt.plot(list_t, list_err_x, label= 'Robot %d' %label) + + #plt.ylim(-2, 2) + #plt.xlim(0, 600) + + plt.legend(loc=1) + plt.title('Robot x-pos error Dataset: ' + dataset_name) + plt.xlabel('Time[s]') + plt.ylabel('Robot x-pos error[m]') + plt.show() + pass + +def plot_RMSE_and_trace_withrespectto_noise(list2D_avg_RMSE, list2D_avg_trace, noise_range): + list_process_noise = np.arange(noise_range[0], noise_range[1], 0.2) + print list_process_noise + plt.figure(1) + plt.suptitle('Error analysis for single EKF for all robots with respect to measurement noise') + + fig1 = plt.subplot(211) + for i in range(5): + fig1.plot(list_process_noise, list2D_avg_RMSE[i], label= 'Robot %d' %(i+1)) + + plt.title('Root mean square error(RMSE)') + plt.xlabel('Measurement noise') + plt.ylabel('RMSE') + #plt.ylim(1, 2) + + plt.legend(loc=1) + + fig2 = plt.subplot(212) + for i in range(5): + fig2.plot(list_process_noise, list2D_avg_trace[i], label= 'Robot %d' %(i+1)) + + plt.title('Trace of state variance') + plt.xlabel('Measurement noise') + plt.ylabel('Trace') + plt.legend(loc=2) + #plt.ylim(0, 2) + + plt.subplots_adjust(hspace = 0.8) + plt.show() + + return 1 + + + +def single_plot_w_bond(start_time, est_result_array, groundtruth_data, robot_index, algo_name): + time_arr = [] + err_arr = [] + sigma_s_arr = [] + bound_arr = [] + i = robot_index + g_idx = 0 + j = 0 + while j < len(est_result_array[i]): + est_t = est_result_array[i][j]['time'] + g_idx = find_nearest_time_idx(groundtruth_data[i], g_idx, est_t) + + if abs(groundtruth_data[i][g_idx]['time']-est_result_array[i][j]['time']) > 0.5: + sys.exit('groundtruth time not match!') + + gt_x_pos = groundtruth_data[i][g_idx]['x_pos'] + gt_y_pos = groundtruth_data[i][g_idx]['y_pos'] + est_x_pos = est_result_array[i][j]['x_pos'] + est_y_pos = est_result_array[i][j]['y_pos'] + sigma_s_trace = est_result_array[i][j]['sigma_s_trace'] + bound = est_result_array[i][j]['bound'] + + err_sq = sum([(est_x_pos-gt_x_pos)*(est_x_pos-gt_x_pos), (est_y_pos-gt_y_pos)*(est_y_pos-gt_y_pos)]) + err_sqrt = math.sqrt(err_sq) + + est_t = est_t - start_time + #print est_t + #print err_sq + + time_arr.append(est_t) + err_arr.append(err_sq) + sigma_s_arr.append(sigma_s_trace) + bound_arr.append(bound) + + #print sigma_s_arr + + j = j+1 + + print est_result_array[0][0] + print est_result_array[0][-1] + + fig = plt.figure() + plt.suptitle('GS-CI analysis w/ e = 0.5') + fig1 = fig.add_subplot(211) + fig2 = fig.add_subplot(212) + + fig1.plot(time_arr, err_arr, label = algo_name, linewidth=3.0) + fig2.plot(time_arr, sigma_s_arr, label = algo_name, linewidth=3.0) + #fig2.plot(time_arr, bound_arr, label = 'bound', linewidth=3.0) + + + fig1.set_title('Actual location error') + fig1.set_xlabel('Time [s]') + fig1.set_ylabel('RMS [m]') + #fig1.set_ylim(0, 1) + fig1.legend(loc=2) + #plt.legend(bbox_to_anchor=(0, 1), loc='upper left', ncol=1) + + fig2.set_title('Trace of state deviation') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('STD [m]') + #fig2.set_ylim(0, 0.2) + fig2.legend(loc=2) + + plt.show() + + return 1 \ No newline at end of file diff --git a/CoLo-AT/dataset_manager/.DS_Store b/CoLo-AT/dataset_manager/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0b6aee47e8927b5469c9e0e3ffc5096f41ce3014 GIT binary patch literal 8196 zcmeHMU2GIp6h3EZVP;zBEtb*&mTp?B1zTuKYrz0++eK3asccIN1(w;JfsRgR>dtJJ zQj1M|AqM{*{0+QlVq)+K!NezHeDMc0(Hc?1gAYFFi;qU5iRa!sOQf)`V8Yzw-tXRf z&Y64fH{Z<kYyklK3uY%k0{|#gIkGBhZc@0N*BeSKoT(&4iU-JnL3IKw$lTx^O+*Yt z3`7h>3`7h>4E!G$pl>!WN}2Dzv_@^jK*Ycu$pC*pB&c#shBz-#ygH~6DF9&wO^ZT( z$^%49BE)2f^AbfUT~lTc7=~h)VxSBsdxE<YCPSQ;D8m6|IAFLkh8YTq)hR9^+yRpk zqc&n7V&Fywc<x?B*?I=1VCK5~J(Df^Q(4E$lE>xjlw<orN5}UVTT)TEbeW=Pind%k zoSyKC>A(mIe!r0)=c6Gbn8=3xVb61}^^NR)+bU*Q-GJu?hV5E;5p0_lxf~j`UDGS} zdj;3@#dXrspeU-MX4u-<+4jzDT^((S_AMQAZHd{=uFkD(iLE`ob91V)x}|f+;L*vM zle16HojNNIiQ$U^Y8D;(T=^3pGyPna_RJ&7kmC5$1Co^3Yb8>ylt@vvDt+(~ZTFa+ z^W3z3(#o(JpEwz$;ZWY1rt^>HJf|?}`WaT6Gn`z(F#@a4ak#TT7FZ_&-aF`f`Cvde zW*95@);^2;>}e}S-W0l$Uuo}DV0*5=-^%-h&B+dVPW62Cs(8~q_jU9<@L+0T`HC8* zt<>s9r)}TPI@U<hHiL-+hM%)s({_&^B$nO4K4x2awKjH99d?aLYoUI11Jl>&>&itb ztXUZ=WbLO4b}+NRR@5wC->7ScOxoQZ&*WD#*(F64mgYuXALo{VyhW|4C~{M+`bL!* z%CJx8l{4+yW|jHs@RKA3F{5{B-3l|+5y!|{j-2Y%wkhmUb#z)DTTX7*b}F^lrjF&j z$w@koFIG<W>G~1A@@~Tq_D)$Y?dnrno~>@E-$lDRz-@h|$@io*CtD?df&rEB?~x8o z&<)#R2o8V=MK}Ymz^m{UoQL<}L-+)~g0JBl_!h3f&+se!4u8U5@HhN}OR)ym;d*Su z1a80{ydQfpiG4VLDICOon8p#@kK<^fg~xFMT`b}WJc+aTES|yV@g;m2-^91^0$#*R z_yK-|pW)~D1zyJQ@JIYf?lV@>_Z~SewRn|!<;5F5(Xk^p6L0*Xhqcsg74Hw#T(Pw) z@2Xq1zPYu%t9N_fwVS%=UjA29LPb(0LOvyVh?{wxF1fb#HEXr_2&v3EvG{o?DV{Ck zdQuj2(n>rLZ&FA(EF8AP?^Q_NEGDkCVPjllOGwG87;f6E#aShZRuRK3-I~TKNY&E1 zbsJfil76Li$4;^Wf9_PVlGYMWsS3lzYAmb8ci{qj3}2E8ufSFK1%87+5J-R3SWo&( zU^Cv0Ew~9cV<&cDH}1flp%QoFV>pD5lN!hIFlO*58u$b{q(u*>aE7!vho|rvJdMwh zB45B4@pXKIRCyN9;X8PKkp>4#>XV4?mDk{OI`2B3dz?H<3cfx#8r>=emdJ$~c>ceu z{O|v_YCF+75d#qew}AnyNTpN#v~al>GS9UWRF6{Sh5OA*6d}}zbevG6<Am4#VMzT1 fx$>A~i1QL@hRQAfAt3tx^S?x+@4ryro!k5is|f>m literal 0 HcmV?d00001 diff --git a/CoLo-AT/dataset_manager/__init__.py b/CoLo-AT/dataset_manager/__init__.py new file mode 100644 index 0000000..b6e690f --- /dev/null +++ b/CoLo-AT/dataset_manager/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/CoLo-AT/dataset_manager/__pycache__/__init__.cpython-35.pyc b/CoLo-AT/dataset_manager/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3c36bd5c707e061f9d31563c5f2f8b0ccc41c32 GIT binary patch literal 205 zcmX|*Jqp4=5QQhvLWGEwcZjg=1w;f%CpNLOSeEQ2F6>X(Y$95CAFq_w$}3noN#QW> zV|eohW|buKXP;e`0PsfrE5>P$Y8D8A9f1Zoix~2B@`=z)qdr=nknjROMPtObqE}}m zy(z5~H#AqK)jTL?NoG6coi)-1QaVo#&ehW6u9M{G3a-^-4AQc-#c<J3!2@q(V1`>> ZNlzJ5Rt3g3^}U~MjT5bwyWyDz1wSsuIUfK3 literal 0 HcmV?d00001 diff --git a/CoLo-AT/dataset_manager/__pycache__/__init__.cpython-36.pyc b/CoLo-AT/dataset_manager/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd31344ff4309517f4f33b309e86875ec7027076 GIT binary patch literal 203 zcmX|*zY4-I5QneTLBxWuQ6Xk<6%nMHxYW%dgeI+l{3&T#(ZToemAX3l3Qk@-c<_B3 zzq^CmB+2~QXO|@aypey!*zJ*Kff67h4QCK>4(a3*VU$LFv^t^T1%8UbsBcBD&PaMw zS}Sg7u1u?WP|lLfcFH?zqz$BWo*bO3rN>z($<Y;DtH-!V%hnddMMDJ-ype$!Zh0j= XWlUKW7+cr(ezrAEv|8?lXBq^4JQ_JV literal 0 HcmV?d00001 diff --git a/CoLo-AT/dataset_manager/__pycache__/existing_dataset.cpython-35.pyc b/CoLo-AT/dataset_manager/__pycache__/existing_dataset.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8f4113524e113b5bc74d0dcc2360c8aac644e3c GIT binary patch literal 14400 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/dataset_manager/__pycache__/existing_dataset.cpython-36.pyc b/CoLo-AT/dataset_manager/__pycache__/existing_dataset.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c4964b7c5fa18e5c4e54efd6d80b0a0f47841d3 GIT binary patch literal 12920 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 M*g#3lvgD@!3qr9-Q~&?~ literal 0 HcmV?d00001 diff --git a/CoLo-AT/dataset_manager/existing_dataset.py b/CoLo-AT/dataset_manager/existing_dataset.py new file mode 100755 index 0000000..ec3fc68 --- /dev/null +++ b/CoLo-AT/dataset_manager/existing_dataset.py @@ -0,0 +1,465 @@ +# -*- coding: utf-8 -*- + +import numpy as np +from numpy import random +import sys +from math import atan2, sqrt, pi +import random +from math import cos +from math import sin +import math +import os.path +''' +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/requests') +import request_response +''' + +def find_nearest_time_idx(l, value): + if len(l) != 0: + array = np.asarray(l) + idx = (np.abs(array-value)).argmin() + return idx + else: + return None + + + +def find_next_time_idx(array, start_idx, value): + i = start_idx + try: + array[i] + except IndexError: + i = -1 + return i + while array[i] < value: + i = i+1 + try: + array[i] + except IndexError: + i = -1 + break + return i + +def linear_interpolation(end0, end1, x): + [x0, y0] = end0 + [x1, y1] = end1 + if x1 == x0: + y = y0 + else: + y = y0+(x-x0)*(y1-y0)/(x1-x0) + return y + +class Dataset: + + def __init__(self, dataset_name): + self.name = dataset_name + + def create_landmark_map(self): + ### Build landmark map ### + self.landmark_map = {} + path=self.dataset_path + "Landmark_Groundtruth.dat" + landmark_file=open(path,'r+'); + s = landmark_file.readline() + while(s): + if(s[0]!='#'): + landmark_location = [float(s.split( )[1]), float(s.split( )[2])] + self.landmark_map.update({int(s.split( )[0]): landmark_location}) + s = landmark_file.readline() + landmark_file.close() + #print "lm ", self.landmark_map, " lm" + return self.landmark_map + + + def load_MRCLAMDatasets(self, dataset_path, dataset_labels, duration, adding_actifical_dataline = True, delay_start = 5): + print ('******** Initialization Started ********') + print ('add synthetic data: ', adding_actifical_dataline) + self.dataset_path = dataset_path + print("Absolute datapath: ") + print(self.dataset_path) + self.dataset_labels = dataset_labels + self.adding_actifical_dataline = adding_actifical_dataline + self.create_landmark_map() + + self.num_robots = len(self.dataset_labels) + self.measurement_data = [[] for i in range(self.num_robots)] + self.odometry_data = [[] for i in range(self.num_robots)] + self.gt_data_odo = [[] for i in range(self.num_robots)] + self.gt_data_meas = [[] for i in range(self.num_robots)] + self.groundtruth_data = [[] for i in range(self.num_robots)] + + #self.groundtruth_time= [[] for i in range(self.num_robots)] + self.time_arr = {'odometry': [[] for i in range(self.num_robots)], 'measurement': [[] for i in range(self.num_robots)], 'groundtruth': [[] for i in range(self.num_robots)]} + + #initialization for MRCLAMDatasets: put files into dictionaries: + self.duration = duration # some more time to avoid index error + self.start_time_arr = [] + #finding the starting time: + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + groundtruth_path = self.dataset_path+"Robot"+robot_num+"_Groundtruth.dat" + with open(groundtruth_path,'r+') as groundtruth_file: + for line in groundtruth_file: + if str(line.split()[0]) != '#': + time = float(line.split()[0]) + self.start_time_arr.append(time) + break + self.start_time = max(self.start_time_arr) + delay_start + self.end_time = self.start_time + self.duration + print('Staring time: ', self.start_time) + #finding starting states: + self.starting_states = {} + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + groundtruth_path = self.dataset_path+"Robot"+robot_num+"_Groundtruth.dat" + with open(groundtruth_path,'r+') as groundtruth_file: + for line in groundtruth_file: + if line[0] != '#' and float(line.split()[0]) >= self.start_time: + time = round(float(line.split()[0]), 3) + x_pos = float(line.split()[1]) + y_pos = float(line.split()[2]) + orientation = float(line.split()[3]) + self.starting_states[label] = [time, x_pos, y_pos, orientation] + break + print('Staring states: ') + print(self.starting_states) + + + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + + groundtruth_path = self.dataset_path+"Robot"+robot_num+"_Groundtruth.dat" + with open(groundtruth_path,'r+') as groundtruth_file: + for line in groundtruth_file: + if line[0] != '#' and (self.end_time >= float(line.split()[0]) >= self.start_time): + time = round(float(line.split()[0]), 3) + x_pos = float(line.split()[1]) + y_pos = float(line.split()[2]) + orientation = float(line.split()[3]) + groundtruth_info = {'time':time, 'x_pos':x_pos, 'y_pos':y_pos, 'orientation':orientation} + self.groundtruth_data[i].append(groundtruth_info) + self.time_arr['groundtruth'][i].append(time) + + + meas_path = self.dataset_path+"Robot"+robot_num+"_Measurement_x.dat" + with open(meas_path,'r+') as measure_file: + for line in measure_file: + if line[0] != '#' and (self.end_time>= float(line.split()[0]) >= self.start_time): + time = round(float(line.split()[0]), 3) + subject_ID = int(line.split()[1]) + measurment_range = float(line.split()[2]) + bearing = float(line.split()[3]) + meas_info = {'time':time, 'subject_ID':subject_ID, 'measurment_range': measurment_range, 'bearing':bearing} + + g_idx = find_nearest_time_idx(self.time_arr['groundtruth'][i],time) + gt_x = self.groundtruth_data[i][g_idx]['x_pos'] + gt_y = self.groundtruth_data[i][g_idx]['y_pos'] + orientation = self.groundtruth_data[i][g_idx]['orientation'] + matched_gt_info = {'time':time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':orientation} + + self.measurement_data[i].append(meas_info) + self.gt_data_meas[i].append(matched_gt_info) + self.time_arr['measurement'][i].append(time) + + + odo_path = self.dataset_path+"Robot"+robot_num+"_Odometry.dat" + with open(odo_path,'r+') as odometry_file: + lines = odometry_file.readlines() + for line_idx in range(0, len(lines)): + line = lines[line_idx] + if line[0] != '#' and (self.end_time >= float(line.split()[0]) >= self.start_time): + t = float(line.split()[0]) + time = round(float(line.split()[0]), 3) + g_idx = find_nearest_time_idx(self.time_arr['groundtruth'][i],time) + velocity = float(line.split()[1]) + a_v = float(line.split()[2]) + orientation = self.groundtruth_data[i][g_idx]['orientation'] + try: + next_line = lines[line_idx+1] + next_time = float(next_line.split()[0]) + delta_t = next_time - time + except IndexError: + delta_t = 0 + if delta_t < 0: + sys.exit('incorrect delta_t: '+ str(delta_t)) + + odo_info = {'time':time, 'velocity':velocity, 'angular velocity': a_v, 'orientation':orientation, 'delta_t': delta_t} + gt_x = self.groundtruth_data[i][g_idx]['x_pos'] + gt_y = self.groundtruth_data[i][g_idx]['y_pos'] + matched_gt_info = {'time':time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':orientation} + + self.odometry_data[i].append(odo_info) + self.gt_data_odo[i].append(matched_gt_info) + self.time_arr['odometry'][i].append(time) + + self.data_trackers = {'odometry': np.ones((self.num_robots,), dtype=np.int), 'measurement':np.ones((self.num_robots,), dtype=np.int)} + # tracker for each robot for both each type of data to keep track of their location in the dataset + self.odo_data_trackers = np.ones((self.num_robots,), dtype=np.int) + self.dataset_data = {'odometry': self.odometry_data, 'measurement': self.measurement_data, 'groundtruth': self.groundtruth_data} + self.dataset_matched_gt_data = {'odometry': self.gt_data_odo, 'measurement': self.gt_data_meas} + print ('******** Initialization Completed ********') + print("self.start_time: ", self.start_time) + print("self.starting_states ", self.starting_states) + return self.start_time, self.starting_states, self.dataset_data, self.time_arr + + def dataset_reset(self): + self.data_trackers = {'odometry': np.ones((self.num_robots,), dtype=np.int),'measurement':np.ones((self.num_robots,), dtype=np.int), 'groundtruth':np.ones((self.num_robots,), dtype=np.int)} + + def get_start_time(self): + return self.start_time + + def get_starting_states(self): + return self.starting_states + + def get_duration(self): + return self.duration + + def get_landmark_map(self): + return self.landmark_map + + def get_start_moving_times(self): + start_moving_times = [] + time_idx = 0 + for i, label in enumerate(self.dataset_labels): + start_moving_times.append(self.dataset_data['odometry'][i][time_idx]['time']) + return start_moving_times + + def get_time_arr(self, data_catagory): + # retunr an array of time shows time for next dataline for each robot given data catagory + time_arr =[] + for i, label in enumerate(self.dataset_labels): + time_idx = self.data_trackers[data_catagory][i] + if time_idx == -1: + time_arr.append(self.start_time + self.duration + 10) # so that it will be out of range and not be selected + else: + time_arr.append(self.dataset_data[data_catagory][i][time_idx]['time']) + return time_arr + + def find_corresponding_ground_truth(self, robot_idx, time): + data_catagory = 'groundtruth' + gt_idx = find_nearest_time_idx(self.time_arr[data_catagory][robot_idx], time) + try: + self.dataset_data[data_catagory][robot_idx][gt_idx] + except IndexError: + print(robot_idx, 'Index ERR: ', gt_idx) + matched_gt_data = self.dataset_data[data_catagory][robot_idx][gt_idx] + return matched_gt_data + + def trackers_sync(self, current_time): + #print('sync current time: ', current_time ) + for catagory in ['odometry', 'measurement']: + for robot_idx in range(self.num_robots): + start_idx = self.data_trackers[catagory][robot_idx] + if start_idx != -1: + time_idx = find_next_time_idx(self.time_arr[catagory][robot_idx], start_idx, current_time) + self.data_trackers[catagory][robot_idx] = time_idx + + def trackers_update(self, req_type, robot_idx): + # update corrsponding trackers + if self.data_trackers[req_type][robot_idx]!=-1: + self.data_trackers[req_type][robot_idx]+=1 + #print(self.data_trackers) + #self.data_trackers['groundtruth'][robot_idx]+=1 + + def get_matched_dataline(self, req): + message = req.get_message() + + if message['robot_index'] == None: + if req.get_type() == None: + odo_time_arr = self.get_time_arr('odometry') + meas_time_arr = self.get_time_arr('measurement') + if min(odo_time_arr)>min(meas_time_arr): + robot_idx = np.argmin(meas_time_arr) + req_type = 'measurement' + req.set_type(req_type) + else: + robot_idx = np.argmin(odo_time_arr) + req_type = 'odometry' + req.set_type(req_type) + else: + req_type = req.get_type() + time_arr = self.get_time_arr(req_type) + robot_idx = np.argmin(time_arr) + + message['robot_index'] = robot_idx + + else: + robot_idx = message['robot_index'] + if req.get_type() == None: + odo_time_idx = self.data_trackers['odometry'][robot_idx] + meas_time_idx = self.data_trackers['measurement'][robot_idx] + if odo_time_idx != -1 and self.dataset_data['odometry'][robot_idx][odo_time_idx]['time'] >= self.dataset_data['measurement'][robot_idx][meas_time_idx]['time']: + req_type = 'measurement' + req.set_type(req_type) + elif meas_time_idx != -1 and self.dataset_data['odometry'][robot_idx][odo_time_idx]['time'] < self.dataset_data['measurement'][robot_idx][meas_time_idx]['time']: + req_type = 'odometry' + req.set_type(req_type) + else: + valid_dataline = False + else: + req_type = req.get_type() + + time_idx = self.data_trackers[req_type][robot_idx] + if self.dataset_data[req_type][robot_idx][time_idx]['time'] > self.end_time or time_idx == -1: + valid_dataline = False + else: + valid_dataline= True + message['data'] = self.dataset_data[req_type][robot_idx][time_idx] + message['groundtruth'] = self.dataset_matched_gt_data[req_type][robot_idx][time_idx] + return valid_dataline, message, req_type, robot_idx, time_idx + + + def create_synthetic_dataline(self, req, time_idx, meas_input_var): + message = req.get_message() + req_type = req.get_type() + robot_idx = message['robot_index'] + req_time = message['time'] + if req_time > self.time_arr[req_type][robot_idx][time_idx]: + try: + prev_time_idx = time_idx + post_time_idx = time_idx+1 + self.time_arr[req_type][robot_idx][post_time_idx] + except IndexError: + prev_time_idx = time_idx-1 + post_time_idx = time_idx + + else: + prev_time_idx = time_idx-1 + post_time_idx = time_idx + + t0= self.time_arr[req_type][robot_idx][prev_time_idx] + t1 = self.time_arr[req_type][robot_idx][post_time_idx] + if t1-t0 > 1: # time interval is too big for linear iterpolation + g_idx = find_nearest_time_idx(self.time_arr['groundtruth'][robot_idx],req_time) + gt_x = self.groundtruth_data[robot_idx][g_idx]['x_pos'] + gt_y = self.groundtruth_data[robot_idx][g_idx]['y_pos'] + gt_orientation = self.groundtruth_data[robot_idx][g_idx]['orientation'] + else: + #groudtruth = {'time':time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':orientation} + x0 = self.dataset_matched_gt_data[req_type][robot_idx][prev_time_idx]['x_pos'] + x1 = self.dataset_matched_gt_data[req_type][robot_idx][post_time_idx]['x_pos'] + gt_x = linear_interpolation([t0, x0], [t1, x1], req_time) + y0 = self.dataset_matched_gt_data[req_type][robot_idx][prev_time_idx]['y_pos'] + y1 = self.dataset_matched_gt_data[req_type][robot_idx][post_time_idx]['y_pos'] + gt_y = linear_interpolation([t0, y0], [t1, y1], req_time) + o0 = self.dataset_matched_gt_data[req_type][robot_idx][prev_time_idx]['orientation'] + o1 = self.dataset_matched_gt_data[req_type][robot_idx][post_time_idx]['orientation'] + gt_orientation = linear_interpolation([t0, o0], [t1, o1], req_time) + + message['groundtruth'] = {'time':req_time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':gt_orientation} + + if req_type == 'odometry': + v0 = self.dataset_data[req_type][robot_idx][prev_time_idx]['velocity'] + v1 = self.dataset_data[req_type][robot_idx][post_time_idx]['velocity'] + velocity = linear_interpolation([t0, v0], [t1, v1], req_time) + o0 = self.dataset_data[req_type][robot_idx][prev_time_idx]['orientation'] + o1 = self.dataset_data[req_type][robot_idx][post_time_idx]['orientation'] + orientation = linear_interpolation([t0, o0], [t1, o1], req_time) + message['data'] = {'time':req_time, 'velocity':velocity, 'orientation':orientation} + else: #measurement: meas_info = {'time':time, 'subject_ID':subject_ID, 'measurment_range': measurment_range, 'bearing':bearing} + pass + + subject_ID = self.dataset_data[req_type][robot_idx][time_idx]['subject_ID'] + #bearing = self.dataset_data[req_type][robot_idx][time_idx]['bearing'] + #print(self.dataset_data[req_type][robot_idx][time_idx]) + var_dis = meas_input_var[0] + var_phi = meas_input_var[1] + if subject_ID > 5: # landmark + [lx, ly] = self.landmark_map[subject_ID] + else: + if subject_ID not in self.dataset_labels: + obj_index = (robot_idx+2)%(len(self.dataset_labels)) + subject_ID = self.dataset_labels[obj_index] + + obj_index = self.dataset_labels.index(subject_ID) + matched_gt_data = self.find_corresponding_ground_truth(obj_index, req_time) + lx = matched_gt_data['x_pos'] + ly = matched_gt_data['y_pos'] + + measurment_range = sqrt((lx-gt_x)*(lx-gt_x)+(ly-gt_y)*(ly-gt_y)) + float(np.random.normal(0, sqrt(var_dis), 1)) + # bearing not matching with closest dataline.... + bearing = (atan2((ly-gt_y), (lx-gt_x))-gt_orientation)%pi + float(np.random.normal(0, sqrt(var_phi), 1)) + if abs(bearing-pi) < abs(bearing): + bearing = bearing-pi + + message['data'] = {'time':req_time, 'subject_ID':subject_ID, 'measurment_range': measurment_range, 'bearing':bearing} + + return message + + + def load_most_recent_dataline(self, req, time_idx): + message = req.get_message() + req_type = req.get_type() + robot_idx = message['robot_index'] + req_time = message['time'] + message['data'] = self.dataset_data[req_type][robot_idx][time_idx] + message['groundtruth'] = self.dataset_matched_gt_data[req_type][robot_idx][time_idx] + return message + + def create_additional_dataline(self, req, time_idx, meas_input_var): + message = self.create_synthetic_dataline(req, time_idx, meas_input_var) + return message + + + def get_dataline_at_specific_time(self, req, time_diff_limit = 0.1): + message = req.get_message() + req_type = req.get_type() + meas_input_var = [0.01, 0.01] + odo_input_var = [0.01, 0.01] + robot_idx = message['robot_index'] + req_time = message['time'] + if req_time < self.dataset_data[req_type][robot_idx][0]['time']: + g_idx = find_nearest_time_idx(self.time_arr['groundtruth'][robot_idx],req_time) + gt_x = self.groundtruth_data[robot_idx][g_idx]['x_pos'] + gt_y = self.groundtruth_data[robot_idx][g_idx]['y_pos'] + gt_orientation = self.groundtruth_data[robot_idx][g_idx]['orientation'] + message['groundtruth'] = {'time':req_time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':gt_orientation} + if req_type == 'odometry': + message['data'] = {'time':req_time, 'velocity':0 , 'orientation':gt_orientation + float(np.random.normal(0, sqrt(odo_input_var[1]), 1) )} + else: + subject_ID = 6 + [lx, ly] = self.landmark_map[subject_ID] + measurment_range = sqrt((lx-gt_x)*(lx-gt_x)+(ly-gt_y)*(ly-gt_y)) + float(np.random.normal(0, sqrt(meas_input_var[0]), 1)) + bearing = (atan2((ly-gt_y), (lx-gt_x))-gt_orientation)%pi + float(np.random.normal(0, sqrt(meas_input_var[1]), 1)) + if abs(bearing-pi) < abs(bearing): + bearing = bearing-pi + + message['data'] = {'time':req_time, 'subject_ID':subject_ID, 'measurment_range': measurment_range, 'bearing':bearing} + valid_dataline = True + time_idx = 0 + return valid_dataline, message, req_type, robot_idx, time_idx + + + + time_idx = find_nearest_time_idx(self.time_arr[req_type][robot_idx], req_time) + respond_time = self.time_arr[req_type][robot_idx][time_idx] + + message['data'] = self.dataset_data[req_type][robot_idx][time_idx] + message['groundtruth'] = self.dataset_matched_gt_data[req_type][robot_idx][time_idx] + + if abs(respond_time-req_time) > time_diff_limit and self.adding_actifical_dataline: + message = self.create_additional_dataline(req, time_idx, meas_input_var) + + if req_time > self.end_time: + valid_dataline = False + else: + valid_dataline= True + return valid_dataline, message, req_type, robot_idx, time_idx + + + def respond(self, req, current_time, need_specific_time = False): + message = req.get_message() + self.trackers_sync(current_time) + if need_specific_time: + valid_respond, message, req_type, robot_idx, time_idx = self.get_dataline_at_specific_time(req) + current_time = message['time'] + else: + valid_respond, message, req_type, robot_idx, time_idx = self.get_matched_dataline(req) + current_time = self.dataset_data[req_type][robot_idx][time_idx]['time'] + if valid_respond: + #load data + message['time'] = current_time + self.trackers_update(req_type, robot_idx) + req.set_message(message) + + return valid_respond, current_time, req + diff --git a/CoLo-AT/dataset_manager/existing_dataset.py~ b/CoLo-AT/dataset_manager/existing_dataset.py~ new file mode 100755 index 0000000..0e266a6 --- /dev/null +++ b/CoLo-AT/dataset_manager/existing_dataset.py~ @@ -0,0 +1,740 @@ +# -*- coding: utf-8 -*- + +import numpy as np +from numpy import random +import sys +<<<<<<< HEAD +from math import atan2, sqrt, pi +======= +import random +from math import cos +from math import sin +import math +>>>>>>> caa3398ca773a598bfbaedd0e32f33e92280c52c +''' +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/requests') +import request_response +''' + +def find_nearest_time_idx(l, value): + if len(l) != 0: + array = np.asarray(l) + idx = (np.abs(array-value)).argmin() + return idx + else: + return None + + + +def find_next_time_idx(array, start_idx, value): + i = start_idx + try: + array[i] + except IndexError: + i = -1 + return i + while array[i] < value: + i = i+1 + try: + array[i] + except IndexError: + i = -1 + break + return i + +<<<<<<< HEAD +def linear_interpolation(end0, end1, x): + [x0, y0] = end0 + [x1, y1] = end1 + if x1 == x0: + y = y0 + else: + y = y0+(x-x0)*(y1-y0)/(x1-x0) + return y + +class Dataset: + + def __init__(self, dataset_name): +======= +def get_pos_within_rad(rad): + rad = abs(rad) + while True: + x = random.uniform(-1*rad, rad) + y = random.uniform(-1*rad, rad) + if (((x**2) + (y**2))**.5 > rad): + continue + else: + return x, y + +def sanitize_angle(angle): + if -3.1415 > angle: + temp = abs(angle) - 3.1415 + angle = 3.1415 - temp + if angle > 3.1415: + temp = abs(angle) - 3.1415 + angle = -3.1415 + temp + return angle + +class Dataset: + + def __init__(self, dataset_name, dataset_path, dataset_labels): + random.seed(a=100) #start a seed for the random data generator +>>>>>>> caa3398ca773a598bfbaedd0e32f33e92280c52c + self.name = dataset_name + + def create_landmark_map(self): + ### Build landmark map ### + self.landmark_map = {} + path=self.dataset_path + "Landmark_Groundtruth.dat" + landmark_file=open(path,'r+'); + s = landmark_file.readline() + while(s): + if(s[0]!='#'): + landmark_location = [float(s.split( )[1]), float(s.split( )[2])] + self.landmark_map.update({int(s.split( )[0]): landmark_location}) + s = landmark_file.readline() + landmark_file.close() + #print "lm ", self.landmark_map, " lm" + return self.landmark_map + + + def load_MRCLAMDatasets(self, dataset_path, dataset_labels, duration, adding_actifical_dataline = True, delay_start = 10, synthetic = True): + print ('******** Initialization Started ********') + self.synthetic = synthetic + print ('add synthetic data: ', self.synthetic) + self.dataset_path = dataset_path + self.dataset_labels = dataset_labels + self.adding_actifical_dataline = adding_actifical_dataline + self.create_landmark_map() + + self.num_robots = len(self.dataset_labels) + self.measurement_data = [[] for i in range(self.num_robots)] + self.odometry_data = [[] for i in range(self.num_robots)] + self.gt_data_odo = [[] for i in range(self.num_robots)] + self.gt_data_meas = [[] for i in range(self.num_robots)] + self.groundtruth_data = [[] for i in range(self.num_robots)] + + #self.groundtruth_time= [[] for i in range(self.num_robots)] + self.time_arr = {'odometry': [[] for i in range(self.num_robots)], 'measurement': [[] for i in range(self.num_robots)], 'groundtruth': [[] for i in range(self.num_robots)]} + + #initialization for MRCLAMDatasets: put files into dictionaries: + self.duration = duration # some more time to avoid index error + self.start_time_arr = [] + #finding the starting time: + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + groundtruth_path = self.dataset_path+"Robot"+robot_num+"_Groundtruth.dat" + with open(groundtruth_path,'r+') as groundtruth_file: + for line in groundtruth_file: + if str(line.split()[0]) != '#': + time = float(line.split()[0]) + self.start_time_arr.append(time) + break + self.start_time = max(self.start_time_arr) + delay_start + self.end_time = self.start_time + self.duration + print('Staring time: ', self.start_time) + #finding starting states: + self.starting_states = {} + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + groundtruth_path = self.dataset_path+"Robot"+robot_num+"_Groundtruth.dat" + with open(groundtruth_path,'r+') as groundtruth_file: + for line in groundtruth_file: + if line[0] != '#' and float(line.split()[0]) >= self.start_time: + time = float(line.split()[0]) + x_pos = float(line.split()[1]) + y_pos = float(line.split()[2]) + orientation = float(line.split()[3]) + self.starting_states[label] = [time, x_pos, y_pos, orientation] + break + print('Staring states: ') + print(self.starting_states) + + + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + + groundtruth_path = self.dataset_path+"Robot"+robot_num+"_Groundtruth.dat" + with open(groundtruth_path,'r+') as groundtruth_file: + for line in groundtruth_file: + if line[0] != '#' and (self.end_time+2 >= float(line.split()[0]) >= self.start_time): + time = float(line.split()[0]) + x_pos = float(line.split()[1]) + y_pos = float(line.split()[2]) + orientation = float(line.split()[3]) + groundtruth_info = {'time':time, 'x_pos':x_pos, 'y_pos':y_pos, 'orientation':orientation} + self.groundtruth_data[i].append(groundtruth_info) + self.time_arr['groundtruth'][i].append(time) + + + meas_path = self.dataset_path+"Robot"+robot_num+"_Measurement_x.dat" + with open(meas_path,'r+') as measure_file: + for line in measure_file: + if line[0] != '#' and (self.end_time+2 >= float(line.split()[0]) >= self.start_time): + time = float(line.split()[0]) + subject_ID = int(line.split()[1]) + measurment_range = float(line.split()[2]) + bearing = float(line.split()[3]) + meas_info = {'time':time, 'subject_ID':subject_ID, 'measurment_range': measurment_range, 'bearing':bearing} + + g_idx = find_nearest_time_idx(self.time_arr['groundtruth'][i],time) + gt_x = self.groundtruth_data[i][g_idx]['x_pos'] + gt_y = self.groundtruth_data[i][g_idx]['y_pos'] + orientation = self.groundtruth_data[i][g_idx]['orientation'] + matched_gt_info = {'time':time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':orientation} + + self.measurement_data[i].append(meas_info) + self.gt_data_meas[i].append(matched_gt_info) + self.time_arr['measurement'][i].append(time) + + + odo_path = self.dataset_path+"Robot"+robot_num+"_Odometry.dat" + with open(odo_path,'r+') as odometry_file: + for line in odometry_file: + if line[0] != '#' and (self.end_time+2 >= float(line.split()[0]) >= self.start_time): + time = float(line.split()[0]) + g_idx = find_nearest_time_idx(self.time_arr['groundtruth'][i],time) + velocity = float(line.split()[1]) + orientation = self.groundtruth_data[i][g_idx]['orientation'] + #print "orientation ", orientation + odo_info = {'time':time, 'velocity':velocity, 'orientation':orientation} + + gt_x = self.groundtruth_data[i][g_idx]['x_pos'] + gt_y = self.groundtruth_data[i][g_idx]['y_pos'] + matched_gt_info = {'time':time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':orientation} + + self.odometry_data[i].append(odo_info) + self.gt_data_odo[i].append(matched_gt_info) + self.time_arr['odometry'][i].append(time) + + self.data_trackers = {'odometry': np.ones((self.num_robots,), dtype=np.int), 'measurement':np.ones((self.num_robots,), dtype=np.int)} + # tracker for each robot for both each type of data to keep track of their location in the dataset + self.odo_data_trackers = np.ones((self.num_robots,), dtype=np.int) + self.dataset_data = {'odometry': self.odometry_data, 'measurement': self.measurement_data, 'groundtruth': self.groundtruth_data} + self.dataset_matched_gt_data = {'odometry': self.gt_data_odo, 'measurement': self.gt_data_meas} + print ('******** Initialization Completed ********') + + return self.start_time, self.starting_states, self.dataset_data, self.time_arr + + def dataset_reset(self): + self.data_trackers = {'odometry': np.ones((self.num_robots,), dtype=np.int),'measurement':np.ones((self.num_robots,), dtype=np.int), 'groundtruth':np.ones((self.num_robots,), dtype=np.int)} + + def get_start_time(self): + return self.start_time + + def get_starting_states(self): + return self.starting_states + + def get_duration(self): + return self.duration + + def get_landmark_map(self): + return self.landmark_map + + def get_start_moving_times(self): + start_moving_times = [] + time_idx = 0 + for i, label in enumerate(self.dataset_labels): + start_moving_times.append(self.dataset_data['odometry'][i][time_idx]['time']) + return start_moving_times + + def get_time_arr(self, data_catagory): + # retunr an array of time shows time for next dataline for each robot given data catagory + time_arr =[] + for i, label in enumerate(self.dataset_labels): + time_idx = self.data_trackers[data_catagory][i] + if time_idx == -1: + time_arr.append(self.start_time + self.duration + 10) # so that it will be out of range and not be selected + else: + time_arr.append(self.dataset_data[data_catagory][i][time_idx]['time']) + return time_arr + + def find_corresponding_ground_truth(self, robot_idx, time): + data_catagory = 'groundtruth' + gt_idx = find_nearest_time_idx(self.time_arr[data_catagory][robot_idx], time) + try: + self.dataset_data[data_catagory][robot_idx][gt_idx] + except IndexError: + print(robot_idx, 'Index ERR: ', gt_idx) + matched_gt_data = self.dataset_data[data_catagory][robot_idx][gt_idx] + return matched_gt_data + + def trackers_sync(self, current_time): +<<<<<<< HEAD + #print('sync current time: ', current_time ) + for catagory in ['odometry', 'measurement']: +======= + for catagory in ['odometry', 'measurement', 'groundtruth']: +>>>>>>> caa3398ca773a598bfbaedd0e32f33e92280c52c + for robot_idx in range(self.num_robots): + start_idx = self.data_trackers[catagory][robot_idx] + if start_idx != -1: + time_idx = find_next_time_idx(self.time_arr[catagory][robot_idx], start_idx, current_time) + self.data_trackers[catagory][robot_idx] = time_idx + + def trackers_update(self,req_type,robot_idx): + # update corrsponding trackers + self.data_trackers[req_type][robot_idx]+=1 + #self.data_trackers['groundtruth'][robot_idx]+=1 + + def get_matched_dataline(self, req): + message = req.get_message() + + if message['robot_index'] == None: + if req.get_type() == None: + odo_time_arr = self.get_time_arr('odometry') + meas_time_arr = self.get_time_arr('measurement') + if min(odo_time_arr)>min(meas_time_arr): + robot_idx = np.argmin(meas_time_arr) + req_type = 'measurement' + req.set_type(req_type) + else: + robot_idx = np.argmin(odo_time_arr) + req_type = 'odometry' + req.set_type(req_type) + else: + req_type = req.get_type() + time_arr = self.get_time_arr(req_type) + robot_idx = np.argmin(time_arr) + + message['robot_index'] = robot_idx + + else: + robot_idx = message['robot_index'] + if req.get_type() == None: + time_idx = self.data_trackers['odometry'][robot_idx] + if self.dataset_data['odometry'][robot_idx][time_idx]['time']>self.dataset_data['measurement'][robot_idx][time_idx]['time']: + req_type = 'measurement' + req.set_type(req_type) + else: + req_type = 'odometry' + req.set_type(req_type) + else: + req_type = req.get_type() + + time_idx = self.data_trackers[req_type][robot_idx] + if self.dataset_data[req_type][robot_idx][time_idx]['time'] > self.end_time: + valid_dataline = False + else: + valid_dataline= True + message['data'] = self.dataset_data[req_type][robot_idx][time_idx] + message['groundtruth'] = self.dataset_matched_gt_data[req_type][robot_idx][time_idx] + return valid_dataline, message, req_type, robot_idx, time_idx + + + def create_synthetic_dataline(self, req, time_idx, meas_input_var): + message = req.get_message() + req_type = req.get_type() + robot_idx = message['robot_index'] + req_time = message['time'] + if req_time > self.time_arr[req_type][robot_idx][time_idx]: + try: + prev_time_idx = time_idx + post_time_idx = time_idx+1 + self.time_arr[req_type][robot_idx][post_time_idx] + except IndexError: + prev_time_idx = time_idx-1 + post_time_idx = time_idx + + else: + prev_time_idx = time_idx-1 + post_time_idx = time_idx + + t0= self.time_arr[req_type][robot_idx][prev_time_idx] + t1 = self.time_arr[req_type][robot_idx][post_time_idx] + if t1-t0 > 1: # time interval is too big for linear iterpolation + g_idx = find_nearest_time_idx(self.time_arr['groundtruth'][robot_idx],req_time) + gt_x = self.groundtruth_data[robot_idx][g_idx]['x_pos'] + gt_y = self.groundtruth_data[robot_idx][g_idx]['y_pos'] + gt_orientation = self.groundtruth_data[robot_idx][g_idx]['orientation'] + else: + #groudtruth = {'time':time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':orientation} + x0 = self.dataset_matched_gt_data[req_type][robot_idx][prev_time_idx]['x_pos'] + x1 = self.dataset_matched_gt_data[req_type][robot_idx][post_time_idx]['x_pos'] + gt_x = linear_interpolation([t0, x0], [t1, x1], req_time) + y0 = self.dataset_matched_gt_data[req_type][robot_idx][prev_time_idx]['y_pos'] + y1 = self.dataset_matched_gt_data[req_type][robot_idx][post_time_idx]['y_pos'] + gt_y = linear_interpolation([t0, y0], [t1, y1], req_time) + o0 = self.dataset_matched_gt_data[req_type][robot_idx][prev_time_idx]['orientation'] + o1 = self.dataset_matched_gt_data[req_type][robot_idx][post_time_idx]['orientation'] + gt_orientation = linear_interpolation([t0, o0], [t1, o1], req_time) + + message['groundtruth'] = {'time':req_time, 'x_pos':gt_x, 'y_pos':gt_y, 'orientation':gt_orientation} + + if req_type == 'odometry': + v0 = self.dataset_data[req_type][robot_idx][prev_time_idx]['velocity'] + v1 = self.dataset_data[req_type][robot_idx][post_time_idx]['velocity'] + velocity = linear_interpolation([t0, v0], [t1, v1], req_time) + o0 = self.dataset_data[req_type][robot_idx][prev_time_idx]['orientation'] + o1 = self.dataset_data[req_type][robot_idx][post_time_idx]['orientation'] + orientation = linear_interpolation([t0, o0], [t1, o1], req_time) + message['data'] = {'time':req_time, 'velocity':velocity, 'orientation':orientation} + else: #measurement: meas_info = {'time':time, 'subject_ID':subject_ID, 'measurment_range': measurment_range, 'bearing':bearing} + pass + + subject_ID = self.dataset_data[req_type][robot_idx][time_idx]['subject_ID'] + #bearing = self.dataset_data[req_type][robot_idx][time_idx]['bearing'] + #print(self.dataset_data[req_type][robot_idx][time_idx]) + var_dis = meas_input_var[0] + var_phi = meas_input_var[1] + if subject_ID > 5: # landmark + [lx, ly] = self.landmark_map[subject_ID] + else: + if subject_ID not in self.dataset_labels: + obj_index = (robot_idx+2)%(len(self.dataset_labels)) + subject_ID = self.dataset_labels[obj_index] + + obj_index = self.dataset_labels.index(subject_ID) + matched_gt_data = self.find_correspoind_ground_truth(obj_index, req_time) + lx = matched_gt_data['x_pos'] + ly = matched_gt_data['y_pos'] + + measurment_range = sqrt((lx-gt_x)*(lx-gt_x)+(ly-gt_y)*(ly-gt_y)) + random.normal(0, sqrt(var_dis)) + # bearing not matching with closest dataline.... + bearing = (atan2((ly-gt_y), (lx-gt_x))-gt_orientation)%pi + random.normal(0, sqrt(var_dis)) + if abs(bearing-pi) < abs(bearing): + bearing = bearing-pi + + message['data'] = {'time':req_time, 'subject_ID':subject_ID, 'measurment_range': measurment_range, 'bearing':bearing} + + return message + + + def load_most_recent_dataline(self, req, time_idx): + message = req.get_message() + req_type = req.get_type() + robot_idx = message['robot_index'] + req_time = message['time'] + message['data'] = self.dataset_data[req_type][robot_idx][time_idx] + message['groundtruth'] = self.dataset_matched_gt_data[req_type][robot_idx][time_idx] + return message + + def create_additional_dataline(self, req, time_idx, meas_input_var): + if self.synthetic: + message = self.create_synthetic_dataline(req, time_idx, meas_input_var) + else: + message = self.load_most_recent_dataline(req, time_idx) + return message + + + def get_dataline_at_specific_time(self, req, time_diff_limit = 0.1): + message = req.get_message() + req_type = req.get_type() + robot_idx = message['robot_index'] + req_time = message['time'] + time_idx = find_nearest_time_idx(self.time_arr[req_type][robot_idx], req_time) + respond_time = self.time_arr[req_type][robot_idx][time_idx] + + message['data'] = self.dataset_data[req_type][robot_idx][time_idx] + message['groundtruth'] = self.dataset_matched_gt_data[req_type][robot_idx][time_idx] + + if abs(respond_time-req_time) > time_diff_limit and self.adding_actifical_dataline: + meas_input_var = [0.1, 0.1] + message = self.create_additional_dataline(req, time_idx, meas_input_var) + + if req_time > self.end_time: + valid_dataline = False + else: + valid_dataline= True + return valid_dataline, message, req_type, robot_idx, time_idx + + + def respond(self, req, current_time, need_specific_time = False): + message = req.get_message() + self.trackers_sync(current_time) +<<<<<<< HEAD + if need_specific_time: + valid_respond, message, req_type, robot_idx, time_idx = self.get_dataline_at_specific_time(req) + current_time = message['time'] + else: + valid_respond, message, req_type, robot_idx, time_idx = self.get_matched_dataline(req) + current_time = self.dataset_data[req_type][robot_idx][time_idx]['time'] + + if valid_respond: + #load data + message['time'] = current_time + self.trackers_update(req_type, robot_idx) +======= + valid_respond, req_type, robot_idx, time_idx = self.get_matched_dataline(req) + if valid_respond: + #load data + current_time = self.dataset_data[req_type][robot_idx][time_idx]['time'] + message['time'] = self.dataset_data[req_type][robot_idx][time_idx]['time'] + message['data'] = self.dataset_data[req_type][robot_idx][time_idx] + #load corresponding groundtruth + time = self.dataset_data[req_type][robot_idx][time_idx]['time'] + matched_gt_data = self.find_corresponding_ground_truth(robot_idx, time) + message['groundtruth'] = matched_gt_data + self.trackers_update(req_type,robot_idx) +>>>>>>> caa3398ca773a598bfbaedd0e32f33e92280c52c + req.set_message(message) + + return valid_respond, current_time, req + + + def generate_random_landmark_map(self): + """num_landmarks = random.randint(8, 20) + + self.landmark_map = {} + for i in range(num_landmarks): + x_coord, y_coord = get_pos_within_rad(5) + self.landmark_map[i+1] = [x_coord, y_coord] + """ + self.landmark_map = {1: [-5.0, 0.0]} + print "map", self.landmark_map + return self.landmark_map + + # take an x and y from the robot and the first two params, + # and a list of coords for the landmark as the second param + # return the distance between them + def landmark_distance(self, old_x, old_y, new_coords): + new_x, new_y = new_coords[0], new_coords[1] + return math.sqrt((old_x - new_x)**2 + (old_y - new_y)**2) + + def getBearing(self, x, y): + return math.atan2(y, x) + + def getLineAngle(self, my_x, my_y, lm_x, lm_y, orientation): + theta = self.getBearing(my_x - lm_x, my_y - lm_y) + #need to account that you don't yet know which direction the angle is, + #eg robot to lm or lmm to robot + if (theta > 0) and (my_y > lm_y): + theta = -3.1415 + theta + elif (theta < 0) and (my_y < lm_y): + print "correcting" + theta = 3.1415 + theta + + angle_from_robot = sanitize_angle(theta - orientation) + + return angle_from_robot + + def get_closest_landmark(self, x, y): + closest_distance = 10 + closest_lm = 0 + for key, coords in self.landmark_map.items(): + distance = self.landmark_distance(x, y, coords) + if (distance < closest_distance): + closest_distance = distance + closest_lm = key + + #print closest_lm, closest_distance, x, y, coords[0], coords[1] + return closest_lm, closest_distance + + def get_second_closest_landmark(self, x, y): + closest_lm, closest_distance = self.get_closest_landmark(x, y) + second_closest_distance = 10 + second_closest_lm = 0 + for key, coords in self.landmark_map.items(): + distance = self.landmark_distance(x, y, coords) + if (distance < second_closest_distance and not(key == closest_lm)): + second_closest_distance = distance + second_closest_lm = key + + return second_closest_lm, second_closest_distance + + def initialization_Random_Dataset(self, duration): + print ('******** Random Initialization Started ********') + self.generate_random_landmark_map()# + + self.num_robots = len(self.dataset_labels) + self.measurement_data = [[] for i in range(self.num_robots)] + self.odometry_data = [[] for i in range(self.num_robots)] + self.groundtruth_data = [[] for i in range(self.num_robots)] + self.time_arr = {'odometry': [[] for i in range(self.num_robots)], 'measurement': [[] for i in range(self.num_robots)], 'groundtruth': [[] for i in range(self.num_robots)]} + + self.duration = duration # some more time to avoid index error + self.start_time_arr = [] + + + #finding the starting time: + self.start_time = (1e9) + self.end_time = self.start_time + self.duration + print('Staring time: ', self.start_time) + + #finding starting states: + self.starting_states = {} + robot_movement_dict = {} + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + + #generate the position starts here + x_pos, y_pos = get_pos_within_rad(5) + orientation = 0#random.uniform(-3.1415, 3.1415) + + self.starting_states[label] = [self.start_time, x_pos, y_pos, orientation] + print('Starting states: ') + print(self.starting_states) + + # + for i, label in enumerate(self.dataset_labels): + robot_num = str(label) + + #give the robot a random starting position + velocity = random.uniform(0.0, 1.0) + inits = self.starting_states[label] + x_pos = inits[1] + y_pos = inits[2] + orientation = inits[3] + this_robot = Robot_Movement_Generator(x_pos, y_pos, orientation, robot_num) + robot_movement_dict[robot_num] = this_robot + + + measurement_file = open("random" + robot_num + "_measurement_x.dat", 'w') + + time = self.start_time + ticks = 0 + while (time < self.end_time):# this is a fixed number of iterations right now + #time moves at a constant step right now + time_delta = 0.0195 + time = time + time_delta + ticks = ticks + 1 + + velocity, orientation, x_pos, y_pos = this_robot.run_tick(time, time_delta) + + #these are biased values that are approximated by the robot from the groundtruth + odo_info = {'time':time, 'velocity':velocity, 'orientation':orientation} + self.odometry_data[i].append(odo_info) + self.time_arr['odometry'][i].append(time)# I think there may be a mistake here. This value isn't meant to be orientation, it should be angular velocity + + groundtruth_info = {'time':time, 'x_pos':x_pos, 'y_pos':y_pos, 'orientation':orientation} # groundtruth + self.groundtruth_data[i].append(groundtruth_info) + self.time_arr['groundtruth'][i].append(time) + + #choose a random landmark and calculate the distance from it + if ticks % 23 == 0: + closest_landmark, closest_distance = self.get_closest_landmark(x_pos, y_pos) + if closest_distance < 5: + measurement_range = closest_distance #+ random.gauss(0.0, .001) #TODO: find a legitimate way to choose this sigma + bearing = self.getLineAngle(x_pos, y_pos, self.landmark_map[closest_landmark][0], self.landmark_map[closest_landmark][1], orientation) + meas_info = {'time':time, 'subject_ID':closest_landmark, 'measurment_range': measurement_range, 'bearing':bearing} + print meas_info + print x_pos, y_pos, self.landmark_map[closest_landmark][0], self.landmark_map[closest_landmark][1], bearing + measurement_file.write(str(time) + "\t" + str(closest_landmark) + "\t" + str(measurement_range) + "\t" + str(bearing) + "\n") + self.measurement_data[i].append(meas_info) + self.time_arr['measurement'][i].append(time) + second_closest_landmark, second_closest_distance = self.get_second_closest_landmark(x_pos, y_pos) + if second_closest_distance < 3: + measurement_range = second_closest_distance #+ random.gauss(0.0, .001) #TODO: find a legitimate way to choose this sigma + bearing = self.getLineAngle(x_pos, y_pos, self.landmark_map[second_closest_landmark][0], self.landmark_map[second_closest_landmark][1], orientation) + print meas_info + meas_info = {'time':time, 'subject_ID':second_closest_landmark, 'measurment_range': measurement_range, 'bearing':bearing} + measurement_file.write(str(time) + "\t" + str(second_closest_landmark) + "\t" + str(measurement_range) + "\t" + str(bearing) + "\n") + self.measurement_data[i].append(meas_info) + self.time_arr['measurement'][i].append(time) + + + measurement_file.close() + this_robot.close_file() + self.data_trackers = {'odometry': np.ones((self.num_robots,), dtype=np.int),'measurement':np.ones((self.num_robots,), dtype=np.int), 'groundtruth':np.ones((self.num_robots,), dtype=np.int)} + # tracker for each robot for both each type of data to keep track of their location in the dataset + self.odo_data_trackers = np.ones((self.num_robots,), dtype=np.int) + self.dataset_data = {'odometry': self.odometry_data, 'measurement': self.measurement_data, 'groundtruth': self.groundtruth_data} + print ('******** Initialization Completed ********') + + return self.start_time, self.starting_states, self.dataset_data, self.time_arr + + + +class Robot_Movement_Generator: + def __init__(self, x, y, orientation, num): + self.robot_num = num + self.velocity = .04#random.uniform(0.0, .1) + self.max_velocity = 0#.1 + self.orientation = orientation + self.angular_velocity = 0#.15 + self.max_angular_velocity = 0#.15 + self.x = x + self.y = y + self.sensor_noise = 0#.25 + self.odometry_file = open("random" + self.robot_num + "_odometry.dat", 'w') + self.groundtruth_file = open("random"+ self.robot_num + "_groundtruth.dat", 'w') + + def close_file(self): + self.odometry_file.close() + self.groundtruth_file.close() + + def update_xy(self, time_delta): + #check if the update is in bounds and if so do it + temp_x = self.x + cos(self.orientation) * self.velocity * (time_delta) + temp_y = self.y + sin(self.orientation) * self.velocity * (time_delta) + if ((temp_x**2 + self.y**2)**.5 < 5) and ((self.y**2 + temp_y**2)**.5 < 5): + self.x = temp_x + self.y = temp_y + else: + self.velocity = 0 + return self.x, self.y + + + def update_angular_velocity(self): + self.angular_velocity = self.max_angular_velocity + return self.angular_velocity + + def update_velocity(self): + self.velocity = self.max_velocity + return self.velocity + + def update_orientation(self, time_delta): + self.orientation += self.update_angular_velocity() * time_delta + self.orientation = sanitize_angle(self.orientation) + return self.orientation + + + def run_tick(self, time, time_delta): + #add biasing here, after we've already computed an accurate groundtruth + v = self.update_velocity()+ random.gauss(0.0, self.sensor_noise) + o = self.update_orientation(time_delta)+ random.gauss(0.0, self.sensor_noise) + x, y = self.update_xy(time_delta) + + + self.odometry_file.write(str(time) + "\t" + str(v) + "\t\t" + str(self.angular_velocity) + "\n") + + self.groundtruth_file.write(str(time) + "\t" + str(self.x) + "\t" + str(self.y) + "\t" + str(self.orientation) + "\n") + return (v, o, x, y) + + + + + +# test script +""" +rgf = open('random1_groundtruth.dat', 'r') +rof = open('random1_odometry.dat', 'r') +end_time=1000000100 +start_time = 1000000000 + +times = [] +x_poss = [] +y_poss = [] +orientations = [] + +times2 = [] +velocities = [] +orientations2 = [] +for line in rgf: + if line[0] != '#' and (end_time+2 >= float(line.split()[0]) >= start_time): + times.append(float(line.split()[0])) + x_poss.append(float(line.split()[1])) + y_poss.append(float(line.split()[2])) + orientations.append(float(line.split()[3])) + +for line in rof: + if line[0] != '#' and (end_time+2 >= float(line.split()[0]) >= start_time): + times2.append(float(line.split()[0])) + velocities.append(float(line.split()[1])) + orientations2.append(float(line.split()[2])) + +for i in range(len(rof)): + + +<<<<<<< HEAD + + + + + + + + +======= +print orientations, orientations2""" +>>>>>>> caa3398ca773a598bfbaedd0e32f33e92280c52c diff --git a/CoLo-AT/dataset_manager/testing_dataset.py b/CoLo-AT/dataset_manager/testing_dataset.py new file mode 100644 index 0000000..3ac374d --- /dev/null +++ b/CoLo-AT/dataset_manager/testing_dataset.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Created on Wed Feb 14 16:13:43 2018 + +@author: william +""" +from existing_dataset import Dataset + +import sys +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/requests') +import request_response + +"""Testing branch for dataset related classes and functions""" + +# testing for DataSet class + +dataset_path = '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/datasets/MRCLAM_Dataset1/' +dataset_labels = [1,2,3,4,5] +testing_dataset = Dataset('testing', dataset_path, dataset_labels) +lm_map = testing_dataset.create_landmark_map() +print(lm_map) +st,_,d,t_arr = testing_dataset.initialization_MRCLAMDatasets(20) + +''' +for i, label in enumerate(dataset_labels): + print(d['odometry'][i][-1]['time']) + print(d['measurement'][i][-1]['time']) + print(d['groundtruth'][i][-1]['time']) +''' +''' +prop_req= request_response.Prop_req_resp(None, None) +print(prop_req.get_message()) +print(prop_req.get_type()) +''' + + +g_req= request_response.Request_response(None, None) +print(g_req.get_message()) +print(g_req.get_type()) +''' +c_t = st +prev_time = 0 +while True: + print('***************** ****************') + g_req= request_response.Request_response(None, None) + prev_time = c_t + valid, c_t, rsp = testing_dataset.respond(g_req, c_t) + print('current time: ', c_t) + + g_req= request_response.Meas_req_resp(None, None) + prev_time = c_t + valid, c_t, rsp = testing_dataset.respond(g_req, c_t) + print('current time-M: ', c_t) + + if c_t < prev_time: + print('Time inconsistant!') + break + + if valid == False : + print('Done!') + break + +''' \ No newline at end of file diff --git a/CoLo-AT/localization_algos/.DS_Store b/CoLo-AT/localization_algos/.DS_Store new file mode 100755 index 0000000000000000000000000000000000000000..16a5a9ef2686ad5e79514819d39d7bf82f5ec619 GIT binary patch literal 10244 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__init__.py b/CoLo-AT/localization_algos/__init__.py new file mode 100755 index 0000000..b6e690f --- /dev/null +++ b/CoLo-AT/localization_algos/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/CoLo-AT/localization_algos/__pycache__/centralized_ekf.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/centralized_ekf.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81a915cb00b1fdfc5005ee5199ace0d68e5e028d GIT binary patch literal 3999 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/centralized_ekf.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/centralized_ekf.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d947265cbc05ed085fa91c83a8c81e78989f7e8b GIT binary patch literal 3669 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 HCd~OCfW|tY literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/centralized_ekf2.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/centralized_ekf2.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d91470af95ab53073a2de77c321310fd870a95b GIT binary patch literal 4951 zcmdT|TW=&s6+YEH_lvJ%kH@pwO?J()Bgk%cl0ZOCvam`*0$9Kzfrdz}_H=vP_Dr`^ z-Ck@n&5Oe$kNgNE#J}OC-Xfm%FYv^7sxLFPC+tQ@NQ~X5>vF2<T)(R7&1SRqNA=O~ z-ft28ljeQ}l%L=U{{rIRU(lFnAhNPS14EY$8XGh*X<*W%K!XBJiZm$Fq(p-fP0BPV zli=|tkDpX%P)X{TuS!QX8r1YO1sd0B(x5>D-9>Ur^d**S(kD)toC;S!-3DD^r6rc; zS+Dv6qS0QjsLWvyDl_zaRkS19@2f)ig^ZMO;`M|wogl(%%{@M_?C~hD4x~MCe;>%> zq2LMd<989yQ#|2&AQ91#pva&p(IpCITBwhVStajABmTkntS9z*1!edrsx+}9>77Xf zvq=*KA{3)TH?sdqvVr=)?vI0^J@zi_$P0WeS@>w^`jO;D*RddP|KZ8GD$5|UCec|H zgF>E;gj@n0axwdH`x89jZ$aG5QS2gk%+R(p*#}NRmkTtrF^rv=7#?$~<kU0|8tddV zbh$!K6WT4Qm8WwOe)Q9i`$H`e7UehVscnd8N^J-OP6b^W+UeRphOD4hRV>T%y~wh9 z2HfS24+d539Usoo21-a1ymAF(8BePIMd!K{53|Xxh?Bc?2V-G~)T{6<>;m5kYQbr+ z3jBL1MC)0vus8Zc>+hd@b@AngFIXW}bfWVUw^xvCeOcqCis!%vUUaUC2jjqwdWKx( z_L_e>v1G6xMBz30)p{7&k!wA-rDyv?S1Z1TF_}I)H}qLBAXkmeSHhz${c{wc$ma!$ z4T?>QQGiDUO^eiuOPLo6G%fKzI@*7N>hqNYgF3K7T&8ImPB!)=%LcVrX9TUZhi<Qu zDybE;9Hf~Np=t!u^AXb=!l5dM-e_W5p(=X5<DMzusbxLd%GJ4UncGN#;pv#IbB$A5 zY6B94tS^Z*Q4?>9i$^z1^`B=La!m4%b;_;wXJmY8wajF&)zqNRVZ<`U6`EEkuCnza zn3BVTP1j{J)!0l3pH5uYB@?BFE(z*PwV`*DS0`?2Pn6(^C7xvp<T8lu&Dhc8S*HzZ zP3zQZ&v);p6_eT-KL#)4&slb-Rf?Bsy39G=(bMwOs1|7#!GN`S`PBdO6_zJnAxIHH zdc8_3UM0*26i#MZWsKkz0K$1o6)hMB&SfmLN=HSyBxu5O;r}H|Y8|m&kwzw>u9ifd zWGH^Y1o8I<UYcAhb9dH0UtY{#Ql{re${f4?42?B{s=~;Pe%)Ksp)EU@Rn<e+4+E(K zTyFC^T_(4fyv7VG6W0z;r8@xzBx$gk4jBeneyeJd2!RvGO&(Ns+;L=EkrK~Ujj_(s zJAu5-o#K~D{6dM}Tu+U)6B(S?qhxzHJweL3EKB$RgwvrRN@CNfAuX0f4e#%YcMP<M z9kGJmHDk-zF)r@iNSB+l<|)GV%Q5pGz`y?@MRXoyDZ&AkqzETVGfNgE1p^hQ2LiW9 z95@Iu4&NpsiXT)td=c8Kyd59uG(a3D`|VMIBQ9R!EYcadu1mZ~OXnM+KgqXvBdg~L z(}_1JLXcw225qIU))WIbQB7X0HfMaBB7j5Mk+5S!L%wW9W!j9lC<0!9mT3#@Nd<*t z#LS*ZJD4kxzs<Z?<nN?i%m9To)J$vCLSkYXmSCI3tV7QBOk(h@r$TX&CGEytma`5G zUdDJUXRN2HU!SiVzm^&2>sfBo6iaTinSlZjcz24KvpTlcwr;~rXoK@o9t_LsIS+JP zfycKg@hT%qJHDf#WY%_vkBp2m@$1^5pzwZ&wg5Yr9sz`wZA^oywh|!1cF1r#gPPJD z)MPNS7&_|mE>c3?W0D^LB%dZE=ZP#Z;Y~%E_CB_~3s>SG%Bb>b?~NI%$Zs*<0yL5L zx#QbBK_!KZeT^9MJKWY7+rBfg<*|jMqN*|SSkm@Kt}5@lI7|2=jUe((W){Cv;zAkY zGd$-?VE4t*@xnT^BkQfK@E9U;ixNK>n1_!aGwFl$xzz8g<wOY2f6gbIz*qHSdpxmy zYh-)=b$r@@%E9;)J9n@jy3$G@>W7de{0t<AC=E`4DL@p%Q%Q6ISv7!E%XlE}h+F9C zns-GHe>>tHxAS9eiEV~4Q8F&>-vF_NOXoPou$tr8-^~9r9K)$J2FU1S$<QlDvpMui z5N$n2xJ^9<^*J6O7os0MEkIiGYE1z^40y>aK{$XD5H9UV_~sD~00o2togrL@afuP` zP^2Ak24jFXG+jZs?Uy2)1};Wk7C414jYu1Svo_8_8N>l^=D-F<Xn%t-IoKrQ>R-E3 zmzSC0RVvV{@aId+;qWWyvz~xws_iQpA#t`w*hHb1>XR;$3iJx>xjJwV!*llvJOk?i zxwE!gIXnaLVLnj6^Y$D(qow;lhiCZ~5J5g>(g*3?{zlj=-{ygQkV{~>p5UFn<H&cp z`Fl(lbu<*q?{kSiBPek+FwZP+V4gEMvrs*^j^z8y@Bxz#nLJ_gBPKs)!e0jx!k1sQ zAzj>$yysVO79Ue6{22(D=}~YI&KfD2&XCr)E8Y?BiAOjrzAJtp9*Vb(9BIu3NV{<H zy<U~??|fCaELF3tN#LB0x!ka<FHY@o(xdO~vJDyK>r5UodCKHtCNn*CN#FGOmd}Nd zn;J&L#9yg#r_q<((_2<W+_F#3ldEX~-&hXk&h&aa)*CbL$+8SGXoN%W<ow~-^YL{- wm6G?Md*j>7?5mLeJfZIgdd)>*s>*Jn@dpBHg#0z8f%EtSY+TF6iqR<i8<AD68UO$Q literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/centralized_ekf2.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/centralized_ekf2.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fecab09170779466d62b94741224829306bf89ef GIT binary patch literal 4565 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 HdD;3OpN7dx literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_gs_bound.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_gs_bound.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70305042b116cf32fd00875c639e615cae841b7b GIT binary patch literal 4460 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_gs_bound.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_gs_bound.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2368b8f11cbbd40638748256f016fb4fe3099cf GIT binary patch literal 4085 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_gs_ci.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_gs_ci.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..69150a44fca989b0b0e3843b3ddad2a91f1f44f4 GIT binary patch literal 2862 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_gs_ci2.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_gs_ci2.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bb4b98c836ce1ebbd895f1c63f76b070036ea18 GIT binary patch literal 4625 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_gs_ci2.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_gs_ci2.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..557e2e83be46e54cd8480385a25d1c0802ece75f GIT binary patch literal 4224 zcmbVPTW{RP73K`dUG7a<Nh|Ftc3dY&T5M}ut<!6&#%>(vf))Y_2MDlrLC`zYnyV!# z4=F_!hDCu*9#izS`2hv`6Z%K`Ft2&?KPdXrerLEhDT;g91<xGLoEgrX`Mxt}-fFe# zzt<0c`;WF|ePylu9O(D)WFJEaOR$MGU?};-iur&us<S6{><paP9k_92P>HL9s;PG- zUR)d0pu3{-nKh_?V2P^mKC^@u)~5ELA=o3UUweU(t%E+(l{m;{bk=vYJxnugXHlZv zAP<te+R2{D944FL(V-tqMyY=≧&&l}AHH{qdvH#q$79_HBsV%9*mJEaxN})`*u{ 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_gs_sci.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_gs_sci.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecd385aa4955ec72d14498fca9bd122ff78a551b GIT binary patch literal 5282 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_gs_sci2.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_gs_sci2.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39fb3191fa91a4062b35e5ae88f5b1d2fec4f8b1 GIT binary patch literal 5033 zcmb7IOLH7o74F-QneKUOG}6pivMd`zWr7_g4v=6(Y;YXgMG#O<k*dK|S9@-2+~b*P z`F2aORJS)MEJN1t4_If#mL&yMtXT9CR!*_-h6QZkJGbX$Su)U5efsvf@6+e|&bjk; zxm@V}^H)FnMN`xMrY&41$~SRGA3<=9v!T{yc<MuKq<3{jI%8;z%&s}Iy4EPy&5iQi zywaOPd*pN-lr5h7RO=S*XgtsDPc?4)&au%ga&}+qIL|P$w$ov0Zsf%xc-k>jqZdZ0 z5e4Ja@?vj%Ej6PjB1V(C|9IE+hW*gp72e4IBovQ(jQZoEr-l0#?&xa}u@*C_9kW;` zS=9P^R?4(}y{{kB0@zN+5IWimg9PmuGg<K?KlXmB2?y{08f`raNB-6)!EhLOqpkbF zXn*L%K{&p8dwdXxa6IzI@zvc>T)h>Bd%i&3fq(VGu;&efBh_$gcYoZY9?{ltL9I3u zZPB*+ksI}bYj5lwrg;&@?kIkm!`u-qO=F@6*`wn0BK=L=(fbg-`Yc_YGp@tb1~<5g zr#Ugbl^MR9;|?!CpXWth!qetuUcuAhRal~y7H|LH1NY8-_x`PW*LrGVj7?9vm0=4g zNSM{dm(PsHQb&D}F+NB~$EWg#yP}L{%5<5aUa9T6!8nLrm)<7ZI%+J;_{OxsY-;+R zvu{fK<Sf<(bn9G~tU+HFd;LsrXbJXyW}P8*Y4r8PlqME!?(~22Yr1}S;~8y?J~xjK z_k6gXKHgK#klF#qHx1&$)Y=_}Ufi)n1#Q#9cz@)I@L?E7X+8@2BhTg2LXcLX*o%Gl zz!QNt?)fK8u>4}RvIm(evLQ6Kj-SnrE-c#QlpZtlkWY}0s4w$l6eN3KCVFBdW@2$B zEtn-I%?EmtPi&c&c2i3nGLm#;PUbjkYQNOyrCq%ZgC>Qng#w4ZBWf78ql-EoK!xyn zey2Dwg))Q7fzgyjX(<%J7@$#JJ~c^{TEUq6Pg53%RSY4(Fj`uS!`K_T%6w^64eHJ| zdeUecKv9qI=DR0aDjP3jz^DYFu@bCDzf0`s^+g-LdVn6`o-SHi9=9^*pTQ@}oXVIm zqdqaCoj6<>2|QvP18-|&w4%&&qpc++JWV{yc*300l(}ssp{qzIsmc;qsB#S7O=|Gr z9G*+kkW1Vk^T!6&$#O%Jr3Mx>t-%=7#%zLaRXg*Pc9UAPwXoKDvi#zFu{FqXlLH6b zkmZd3XcbTY66a;{n7yz4{0~V3YidBdA{#RISQpRbvRsiXTvx6#E72Nc{j3_e+3H#S zEDb$tvWgwn2KKSm(B9Du4QpOKsl^y)j?&gzXU@N^J$e4*`Nveh49r`woGGoo0pweA z<SV}x6f~ZZ=s2knjN{Z8`eVhl^Jt)4KO+T8c;mjGnteb1sMAy^5Nqh279)Qgg+gIL ztV1Ktlh`0}fg03Cz8CEap8`dOn59XVUN~io)XDfH<Y8(-=^ls`>YL~OF!tOyWd~`2 z=+#xhDP=!N*~em&=9oi^4N`qD5En^Hv1@^V>w6;H^ZE*)?*1Nd>(f%BZ$V_>F?Ca~ zDF^{dy2(nqtzTwWAWe2juRv$BciEe)!LHjTv_~6@Fnf9U8MMe6Ga~=%E1;!<Ho=N1 zSQQ9BfDXY6E~nr{Fe7*|f)rSeAXJU@fq~mZ0A#Yz&~_2rV~d-g>42Ff32N0{eOu!> zlnq(sMiXtewKzwvKgb`$9TgNy3bw|;MjQQDZ)r(gmI&H1)1lu)zdY|tvuEy>jfIgK zfO0u@GN_|e$V!xS&};x0fpj%#%BEZeU|Q1QdCWr4r`zGSS{>1W)1Y;tL_INfTQ12K z+AL-7vW@=dWNY?*ZctS1*5LYU0BNIzUT9;W&6-?7PxQvlT3B~U7Ptze$+}$6Y5}b# z+N=-Cu!?Hm(k3&l$u?@%vNw#_#E4CdL{M#>0GpG=4uvss84l24VhN9D|HdWA=@3>( zpH(iFE8?r9rz~y}eMi0sBher&g+B2bL}~`HKboUef%BfAsF0eyaPP2levVVop>C(( zQ@l<UU#Cv?1cVP2_{5u}D-FFdA9>=ji{vdec!2bD?@^$zml}87AZ2%_Fnu~LAagi! zA9;Z7(Hx%&nA6~RlvcCJg7E<*8{s%DKK6zqZ|wFx%6<dN0#Cwt#d{cq!+nIq@L}YO z36g(^bw=9|3dz7La16BK2f2>WSYtK4!CGvCZIYhKMuRo<8W3M$-=KE-(ZxkPpE}PB z(!?+`NN*#Ll9YU$5-rb!G!hUvGet~-HbI)8U70|;D$A<AM)4A0s#45E$;?U$NEU#! z6z2vYgE{PzIsjh>;7b$0*8zAyI0HP&R991VR5pkZCS+hMGQg;^j+HF~@(xkQF|tRL zKn;oz8Wa753MO@PVpxf1<6v!wr*dVwT8z3n0eXdYgF6E{=w<?RRT^LoXxmgI(MsCf zOwM7Y=hhT-72wy9<3rQZpj*Z`ZP{v~k6h0B$|m5sjwrmgpj(ITJRm)7bAC`z^K5`9 zHb5$?Q=-7Si!)-lATJC`u*n9^19HHK$)>z8dnZbGp~Ykc8;V9YvNz1!mYcFov;)#; z|2MMefByS_y!PPpFK;NOcr{&=7wCc#`Z*gYipVJB9jZ{Y@h+9VO@dfLT!-jf{J%&- ze1|$xa8~?~@jx+yqe^$hcd70@5^s~BvrB4%C<fvty?>9y_eoH)DQ=Tkh~Yly#eIv! zHSqz}-63(8#A$(jMfh|aJ$R834$(ZK-kL#)v5M>&BPdqb)a!~B6f;;Yw#hb#6DZc} zHRCd3e8T`UKzAB9oI2x-8)z#gZk0)YiNdMekbht#4vs1~a7=RPEa(@x4pyM>SOyyu z@T?+;1H<ri3XK)`67przDDPLfBy@Fn@RF=IaXM694gA9Y9cj$G+8CG;e>>2*F=@yK zd8S;3M<XPvjF-xU$yv=HM<ZbrBnLo^dc#Z=1l0;Wxh%`Fa>A3%EbR6F^hdh>ej|%+ z`2`nMu1Dvox&J9Y?X3O}PMA8qa5TzN$g(QV(#Mi|%?@QzT3>uq=hP_k*biyuxwF08 zj-S#u5ENj<4vAMgqgvGdIOwT7^9yu{E<tEIIbi`o2#F(tO^rei-YN)8SCm5@wHJdA zt$sGjPNzVBAJAV6uA3HIcNFsdA(cz6`()o6W;LQp%WISP3W;x$xJTkgBz{U_o)fDQ z{TCtV^hj?Jo$#?Z!_L``{g!>jzOL#zrPRW)fA4T188Pv1)uRQXp-?F3FrKcx^as!U i-zq`p%Z!C+($iLx+S}Rg-b0$KMYKR0Ky6VnZu|!o3tXcB literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_ls_bda.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_ls_bda.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..005931bbcedf15b2cb73c58feec0bec63bdfca66 GIT binary patch literal 5386 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_ls_bda.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_ls_bda.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ca85c6006b5eaf6bedd40448862c238c2a09aaf GIT binary patch literal 4819 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_ls_ci.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_ls_ci.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c46d670d002febc994b991f5e161624431c22975 GIT binary patch literal 3877 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 IHMwX17t;r6ZU6uP literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/ekf_ls_ci2.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/ekf_ls_ci2.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e30eed1b45497e918f55103b7fe9d301faa1a916 GIT binary patch literal 5074 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/localization_algo_framework.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/localization_algo_framework.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c70caf19a44a99759548f9b65aac709c0097fd76 GIT binary patch literal 2419 zcmc&#OK;mo5S}IVvPC(LVy92IY>NbC4=Hl%p(uhDZBNz3J*fp2G<PMlrbuR&auPxA zA!&b1e@?G^?WupEr_Ky5S+a-}1qx)v9ggO){APA$_x@n8|J5JA{TOxt{)CO;BmV@a z{TPYDM?eNJ7Vw?&K>6@1ihOwG!5IGvIE`9=p&^VCqO0K{^8}}TiA1wIE>(MseORwF zZh^w5O{<REpgN$s%p=nSwa0uH)IO*_^C%2J4Vd2pbpYxP^Js7g>MrwrP(x7nm`CFy z#CYt6`eGvEY+A^PiD&v*VJ;TmSLdk>@u|*rxE6=c(&{{nvn(tNYtyp~b@M!_(jvFv zq%dJtBypB5Vv?ZUv@qx}vk3)FgWfd1#%TvgmI9UllGAw_iBTln9z)3yN#wbf)!D>Q z;(rIz#@FAEH^0HK?Poipn@Ap&FI-Q`G*2rjX#vYv#Nxf(s2{ED5`l&^=uMOHc9B7_ zKLciskTNWMwNTF3YJyb*t~b?{q!@bm?{%MC*)^x=5WOodv{wRN3M#tO$Qv!fZ{sx6 zDy)i7=}DUF&{lD!!^_yDah~W8DUaVgPjpE;5qXT!?dS8EG{sp_+1q&UvA<mTbH4f; z&>uErtHI^JMG@^pQJFZ=VKLba$Lt}Rbs!vsRB;vG4&($2FqvnV49SbhZIlNaF+FaG z>Gj?TZ8Z&gQ&DnV{DRDqJO080^Zs>>P-XLBa7sE4NcTDGP_d=+S@#3$yj!{!>q^%7 z8@h^*1}qA}CD9qVerbv_o^tCgj<Pscv)EjO#hKOS@>*&%CMLba4BtrIASq_Ed7dV< z(LtJDVh^iuUSfWA)ON#-m1Qk;$MKmhvN>j%ms*QgU)U0xJD4HYE=`(OQLFBkfJFUz zHCeqVwd-4*+rl*NYM;-9+WIbf+947Ufp;hZv7X-Iq+v@pToc+e8q~_PhrE9uAcH&d zQwy$qxI)^7s}616vIWaFOnvTmF0`n7gWepYpA*&vc*^A(`;U%6*R|<%7E9~eX|DA1 zTlHzEqfc;JE+sJ(iw6yucQgL~LpN_B4D&XTcZj@8gigqs&@pBx*B{}$LHkJq+QwRV zGk~cs9{wxf#wvX?fT=Y;-2xmoWO%DZN6~<;G`d}+bo)}y3N_D&52SoLkF#q{S4veR zQW~muLl=>uBi+!wYwi=FV&pwGls9hEjSApe;4+{qlUm0fAqhlB1pf7J5VYuL$RhGx c8*doAaJ{@_Nz-Dk_eG8OOS)M3Y7D%807G3Qe*gdg literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/localization_algo_framework.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/localization_algo_framework.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed8bf49bd81b702d10a4fd624404d3f372042198 GIT binary patch literal 2362 zcmcgt&2QT_6c;7gR{W8+X|his&<3oi2BgNYYcUinx?MJ7KrVw<fM7)0;Ub9|DLbuU zUzYBV*`Kp3uRHBu*lF+4v7^L7x5H36e2;nJBY*FU@5{lU`}H5c{S>!7?@zBb0$4wT zX+8qNJx(%jOuqHF&x1D}53c;N&&jEmgnz+zZ<He43?CNHV45F+2+-pm?j8qg?QzIM z-g@JWTfEIXz}r0Hd%!!q%X`2h-sc10dwieY1K#EL`2*lRe!w3B@AE^r`N$rKiwR}f zRMClMxwusNV)1=-E=>%7)wzhb;`mZl=P}E&xKzf-vkbn?inNldF!4m`I8!Oh<bt6D z_Dz)rh1{fQ3J&BrpTjg=AWO3JC^!aykWoVHp2JZ9jKsI05!pne3xD@?3)tVQ;knAi z@KR=(Wclz^=CjOQcJiW_ORb7r6x9hJIeD&BDKvbWi<9qasD@j>!#Y@Jzu6Vtxa3Ls z+D4ShLROR_7~_m0i;s8R_hhp#C9n|(a-7a^ND^=9{k$>SS(p$Vg4mh4Cb-K+Q&CZL zM+E=9?Z(Z%W>@z?yMpYyBELcwfwTS5BL0TSOz^l;F&7hAh}cxD67igA$%<5bg5h}a zDitM0Gw~fh+bw1})#^-D<}TKUPM>b{ovV5^*pC_<)u8g<El74Os5DDOtR}mr=siHP zHNqJ{Ijh)RBaR_~Q%ovB-C^`L!u^^(Uo_bBcI^~Hi~~95wM&PWuvkK2U-<eE(*kM& z9)?qt`5=1?GE$QTAbScjza|So_5;X*jjV#F;fj!TWwl4PS87$VsjHR6Va5ucGkp=O zGb8l;TB-%s(j5GEBejE6<@v0T>3Y+?Eap(*Jf4-{J(0BRLG5I^mf9nBW>hu<AG)Kq z;>``W#QGlCZ(F67MU{l>D!_cTz4d9ddR+?JGomm`H^!{z9*y<x2cT&VfOsVG`y?XU z=`W5O0#;K^F(NoRFfl?dI`6?^NnVDlU=^-ftM)QjhRfD8a4(k2o}_aFS|7o7ON{Nq z(^m*6D0~}j$H-~UsIe_saPjI+(&_u4bPUtD`~b*{&l;faI{JS@tlx**^#@2kM1tMw zE=ct3r!a3oK5hWn82NXK6NCTgUvW03;ycBOY5(~xoN<FcZ<XID8DI~>en6@1QkpA1 z%W&PN^p_dSuD^6B<tn9AV<u~C9U32EJwSp9?J`bdL^Zn0m0&I2*xoeuAB{Z@%fcK2 qiAYGI;QBX+Lj1WMNnl&h7obD>Md>6>huP@q8t+%w30*Ub{C@!Xm_aN6 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/simple_ekf.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/simple_ekf.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6aa1a5652f53acdfb31168e23820c7265f0c4ae GIT binary patch literal 3483 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/simple_ekf.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/simple_ekf.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..796da56e40283212099772fe8c64b1eab28ffb56 GIT binary patch literal 3239 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 Q)cFAMpgY;)ZQFDH2aYi8=Kufz literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/simple_ekf_2.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/simple_ekf_2.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d373b47ea3d79b661c68dd98e07c23814d5df3f GIT binary patch literal 3794 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 bp#4v3g?viyfcc=HP<azt#*=Ax9N+yPd2eve literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/simple_ekf_meas_only.cpython-35.pyc b/CoLo-AT/localization_algos/__pycache__/simple_ekf_meas_only.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49abc100156a47f7e3866cab47e5b639d5991f4f GIT binary patch literal 3333 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/__pycache__/simple_ekf_meas_only.cpython-36.pyc b/CoLo-AT/localization_algos/__pycache__/simple_ekf_meas_only.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..392809c937f58499e81e740e57fb568831ccf316 GIT binary patch literal 3130 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 LZkh-+x##>Bk<;{v literal 0 HcmV?d00001 diff --git a/CoLo-AT/localization_algos/cal_test.py b/CoLo-AT/localization_algos/cal_test.py new file mode 100644 index 0000000..67766b1 --- /dev/null +++ b/CoLo-AT/localization_algos/cal_test.py @@ -0,0 +1,44 @@ + +import scipy +import numpy as np +from sympy import * +''' +# for absolute landmark +x_symbol, y_symbol = symbols('x y') +h1 = sqrt((lx-x_symbol)*(lx-x_symbol)+(ly-y_symbol)*(ly-y_symbol)) +h2 = atan2((ly-y_symbol), (lx-x_symbol)) + +h_11 = diff(h1, x_symbol) +print(h_11) +h_12 = diff(h1, y_symbol) +print(h_12) +h_21 = diff(h2, x_symbol) +print(h_21) +h_22 = diff(h2, y_symbol) +print(h_22) +''' +''' +h11 = float(h_11.subs([(x_symbol, x),(y_symbol, y)])) +h12 = float(h_12.subs([(x_symbol, x),(y_symbol, y)])) +h21 = float(h_21.subs([(x_symbol, x),(y_symbol, y)])) +h22 = float(h_22.subs([(x_symbol, x),(y_symbol, y)])) +''' + +# for relative landmark +x_i, y_i, x_j, y_j = symbols('x_i, y_i, x_j, y_j') + +h1 = sqrt((x_j-x_i)*(x_j-x_i)+(y_j-y_i)*(y_j-y_i)) +h2 = atan2((y_j-y_i), (x_j-x_i)) + +h_11 = diff(h1, x_j) +print(h_11) +h_12 = diff(h1, y_j) +print(h_12) +h_21 = diff(h2, x_j) +print(h_21) +h_22 = diff(h2, y_j) +print(h_22) + + +temp = np.asmatrix(scipy.linalg.sqrtm(np.matrix('1,2;3,4')))**2 +print(temp) diff --git a/CoLo-AT/localization_algos/centralized_ekf.py b/CoLo-AT/localization_algos/centralized_ekf.py new file mode 100755 index 0000000..821c31e --- /dev/null +++ b/CoLo-AT/localization_algos/centralized_ekf.py @@ -0,0 +1,137 @@ +import numpy as np +import math +from math import cos, sin, atan2, sqrt +from numpy import dot +import scipy.linalg as linalg +#import parameters +from localization_algo_framework import ekf_algo_framework + +def rot_mtx(theta): + return np.matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class Centralized_EKF(ekf_algo_framework): + + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.01*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + trace_state_var = np.trace(sigma_s[i:i+2, i:i+2]) + return trace_state_var + + #ef propagation_update(self, s, orinetations, sigma_s, input_data, sigma_odo, index): + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + num_robots = int(len(s)/2) + + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + i = 2*index + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + G = rot_mtx(self_theta) + W = sigma_odo + W[0,0] = sigma_odo[0,0]*delta_t*delta_t + #W[1,1] = sigma_odo[1,1]*delta_t*delta_t*v*v + W[1,1] = sigma_odo[1,1]*delta_t*delta_t + Q_ii = G * W * G.getT() + Q = np.zeros((2*num_robots,2*num_robots)) + Q[i:i+2, i:i+2] = Q_ii + sigma_s = sigma_s + Q #errors in the odometric measurements of the robots are uncorrelated, it's a diagonal matrix + + return [s, orinetations, sigma_s] + + + + #def absolute_obser_update(self, s, orinetations, sigma_s, input_data, sigma_ob, index): + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + i = 2*index + landmark_loc = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + ################### + z = np.matrix([meas_range*cos(bearing), meas_range*sin(bearing)]).getT() # actual measurement + # for estimated measurement + delta_x = landmark_loc[0] - s.item(i,0) + delta_y = landmark_loc[1] - s.item(i+1,0) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) # shifted to robot frame + + H_i = np.matrix(np.zeros((2,2*num_robots))) + H_i[0, i] = -1 + H_i[1, i+1] = -1 + H = rot_mtx(self_theta).getT()*H_i + + #sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + V = rot_mtx(bearing) + R = V*sigma_ob*V.getT() #sigma_z + + sigma_invention = H * sigma_s * H.getT() + R + kalman_gain = sigma_s*H.getT()*sigma_invention.getI() + s = s + kalman_gain*(z - z_hat) + sigma_s = sigma_s - kalman_gain*H*sigma_s + ################## + + return [s, orinetations, sigma_s] + + + + #def relative_obser_update(self, s, orinetations, sigma_s, input_data, sigma_ob, index): + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + + ############### + i = index * 2 + obser_index = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + j = obser_index * 2 + + z = np.matrix([meas_range*cos(bearing), meas_range*sin(bearing)]).getT() # actual measurement + + H_ij = np.zeros((2,2*num_robots)) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + + H = rot_mtx(self_theta).getT()*H_ij + + z_hat = H * s + + #sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + + V = rot_mtx(bearing) + R = V*sigma_ob*V.getT() + + sigma_invention = H* sigma_s*H.getT() + R + kalman_gain = sigma_s*H.getT()*sigma_invention.getI() + s = s + kalman_gain*(z - z_hat) + sigma_s = sigma_s - kalman_gain*H*sigma_s + ################# + + return [s, orinetations, sigma_s] diff --git a/CoLo-AT/localization_algos/ekf_gs_bound.py b/CoLo-AT/localization_algos/ekf_gs_bound.py new file mode 100644 index 0000000..1736d1f --- /dev/null +++ b/CoLo-AT/localization_algos/ekf_gs_bound.py @@ -0,0 +1,143 @@ +import numpy as np +from numpy import matrix +from math import cos, sin, atan2, sqrt +from localization_algo_framework import ekf_algo_framework + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class EKF_GS_BOUND(ekf_algo_framework): + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.1*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + trace_state_var = np.trace(sigma_s[i:i+2, i:i+2]) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + + var_v = 0.1 # variance of the velocity + + i = 2*index + num_robots = int(len(s)/2) + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + Q = sigma_odo + Q[1,1] = Q[1,1]*v*v + W = delta_t*rot_mtx(self_theta) + + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + for j in range(num_robots): + jj = 2*j + sigma_s[jj:jj+2, jj:jj+2] += delta_t*delta_t*var_v*np.identity(2) + + return [s, orinetations, sigma_s] + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + ''' + landmark_loc = measurement_data[0] + dis = measurement_data[1] + phi = measurement_data[2] + ''' + + i = 2*index + H_i = np.matrix(np.zeros((2,2*num_robots)), dtype = float) + H_i[0, i] = -1 + H_i[1, i+1] = -1 + H = rot_mtx(self_theta).getT()*H_i + + var_range = 0.1 + d_max = pow(0.05,2) + var_bearing = pow(2.0 / 180, 2) + + R = np.matrix(max(var_range, d_max, var_bearing)*np.identity(2)) + sigma_s = (sigma_s.getI()+H.getT()*R.getI()*H).getI() + + return [s, orinetations, sigma_s] + + + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + i = index * 2 + obser_index = measurement_data[0] + #dis = measurement_data[1] + #phi = measurement_data[2] + j = obser_index * 2 + + #z = matrix([dis*cos(phi), dis*sin(phi)]).getT() + + H_ij = np.zeros((2,2*num_robots)) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + H = rot_mtx(self_theta).getT()*H_ij + + var_range = 0.1 + d_max = pow(0.05,2) + var_bearing = pow(2.0 / 180, 2) + + R = np.matrix(max(var_range, d_max, var_bearing)*np.identity(2)) + sigma_s = (sigma_s.getI()+H.getT()*R.getI()*H).getI() + + return [s, orinetations, sigma_s] + + def communication(self, robot_data, sensor_data): + + [s, orinetations, sigma_s, index] = robot_data + [comm_data, comm_variance] = sensor_data + [sender_idx, comm_robot_s, comm_robot_sigma_s]=comm_data + + #sent to robot i from robot k + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + i = index * 2 + k = sender_idx*2 + e = 0.9 # (iii+1)*0.01 + #e = comm_e + + H_k = np.zeros((2,2*num_robots)) + H_k[0, i] = -1 + H_k[1, i+1] = -1 + H_k[0, k] = 1 + H_k[1, k+1] = 1 + H = rot_mtx(self_theta).getT()*H_k + + var_range = 0.25 + d_max = pow(0.05,2) + var_bearing = pow(2.0 / 180, 2) + + R = np.matrix(max(var_range, d_max, var_bearing)*np.identity(2)) + sig_inv = e*sigma_s.getI() + (1-e)*(H.getT()*R.getI()*H) + sigma_s = sig_inv.getI() + + return [s, orinetations, sigma_s] \ No newline at end of file diff --git a/CoLo-AT/localization_algos/ekf_gs_ci.py b/CoLo-AT/localization_algos/ekf_gs_ci.py new file mode 100644 index 0000000..9933159 --- /dev/null +++ b/CoLo-AT/localization_algos/ekf_gs_ci.py @@ -0,0 +1,148 @@ +import numpy as np +from numpy import matrix +from math import cos, sin, atan2, sqrt +from localization_algo_framework import ekf_algo_framework + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class EKF_GS_CI(ekf_algo_framework): + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.02*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + trace_state_var = np.trace(sigma_s[i:i+2, i:i+2]) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + + var_v = 0.1 + + num_robots = int(len(s)/2) + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + i = 2*index + + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + for j in range(num_robots): + jj = 2*j + if j==index: + #print(np.matmul(sigma_odo,rot_mtx(self_theta).getT())) + sigma_s[jj:jj+2, jj:jj+2] += delta_t*delta_t*rot_mtx(self_theta)*sigma_odo*rot_mtx(self_theta).getT() + else: + sigma_s[jj:jj+2, jj:jj+2] += delta_t*delta_t*var_v*np.identity(2) + + return [s, orinetations, sigma_s] + + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + + + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + landmark_loc = measurement_data[0] + dis = measurement_data[1] + phi = measurement_data[2] + + i = 2*index + H_i = np.matrix(np.zeros((2,2*num_robots)), dtype = float) + H_i[0, i] = -1 + H_i[1, i+1] = -1 + H = rot_mtx(self_theta).getT()*H_i + + + #z_hat= rot_mtx(self_theta).getT() * (landmark_loc + H_i*s) + delta_x = landmark_loc[0] - s.item(i,0) + delta_y = landmark_loc[1] - s.item(i+1,0) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) + z = matrix([dis*cos(phi), dis*sin(phi)]).getT() + + sigma_z = rot_mtx(phi) * sigma_ob * rot_mtx(phi).getT() + + sigma_invention = H * sigma_s * H.getT() + sigma_z + kalman_gain = sigma_s*H.getT()*sigma_invention.getI() + + s = s + kalman_gain*(z - z_hat) + sigma_s = sigma_s - kalman_gain*H*sigma_s + + return [s, orinetations, sigma_s] + + ''' + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + i = index * 2 + obser_index = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + j = obser_index * 2 + + z = np.matrix([meas_range*cos(bearing), meas_range*sin(bearing)]).getT() # actual measurement + + H_ij = np.zeros((2,2*num_robots)) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + H = rot_mtx(self_theta).getT()*H_ij + + z_hat = H * s + + sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + + V = rot_mtx(bearing) + R = V*sigma_ob*V.getT() #sigma_z + + sigma_invention = H*sigma_s*H.getT() + R + kalman_gain = sigma_s*H.getT()*sigma_invention.getI() + + s = s + kalman_gain*(z - z_hat) + print('inside ekf gs ci') + print(s) + sigma_s = sigma_s - kalman_gain*H*sigma_s + + return [s, orinetations, sigma_s] + ''' + ''' + def communication(self, robot_data, sensor_data): + + [s, orinetations, sigma_s, index] = robot_data + [comm_data, comm_e] = sensor_data + + comm_robot_s = comm_data[0] + comm_robot_sigma_s = comm_data[1] + + e = 0.23 # (iii+1)*0.01 + #e = comm_e + + sig_inv = e*sigma_s.getI() + (1-e)*comm_robot_sigma_s.getI() + s = sig_inv.getI() * (e*sigma_s.getI()*s + (1-e)*comm_robot_sigma_s.getI()*comm_robot_s) + sigma_s = sig_inv.getI() + + return [s, orinetations, sigma_s] + ''' \ No newline at end of file diff --git a/CoLo-AT/localization_algos/ekf_gs_sci2.py b/CoLo-AT/localization_algos/ekf_gs_sci2.py new file mode 100644 index 0000000..482547d --- /dev/null +++ b/CoLo-AT/localization_algos/ekf_gs_sci2.py @@ -0,0 +1,205 @@ +import numpy as np +from numpy import matrix +from math import cos, sin, atan2, sqrt +from localization_algo_framework import ekf_algo_framework + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + +class EKF_GS_SCI2(ekf_algo_framework): + def __init__(self, algo_name): + self.algo_name = algo_name + + def state_variance_init(self, num_robots): + sigma_d = 0.1*np.matrix(np.identity(2*num_robots), dtype = float) + sigma_i = 0.1*np.matrix(np.identity(2*num_robots), dtype = float) + state_variance = [sigma_d, sigma_i] + return state_variance + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + [sigma_d, sigma_i] = sigma_s + total_sigma = sigma_d + sigma_i + trace_state_var = np.trace(total_sigma[i:i+2, i:i+2]) + return np.trace(total_sigma) + + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + + var_v = 0.1 + + num_robots = int(len(s)/2) + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + Q = sigma_odo + W = delta_t*rot_mtx(self_theta) + + i = 2*index + + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + [sigma_d, sigma_i] = sigma_s + + Q = sigma_odo + W = delta_t*rot_mtx(self_theta)*np.matrix([[1,0],[0,v]]) + + for j in range(num_robots): + jj = 2*j + + if j ==index: + total_sigma = sigma_i[jj:jj+2, jj:jj+2] + sigma_d[jj:jj+2, jj:jj+2] + sigma_i[jj:jj+2, jj:jj+2] += W*Q*W.getT() + total_sigma += W*Q*W.getT() + sigma_d[jj:jj+2, jj:jj+2] = total_sigma - sigma_i[jj:jj+2, jj:jj+2] + + else: + ''' + total_sigma = sigma_i[jj:jj+2, jj:jj+2] + sigma_d[jj:jj+2, jj:jj+2] #repeated + sigma_i[jj:jj+2, jj:jj+2] += delta_t*delta_t*var_v*np.identity(2) #unknow other robot's movement + total_sigma += delta_t*delta_t*var_v*np.identity(2) + sigma_d[jj:jj+2, jj:jj+2] = total_sigma - sigma_i[jj:jj+2, jj:jj+2] + ''' + + sigma_s = [sigma_d, sigma_i] + + return [s, orinetations, sigma_s] + + + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + landmark_loc = measurement_data[0] + dis = measurement_data[1] + phi = measurement_data[2] + + i = 2*index + H_i = np.matrix(np.zeros((2,2*num_robots)), dtype = float) + H_i[0, i] = -1 + H_i[1, i+1] = -1 + H = rot_mtx(self_theta).getT()*H_i + + delta_x = landmark_loc[0] - s.item(i,0) + delta_y = landmark_loc[1] - s.item(i+1,0) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) + z = matrix([dis*cos(phi), dis*sin(phi)]).getT() + + [sigma_d, sigma_i] = sigma_s + total_sigma = sigma_i + sigma_d + + sigma_ob[1,1] = sigma_ob[1,1]*dis*dis + sigma_z = rot_mtx(phi) * sigma_ob * rot_mtx(phi).getT() + + + sigma_invention = H * total_sigma * H.getT() + sigma_z + kalman_gain = total_sigma*H.getT()*sigma_invention.getI() + + s = s + kalman_gain*(z - z_hat) + + total_sigma = total_sigma - kalman_gain*H*total_sigma + i_mtx = np.identity(num_robots*2) + sigma_i = (i_mtx - kalman_gain*H) * sigma_i * (i_mtx.copy() - kalman_gain*H).getT() + kalman_gain * sigma_z * kalman_gain.getT() + sigma_d = total_sigma - sigma_i + + sigma_s = [sigma_d, sigma_i] + + return [s, orinetations, sigma_s] + + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + i = index * 2 + obser_index = measurement_data[0] + dis = measurement_data[1] + phi = measurement_data[2] + j = obser_index * 2 + + z = matrix([dis*cos(phi), dis*sin(phi)]).getT() + + H_ij = np.zeros((2,2*num_robots)) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + H = rot_mtx(self_theta).getT()*H_ij + + #z_hat = H * s + #sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + + delta_x = s.item(j,0) - s.item(i,0) + delta_y = s.item(j+1,0) - s.item(i+1,0) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) + + sigma_ob[1,1] = sigma_ob[1,1]*dis*dis + sigma_z = rot_mtx(phi)*sigma_ob*rot_mtx(phi).getT() + + [sigma_d, sigma_i] = sigma_s + + e = 0.83 + + p_1 = (1/e) * sigma_d + sigma_i + + # + p_2 = (1/(1-e)) * H * (sigma_i + sigma_d) * H.getT() + sigma_z + sigma_invention = H * p_1 * H.getT() + p_2 + kalman_gain = p_1 *H.getT()*sigma_invention.getI() + # + + s = s + kalman_gain*(z - z_hat) + i_mtx = np.identity(num_robots*2) + + total_sigma = (i_mtx.copy()-kalman_gain*H) * p_1 + sigma_i = (i_mtx - kalman_gain*H) * sigma_i * (i_mtx.copy() - kalman_gain*H).getT() + kalman_gain * sigma_z * kalman_gain.getT() + sigma_d = total_sigma - sigma_i + + sigma_s = [sigma_d, sigma_i] + + return [s, orinetations, sigma_s] + + def communication(self, robot_data, sensor_data): + + [s, orinetations, sigma_s, index] = robot_data + [comm_data, comm_variance] = sensor_data + [comm_robot_s, orinetations, comm_robot_sigma_s]=comm_data + num_robots = int(len(s)/2) + + e = 0.9 # (iii+1)*0.01 + + [sigma_d, sigma_i] = sigma_s + [comm_robot_sigma_d, comm_robot_sigma_i] = comm_robot_sigma_s + + p_1 = (1/e) * sigma_d + sigma_i + p_2 = (1/(1-e)) * comm_robot_sigma_d + comm_robot_sigma_i + + kalman_gain = p_1 * (p_1+p_2).getI() + s = s + kalman_gain * (comm_robot_s - s) + + i_mtx = np.identity(num_robots*2) + total_sigma = (i_mtx.copy() - kalman_gain) * p_1 + sigma_i = (i_mtx - kalman_gain) * sigma_i * (i_mtx.copy() - kalman_gain).getT() + kalman_gain * comm_robot_sigma_i * kalman_gain.getT() + sigma_d = total_sigma - sigma_i + sigma_s = [sigma_d, sigma_i] + + return [s, orinetations, sigma_s] + + diff --git a/CoLo-AT/localization_algos/ekf_ls_bda.py b/CoLo-AT/localization_algos/ekf_ls_bda.py new file mode 100644 index 0000000..4cde55a --- /dev/null +++ b/CoLo-AT/localization_algos/ekf_ls_bda.py @@ -0,0 +1,175 @@ +# coding: utf-8 + + +#local state CI (LS-BDA) [9] - “Recursive decentralized collaborative localization for sparsely communicating robots†- L. Luft, T. Schubert, S. I. Roumeliotis, and W. Burgard, +#Local state with block diagonal approximation (BDA) algorithm +import numpy as np +from numpy import matrix +from numpy import linalg +from math import cos, sin, atan2, sqrt +from localization_algo_framework import ekf_algo_framework + + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class EKF_LS_BDA(ekf_algo_framework): + + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.01*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + trace_state_var = np.trace(sigma_s) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + + num_robots = int(len(s)/2) + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + i = 2*index + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + W = sigma_odo + W[0,0] = sigma_odo[0,0]*delta_t*delta_t + W[1,1] = sigma_odo[1,1]*delta_t*delta_t*v*v + G = rot_mtx(self_theta) + Q_ii = G * W * G.getT() + + Q = np.zeros((2*num_robots,2*num_robots)) + Q[i:i+2, i:i+2] = Q_ii + sigma_s = sigma_s + Q #errors in the odometric measurements of the robots are uncorrelated, it's a diagonal matrix + + return [s, orinetations, sigma_s] + + + + #def absolute_obser_update(self, s, orinetations, sigma_s, input_data, sigma_ob, index): + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + i = 2*index + + local_s = s[i:i+2] + local_sigma = sigma_s[i:i+2,i:i+2] + + landmark_loc = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + z = matrix([meas_range*cos(bearing), meas_range*sin(bearing)]).getT() # actual measurement + # for estimated measurement + delta_x = landmark_loc[0] - s.item(i,0) + delta_y = landmark_loc[1] - s.item(i+1,0) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) + + H_i = matrix([[-1,0],[0,-1]], dtype=float) + H = rot_mtx(self_theta).getT()*H_i + + sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + V = rot_mtx(bearing) + R = V*sigma_ob*V.getT() #sigma_z + sigma_invention = H*local_sigma*H.getT() + R + kalman_gain = local_sigma*H.getT()*sigma_invention.getI() + + s[i:i+2] = local_s + kalman_gain*(z - z_hat) + sigma_s[i:i+2,i:i+2] = local_sigma - kalman_gain*H*local_sigma + + multi_i = (np.identity(2) - kalman_gain*H ) + + for k in range(num_robots): + if( not (k==index)): + kk = 2*k + sigma_s[i:i+2,kk:kk+2] = multi_i * sigma_s[i:i+2,kk:kk+2] + sigma_s[kk:kk+2,i:i+2] = sigma_s[kk:kk+2,i:i+2] * multi_i.getT() + + return [s, orinetations, sigma_s] + + + #def relative_obser_update(self, s, orinetations, sigma_s, input_data, sigma_ob, index): + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + obser_index = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + i = index * 2 + j = obser_index * 2 + + H_ij = np.zeros((2,2*num_robots)) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + + H = rot_mtx(self_theta).getT()*H_ij + z_hat = H * s + z = matrix([meas_range*cos(bearing), meas_range*sin(bearing)]).getT() #actual measurement + + + reduced_sigma = np.zeros((len(s), len(s))) + reduced_sigma[i:i+2,i:i+2] = sigma_s[i:i+2,i:i+2] + reduced_sigma[j:j+2,j:j+2] = sigma_s[j:j+2,j:j+2] + reduced_sigma[i:i+2,j:j+2] = sigma_s[i:i+2,j:j+2] + reduced_sigma[j:j+2,i:i+2] = sigma_s[j:j+2,i:i+2] + + multi_i = sigma_s[i:i+2,i:i+2].getI() + multi_j = sigma_s[j:j+2,j:j+2].getI() + + sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + V = rot_mtx(bearing) + R = V*sigma_ob*V.getT() #sigma_z + sigma_invention = H*reduced_sigma*H.getT() + R + kalman_gain = reduced_sigma*H.getT()*sigma_invention.getI() + + s[i:i+2] = s[i:i+2] + kalman_gain[i:i+2]*(z - z_hat) + s[j:j+2] = s[j:j+2] + kalman_gain[j:j+2]*(z - z_hat) + + sigma_s = sigma_s - kalman_gain*H*reduced_sigma + + multi_i = sigma_s[i:i+2,i:i+2] * multi_i + multi_j = sigma_s[j:j+2,j:j+2] * multi_j + + + for k in range(5): + if( not (k == index)): + if( not (k == obser_index)): + kk = 2*k + sigma_s[i:i+2,kk:kk+2] = multi_i * sigma_s[i:i+2,kk:kk+2] + sigma_s[j:j+2,kk:kk+2] = multi_j * sigma_s[j:j+2,kk:kk+2] + + + for k in range(5): + if( not (k == index)): + if( not (k == obser_index)): + kk = 2*k + sigma_s[kk:kk+2,i:i+2] = sigma_s[kk:kk+2,i:i+2] * multi_i.getT() + sigma_s[kk:kk+2,j:j+2] = sigma_s[kk:kk+2,j:j+2] * multi_j.getT() + + + return [s, orinetations, sigma_s] diff --git a/CoLo-AT/localization_algos/ekf_ls_ci.py b/CoLo-AT/localization_algos/ekf_ls_ci.py new file mode 100644 index 0000000..fe39646 --- /dev/null +++ b/CoLo-AT/localization_algos/ekf_ls_ci.py @@ -0,0 +1,137 @@ +# coding: utf-8 + +#local state CI (LS-CI) - “Decentralized multi-robot cooperative localization using covariance intersection,†L. C. Carrillo-Arce, E. D. Nerurkar, J. L. Gordillo, and S. I. Roumeliotis +import numpy as np +from numpy import matrix +from numpy import linalg +from math import cos, sin, atan2, sqrt +from localization_algo_framework import ekf_algo_framework + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + +class EKF_LS_CI(ekf_algo_framework): + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.01*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + trace_state_var = np.trace(sigma_s[i:i+2, i:i+2]) + return trace_state_var + + #def propagation_update(self, s, orinetations, sigma_s, input_data, sigma_odo, index): + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + + num_robots = int(len(s)/2) + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + i = 2*index + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + var_u_v = sigma_odo[0,0] + sigma_s[i:i+2, i:i+2] = sigma_s[i:i+2, i:i+2]+ delta_t*delta_t*rot_mtx(self_theta)*matrix([[var_u_v, 0],[0, 0]])*rot_mtx(self_theta).T + + return [s, orinetations, sigma_s] + + + #def absolute_obser_update(self, s, orinetations, sigma_s, input_data, sigma_ob, index): + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + i = 2*index + + local_s = s[i:i+2] + local_sigma = sigma_s[i:i+2,i:i+2] + + landmark_loc = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + var_dis = sigma_ob[0,0] + var_phi = sigma_ob[1,1] + + H = rot_mtx(self_theta).getT()*matrix([[-1,0],[0,-1]], dtype=float) + + local_s = s[i:i+2] + local_sigma = sigma_s[i:i+2,i:i+2] + + landmark_loc = np.matrix(landmark_loc).getT() + z = np.matrix([meas_range*cos(bearing), meas_range*sin(bearing)]).getT() # actual measurement + delta_x = float(landmark_loc[0] - s.item(i,0)) + delta_y = float(landmark_loc[1] - s.item(i+1,0)) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) # shifted to robot frame + + + + + sigma_z = rot_mtx(bearing) * sigma_ob * rot_mtx(bearing).getT() + sigma_invention = H * local_sigma * H.getT() + sigma_z + kalman_gain = local_sigma*H.getT()*sigma_invention.getI() + + s[i:i+2] = local_s + kalman_gain*(z - z_hat) + + sigma_s[i:i+2,i:i+2] = local_sigma - kalman_gain*H*local_sigma + + return [s, orinetations, sigma_s] + + + #def relative_obser_update(self, s, orinetations, sigma_s, input_data, sigma_ob, index): + def relative_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + #i obser j + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + obser_index = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + i = index * 2 + j = obser_index * 2 + + H_ij = np.zeros((2,2*num_robots)) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + + H = rot_mtx(self_theta).getT()*H_ij + + dis = meas_range + phi = bearing + + z = matrix([[dis*cos(phi)],[dis*sin(phi)]]) + + hat_j = z + s[i:i+2] + + sigma_i = sigma_s[i:i+2,i:i+2] + sigma_j = sigma_s[j:j+2,j:j+2] + + e = 0.5 + + sigma_j_next_inv = e*sigma_j.getI() + (1-e)*sigma_i.getI() + + s[j:j+2] = sigma_j_next_inv.getI()*(e*sigma_j.getI()*s[j:j+2] + (1-e)*sigma_i.getI()*hat_j) + sigma_s[j:j+2,j:j+2] = sigma_j_next_inv.getI() + return [s, orinetations, sigma_s] + + + diff --git a/CoLo-AT/localization_algos/gs_ci_bound.py b/CoLo-AT/localization_algos/gs_ci_bound.py new file mode 100644 index 0000000..74e482c --- /dev/null +++ b/CoLo-AT/localization_algos/gs_ci_bound.py @@ -0,0 +1,141 @@ +import numpy as np +from numpy import matrix +from math import cos, sin, atan2, sqrt + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + +class gs_ci_bound(): + def __init__(self, algo_name): + self.algo_name = algo_name + self.d_max = 4.5 # max measurement distance + self.d_var = 0.2 + self.bearing_var = 0.2 + self.var_v = 0.5 + + def state_veriance_init(self, num_robots): + return 0.01*np.matrix(np.identity(2*num_robots), dtype = float) + + def algo_update(self, robot_data, update_type, sensor_data): + print 'in th algo update' + #return [s, orinetations, sigma_s] + [s, odo_freq, th_sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + + if update_type == 'propagation update': + print 'th bound propagation' + return self.propagation_update(s, th_sigma_s, sensor_covariance, index, odo_freq) + elif update_type == 'landmark observation update': + return self.absolute_obser_update(s, th_sigma_s, index) + elif update_type == 'relative observation update': + obser_index = measurement_data[0] + return self.relative_obser_update(s, th_sigma_s, index, obser_index) + elif update_type == 'communication': + return self.communication(s, th_sigma_s, index, measurement_data) + else: + print "invalid update" + + + def calculate_trace_state_variance(self, state_variance, robot_index): + #j = robot_index*2 + #return np.trace(state_variance[j:j+1, j:j+1]) + return np.trace(state_variance) + + def propagation_update(self, s, th_sigma_s, sigma_odo, index, odo_freq): + num_robots = len(s)/2 + i = 2*index + delta_t = 1/odo_freq + + for j in range(num_robots): + jj = 2*j + + if j==index: + th_sigma_s[jj:jj+2, jj:jj+2] += sigma_odo[0,0]*np.identity(2)*delta_t*delta_t + else: + #var_v = pow(2*self.d_max, 2)/12 + var_v = self.var_v + th_sigma_s[jj:jj+2, jj:jj+2] += var_v*np.identity(2)*delta_t*delta_t + print 'bound' + print np.trace(state_variance) + return th_sigma_s + + + def absolute_obser_update(self, s, th_sigma_s, index): + num_robots = len(s)/2 + i = 2*index + H_i = np.matrix(np.zeros((2,2*num_robots))) + H_i[0, i] = -1 + H_i[1, i+1] = -1 + + d_max = self.d_max + var_dis = self.d_var + var_phi = self.bearing_var + + #sigma_th_z = np.matrix(max(sigma_d, d_max*d_max*sigma_bearing)*np.identity(2)) #sigme_Ri + #th_sigma_s = (th_sigma_s.getI()+H_i.getT()*sigma_th_z.getI()*H_i).getI() + + sigma_th_z = np.matrix(max(var_dis, d_max*d_max*var_phi)*np.identity(2)) + th_sigma_s = (th_sigma_s.getI() + H_i.getT() * sigma_th_z.getI() * H_i).getI() + + return th_sigma_s + + + def relative_obser_update(self, s, th_sigma_s, index, obser_index): + #i obser j + + i = 2*index + j = obser_index * 2 + + num_robots = len(s)/2 + + H_ij = np.matrix(np.zeros((2,2*num_robots))) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + + d_max = self.d_max + var_dis = self.d_var + var_phi = self.bearing_var + + sigma_th_z = np.matrix(max(var_dis, d_max*d_max*var_phi)*np.identity(2)) + th_sigma_s = (th_sigma_s.getI() + H_ij.getT() * sigma_th_z.getI() * H_ij).getI() + return th_sigma_s + + + def communication(self, s, th_sigma_s, index, measurement_data): + + e = 0.5 + ''' + sender_th_sigma_s = measurement_data + rec_th_sigma_s = th_sigma_s + sig_inv = e*rec_th_sigma_s.getI() + (1-e)*sender_th_sigma_s.getI() + th_sigma_s = sig_inv.getI() + + ''' + ''' + i = 1*2 + j = 2*2 + + num_robots = len(s)/2 + + H_ij = np.matrix(np.zeros((2,2*num_robots))) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + + + d_max = self.d_max + sigma_d = self.d_var + sigma_bearing = self.bearing_var + + sigma_th_z = np.matrix(max(sigma_d, d_max*d_max*sigma_bearing)*np.identity(2)) #sigme_Ri + sig_inv = e*th_sigma_s.getI() + (1-e)*(th_sigma_s.getI()+H_ij.getT()*sigma_th_z.getI()*H_ij) + th_sigma_s = sig_inv.getI() + ''' + + comm_robot_th_sigma = measurement_data + th_sigma_s = ( e*th_sigma_s.getI() + (1-e)*comm_robot_th_sigma.getI()).getI() # from TK's gs-ci + + return th_sigma_s \ No newline at end of file diff --git a/CoLo-AT/localization_algos/localization_algo_framework.py b/CoLo-AT/localization_algos/localization_algo_framework.py new file mode 100644 index 0000000..4acfe68 --- /dev/null +++ b/CoLo-AT/localization_algos/localization_algo_framework.py @@ -0,0 +1,44 @@ +import numpy as np + +class ekf_algo_framework(): + """this is the framework with all possible functions for localization algorithms""" + def __init__(self, algo_name): + self.algo_name = algo_name + + def get_name(self): + return self.algo_name + + def state_variance_init(self, num_robots): + raise Exception("Failed to define state variance!") + + def calculate_trace_state_variance(self, robot_data): + raise Exception("Failed to define trace of state variance!") + + def algo_update(self, robot_data, update_type, sensor_data): + if update_type == 'propagation': + #print 'algo propagation update' + return self.propagation_update(robot_data, sensor_data) + elif update_type == 'landmark observation': + return self.absolute_obser_update(robot_data, sensor_data) + elif update_type == 'relative observation': + return self.relative_obser_update(robot_data, sensor_data) + elif update_type == 'communication': + return self.communication(robot_data, sensor_data) + else: + print("invalid update") + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + return [s, orinetations, sigma_s] + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + return [s, orinetations, sigma_s] + + def relative_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + return [s, orinetations, sigma_s] + + def communication(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + return [s, orinetations, sigma_s] \ No newline at end of file diff --git a/CoLo-AT/localization_algos/simple_ekf.py b/CoLo-AT/localization_algos/simple_ekf.py new file mode 100644 index 0000000..f56a96c --- /dev/null +++ b/CoLo-AT/localization_algos/simple_ekf.py @@ -0,0 +1,100 @@ +import numpy as np +import math +from math import cos, sin, atan2, sqrt, pi +from numpy import dot, arctan +from numpy.linalg import inv +import scipy.linalg as linalg +import sys +#import parameters +from localization_algo_framework import ekf_algo_framework +#from sympy import * + +def rot_mtx(theta): + return np.matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class Simple_EKF(ekf_algo_framework): + + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_init(self): + return 0.01*np.matrix(np.identity(2), dtype = float) + + def state_variance_init(self, num_robots): + return 0.01*np.matrix(np.identity(2), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + trace_state_var = np.trace(sigma_s) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + num_robots = int(len(s)/2) + + delta_t = measurement_data[0] + if delta_t < 0: + sys.exit('delta_t: '+ str(delta_t)) + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + i = 2*index + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + Q = sigma_odo + P = sigma_s + + W = delta_t*rot_mtx(self_theta) + P = P + W*Q*W.getT() # A is identity matrix + sigma_s = P + return [s, orinetations, sigma_s] + + + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + landmark_loc = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + i = 2*index + P = sigma_s + R = sigma_ob + z = np.matrix([meas_range,bearing]).getT() + lx = landmark_loc[0] + ly = landmark_loc[1] + x = s[i,0] + y = s[i+1,0] + + z_hat_0 = sqrt((lx-x)*(lx-x)+(ly-y)*(ly-y)) + z_hat_1 = (atan2((ly-y), (lx-x))-self_theta)%pi + if abs(z_hat_1-pi) < abs(z_hat_1): + z_hat_1 = z_hat_1-pi + + z_hat = np.matrix([z_hat_0, z_hat_1]).getT() + + h11 = (-lx + x)/sqrt((lx - x)**2 + (ly - y)**2) + h12 = (-ly + y)/sqrt((lx - x)**2 + (ly - y)**2) + h21 = -(-ly + y)/((lx - x)**2 + (ly - y)**2) + h22 = -(lx - x)/((lx - x)**2 + (ly - y)**2) + + + H = np.matrix([[h11, h12],[h21, h22]]) + sigma_invention = H * P * H.getT() + R # V is a identity matrix + K = P*H.getT()*sigma_invention.getI() + s[i:i+2, 0] = s[i:i+2, 0] + K*(z - z_hat) + P = P - K*H*P + + sigma_s = P + + return [s, orinetations, sigma_s] \ No newline at end of file diff --git a/CoLo-AT/localization_algos/under_developing_algos/centralized_ekf2.py b/CoLo-AT/localization_algos/under_developing_algos/centralized_ekf2.py new file mode 100644 index 0000000..06db657 --- /dev/null +++ b/CoLo-AT/localization_algos/under_developing_algos/centralized_ekf2.py @@ -0,0 +1,158 @@ +import numpy as np +import math +from math import cos, sin, atan2, sqrt, pi +from numpy import dot +import scipy.linalg as linalg +#import parameters +from localization_algo_framework import ekf_algo_framework + +def rot_mtx(theta): + return np.matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class Centralized_EKF2(ekf_algo_framework): + + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.01*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + trace_state_var = np.trace(sigma_s[i:i+2, i:i+2]) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + num_robots = int(len(s)/2) + + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + i = 2*index + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + Q = sigma_odo + Q[1,1] = Q[1,1]*v*v + P = sigma_s[i:i+2, i:i+2] + W = delta_t*rot_mtx(self_theta) + W[0,1] = sigma_odo[0,1]*v + W[1,1] = sigma_odo[1,1]*v + + P = P + W*Q*W.getT() # A is identity matrix + + sigma_s[i:i+2, i:i+2] = P + + return [s, orinetations, sigma_s] + + + + #def absolute_obser_update(self, s, orinetations, sigma_s, input_data, sigma_ob, index): + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + landmark_loc = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + i = 2*index + P = sigma_s + sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + R = sigma_ob + z = np.matrix([meas_range,bearing]).getT() + lx = landmark_loc[0] + ly = landmark_loc[1] + x = s[i,0] + y = s[i+1,0] + + z_hat_0 = sqrt((lx-x)*(lx-x)+(ly-y)*(ly-y)) + z_hat_1 = (atan2((ly-y), (lx-x))-self_theta)%pi + if abs(z_hat_1-pi) < abs(z_hat_1): + z_hat_1 = z_hat_1-pi + + z_hat = np.matrix([z_hat_0, z_hat_1]).getT() + + + H = np.matrix(np.zeros((2,2*num_robots))) + h11 = (-lx + x)/sqrt((lx - x)**2 + (ly - y)**2) + h12 = (-ly + y)/sqrt((lx - x)**2 + (ly - y)**2) + h21 = -(-ly + y)/((lx - x)**2 + (ly - y)**2) + h22 = -(lx - x)/((lx - x)**2 + (ly - y)**2) + H[0,i] = h11 + H[0,i+1] = h12 + H[1,i] = h21 + H[1,i+1] = h22 + + + sigma_invention = H * P * H.getT() + R + kalman_gain = P*H.getT()*sigma_invention.getI() + s = s + kalman_gain*(z - z_hat) + P = P - kalman_gain*H*P + sigma_s = P + + return [s, orinetations, sigma_s] + + + + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + obser_index = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + i = 2*index + P = sigma_s + sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + R = sigma_ob + z = np.matrix([meas_range,bearing]).getT() + j = obser_index * 2 + + x_i = s[i,0] + y_i = s[i+1,0] + x_j = s[j,0] + y_j = s[j+1,0] + + z_hat_0 = sqrt((x_j-x_i)*(x_j-x_i)+(y_j-y_i)*(y_j-y_i)) + z_hat_1 = (atan2((y_j-y_i), (x_j-x_i))-self_theta)%pi + if abs(z_hat_1-pi) < abs(z_hat_1): + z_hat_1 = z_hat_1-pi + + z_hat = np.matrix([z_hat_0, z_hat_1]).getT() + + H = np.matrix(np.zeros((2,2*num_robots))) + H[0,i] = (x_i - x_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[0,i+1] = (y_i - y_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,i] = -(y_i - y_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,i+1] = -(-x_i + x_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + + H[0,j] = (-x_i + x_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[0,j+1] = (-y_i + y_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,j] = (y_i - y_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,j+1] = (-x_i + x_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + + sigma_invention = H * P * H.getT() + R + kalman_gain = P*H.getT()*sigma_invention.getI() + s = s + kalman_gain*(z - z_hat) + P = P - kalman_gain*H*P + sigma_s = P + + + return [s, orinetations, sigma_s] diff --git a/CoLo-AT/localization_algos/under_developing_algos/ekf_gs_ci2.py b/CoLo-AT/localization_algos/under_developing_algos/ekf_gs_ci2.py new file mode 100644 index 0000000..0c3d51d --- /dev/null +++ b/CoLo-AT/localization_algos/under_developing_algos/ekf_gs_ci2.py @@ -0,0 +1,146 @@ +import numpy as np +from numpy import matrix +from math import cos, sin, atan2, sqrt +from localization_algo_framework import ekf_algo_framework + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class EKF_GS_CI2(ekf_algo_framework): + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.1*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + trace_state_var = np.trace(sigma_s[i:i+2, i:i+2]) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + + var_v = 0.1 # variance of the velocity + i = 2*index + num_robots = int(len(s)/2) + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + Q = sigma_odo + Q[1,1] = Q[1,1]*v*v + W = delta_t*rot_mtx(self_theta) + + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + for j in range(num_robots): + jj = 2*j + if j==index: + #print(np.matmul(sigma_odo,rot_mtx(self_theta).getT())) + sigma_s[jj:jj+2, jj:jj+2] += delta_t*delta_t*rot_mtx(self_theta)*Q*rot_mtx(self_theta).getT() + else: + sigma_s[jj:jj+2, jj:jj+2] += delta_t*delta_t*var_v*np.identity(2) + + return [s, orinetations, sigma_s] + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + + sigma_ob = sensor_covariance + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + landmark_loc = measurement_data[0] + dis = measurement_data[1] + phi = measurement_data[2] + + i = 2*index + H_i = np.matrix(np.zeros((2,2*num_robots)), dtype = float) + H_i[0, i] = -1 + H_i[1, i+1] = -1 + H = rot_mtx(self_theta).getT()*H_i + + + #z_hat= rot_mtx(self_theta).getT() * (landmark_loc + H_i*s) + delta_x = landmark_loc[0] - s.item(i,0) + delta_y = landmark_loc[1] - s.item(i+1,0) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) + z = matrix([dis*cos(phi), dis*sin(phi)]).getT() + + sigma_ob[1,1] = sigma_ob[1,1]*dis*dis + sigma_z = rot_mtx(phi) * sigma_ob * rot_mtx(phi).getT() + + sigma_invention = H * sigma_s * H.getT() + sigma_z + kalman_gain = sigma_s*H.getT()*sigma_invention.getI() + + s = s + kalman_gain*(z - z_hat) + sigma_s = sigma_s - kalman_gain*H*sigma_s + + return [s, orinetations, sigma_s] + + + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + i = index * 2 + obser_index = measurement_data[0] + dis = measurement_data[1] + phi = measurement_data[2] + j = obser_index * 2 + + z = matrix([dis*cos(phi), dis*sin(phi)]).getT() + + H_ij = np.zeros((2,2*num_robots)) + H_ij[0, i] = -1 + H_ij[1, i+1] = -1 + H_ij[0, j] = 1 + H_ij[1, j+1] = 1 + H = rot_mtx(self_theta).getT()*H_ij + + #z_hat = H * s + #sigma_ob[1,1] = sigma_ob[1,1]*meas_range*meas_range + + delta_x = s.item(j,0) - s.item(i,0) + delta_y = s.item(j+1,0) - s.item(i+1,0) + z_hat = rot_mtx(self_theta).getT()*(np.matrix([delta_x, delta_y]).getT()) + + sigma_ob[1,1] = sigma_ob[1,1]*dis*dis + sigma_z = rot_mtx(phi)*sigma_ob*rot_mtx(phi).getT() + + sigma_invention = H*sigma_s*H.getT() + sigma_z + kalman_gain = sigma_s*H.getT()*sigma_invention.getI() + + s = s + kalman_gain*(z - z_hat) + sigma_s = sigma_s - kalman_gain*H*sigma_s + + return [s, orinetations, sigma_s] + + def communication(self, robot_data, sensor_data): + + [s, orinetations, sigma_s, index] = robot_data + [comm_data, comm_variance] = sensor_data + [sender_idx, comm_robot_s, comm_robot_sigma_s]=comm_data + + e = 0.8 # (iii+1)*0.01 + #e = comm_e + + sig_inv = e*sigma_s.getI() + (1-e)*comm_robot_sigma_s.getI() + s = sig_inv.getI() * (e*sigma_s.getI()*s + (1-e)*comm_robot_sigma_s.getI()*comm_robot_s) + sigma_s = sig_inv.getI() + + return [s, orinetations, sigma_s] \ No newline at end of file diff --git a/CoLo-AT/localization_algos/under_developing_algos/ekf_ls_bda2.py b/CoLo-AT/localization_algos/under_developing_algos/ekf_ls_bda2.py new file mode 100644 index 0000000..cd0baa0 --- /dev/null +++ b/CoLo-AT/localization_algos/under_developing_algos/ekf_ls_bda2.py @@ -0,0 +1,161 @@ +# coding: utf-8 + + +#local state CI (LS-BDA) [9] - “Recursive decentralized collaborative localization for sparsely communicating robots†- L. Luft, T. Schubert, S. I. Roumeliotis, and W. Burgard, +#Local state with block diagonal approximation (BDA) algorithm +import numpy as np +from numpy import matrix +from numpy import linalg +from math import cos, sin, atan2, sqrt +from localization_algo_framework import ekf_algo_framework + + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + + +class EKF_LS_BDA2(ekf_algo_framework): + + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.01*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + trace_state_var = np.trace(sigma_s) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + + num_robots = int(len(s)/2) + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + i = 2*index + s[i,0] = s[i,0] + cos(self_theta)*v*delta_t #x + s[i+1,0] = s[i+1,0] + sin(self_theta)*v*delta_t #y + + Q = sigma_odo + P = sigma_s[i:i+2, i:i+2] + W = delta_t*rot_mtx(self_theta) + W[0,1] = sigma_odo[0,1]*v + W[1,1] = sigma_odo[1,1]*v + + P = P + W*Q*W.getT() # A is identity matrix + + sigma_s[i:i+2, i:i+2] = P + + return [s, orinetations, sigma_s] + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + i = 2*index + + local_s = s[i:i+2] + local_P = sigma_s[i:i+2,i:i+2] + + landmark_loc = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + lx = landmark_loc[0] + ly = landmark_loc[1] + x = s[i,0] + y = s[i+1,0] + + z = np.matrix([meas_range,bearing]).getT() + z_hat_0 = sqrt((lx-x)*(lx-x)+(ly-y)*(ly-y)) + z_hat_1 = (atan2((ly-y), (lx-x))-self_theta)%pi + if abs(z_hat_1-pi) < abs(z_hat_1): + z_hat_1 = z_hat_1-pi + z_hat = np.matrix([z_hat_0, z_hat_1]).getT() + + H = np.matrix(np.zeros((2,2*num_robots))) + h11 = (-lx + x)/sqrt((lx - x)**2 + (ly - y)**2) + h12 = (-ly + y)/sqrt((lx - x)**2 + (ly - y)**2) + h21 = -(-ly + y)/((lx - x)**2 + (ly - y)**2) + h22 = -(lx - x)/((lx - x)**2 + (ly - y)**2) + H[0,i] = h11 + H[0,i+1] = h12 + H[1,i] = h21 + H[1,i+1] = h22 + + sigma_invention = H * P * H.getT() + R + kalman_gain = P*H.getT()*sigma_invention.getI() + + local_s = local_s + kalman_gain*(z - z_hat) + local_P = local_P - kalman_gain*H*local_P + + s[i:i+2] = local_s + sigma_s[i:i+2,i:i+2] = local_P + + + + for rbt_idx in range(num_robots): + if(not (rbt_idx==index)): + j = 2*rbt_idx + sigma_s[i:i+2,j:j+2] = sigma_s[i:i+2,j:j+2] - kalman_gain*H*sigma_s[i:i+2,j:j+2] + + return [s, orinetations, sigma_s] + + + def relative_obser_update(self, robot_data, sensor_data): + #when robot i observes robot j + + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + obser_index = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + i = index * 2 + j = obser_index * 2 + P = sigma_s + R = sigma_ob + z = np.matrix([meas_range,bearing]).getT() + + x_i = s[i,0] + y_i = s[i+1,0] + x_j = s[j,0] + y_j = s[j+1,0] + + z_hat_0 = sqrt((x_j-x_i)*(x_j-x_i)+(y_j-y_i)*(y_j-y_i)) + z_hat_1 = (atan2((y_j-y_i), (x_j-x_i))-self_theta)%pi + if abs(z_hat_1-pi) < abs(z_hat_1): + z_hat_1 = z_hat_1-pi + + z_hat = np.matrix([z_hat_0, z_hat_1]).getT() + + H = np.matrix(np.zeros((2,2*num_robots))) + H[0,i] = (x_i - x_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[0,i+1] = (y_i - y_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,i] = -(y_i - y_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,i+1] = -(-x_i + x_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + + H[0,j] = (-x_i + x_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[0,j+1] = (-y_i + y_j)/sqrt((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,j] = (y_i - y_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + H[1,j+1] = (-x_i + x_j)/((-x_i + x_j)**2 + (-y_i + y_j)**2) + + inverse_sigma = [H] + K_i = + + return [s, orinetations, sigma_s] \ No newline at end of file diff --git a/CoLo-AT/localization_algos/under_developing_algos/ekf_ls_ci2.py b/CoLo-AT/localization_algos/under_developing_algos/ekf_ls_ci2.py new file mode 100644 index 0000000..8de4f28 --- /dev/null +++ b/CoLo-AT/localization_algos/under_developing_algos/ekf_ls_ci2.py @@ -0,0 +1,177 @@ +# coding: utf-8 + +#local state CI (LS-CI) - “Decentralized multi-robot cooperative localization using covariance intersection,†L. C. Carrillo-Arce, E. D. Nerurkar, J. L. Gordillo, and S. I. Roumeliotis +import numpy as np +from numpy import matrix +from numpy import linalg +from math import cos, sin, atan2, sqrt, pi +from localization_algo_framework import ekf_algo_framework +import scipy + + +def rot_mtx(theta): + return matrix([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]) + +class EKF_LS_CI2(ekf_algo_framework): + def __init__(self, algo_name): + ekf_algo_framework.__init__(self, algo_name) + + def state_variance_init(self, num_robots): + return 0.1*np.matrix(np.identity(2*num_robots), dtype = float) + + def calculate_trace_state_variance(self, robot_data): + [s, orinetations, sigma_s, index] = robot_data + i = 2*index + trace_state_var = np.trace(sigma_s[i:i+2, i:i+2]) + return trace_state_var + + def propagation_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_odo = sensor_covariance + num_robots = int(len(s)/2) + + delta_t = measurement_data[0] + v = measurement_data[1] + orinetations[index] = measurement_data[2] + self_theta = orinetations[index] + + i = 2*index + local_s = s[i:i+2] + local_P = sigma_s[i:i+2,i:i+2] + + local_s[0,0] = local_s[0,0] + cos(self_theta)*v*delta_t #x + local_s[1,0] = local_s[1,0] + sin(self_theta)*v*delta_t #y + + Q = sigma_odo + W = delta_t*rot_mtx(self_theta) + local_P = local_P + W*Q*W.getT() # A is identity matrix + + s[i:i+2] = local_s + sigma_s[i:i+2, i:i+2] = local_P + + return [s, orinetations, sigma_s] + + + def absolute_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + landmark_loc = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + i = 2*index + + local_s = s[i:i+2] + local_P = sigma_s[i:i+2,i:i+2] + R = sigma_ob + + z = np.matrix([meas_range,bearing]).getT() + lx = landmark_loc[0] + ly = landmark_loc[1] + x = local_s[0,0] + y = local_s[1,0] + + z_hat_0 = sqrt((lx-x)*(lx-x)+(ly-y)*(ly-y)) + z_hat_1 = (atan2((ly-y), (lx-x))-self_theta)%pi + if abs(z_hat_1-pi) < abs(z_hat_1): + z_hat_1 = z_hat_1-pi + z_hat = np.matrix([z_hat_0, z_hat_1]).getT() + + h11 = (-lx + x)/sqrt((lx - x)**2 + (ly - y)**2) + h12 = (-ly + y)/sqrt((lx - x)**2 + (ly - y)**2) + h21 = -(-ly + y)/((lx - x)**2 + (ly - y)**2) + h22 = -(lx - x)/((lx - x)**2 + (ly - y)**2) + H = np.matrix([[h11, h12],[h21, h22]]) + + sigma_invention = H * local_P * H.getT() + R # V is a identity matrix + K = local_P*H.getT()*sigma_invention.getI() + local_s = local_s + K*(z - z_hat) + local_P = local_P - K*H*local_P + + s[i:i+2] = local_s + sigma_s[i:i+2,i:i+2] = local_P + + return [s, orinetations, sigma_s] + + + def relative_obser_update(self, robot_data, sensor_data): + [s, orinetations, sigma_s, index] = robot_data + [measurement_data, sensor_covariance] = sensor_data + sigma_ob = sensor_covariance + + #a obser b + num_robots = int(len(s)/2) + self_theta = orinetations[index] + + obser_index = measurement_data[0] + meas_range = measurement_data[1] + bearing = measurement_data[2] + + a_i = index * 2 + b_i = obser_index * 2 + + R = sigma_ob + s_a = s[a_i:a_i+2] + P_a = sigma_s[a_i:a_i+2,a_i:a_i+2] + P_ab = sigma_s[a_i:a_i+2,b_i:b_i+2] + + s_b = s[b_i:b_i+2] + P_b = sigma_s[b_i:b_i+2,b_i:b_i+2] + + x_a = s_a[0,0] + y_a = s_a[1,0] + x_b = s_b[0,0] + y_b = s_b[1,0] + + z = np.matrix([meas_range,bearing]).getT() + z_hat_0 = sqrt((x_b-x_a)*(x_b-x_a)+(y_b-y_a)*(y_b-y_a)) + z_hat_1 = (atan2((y_b-y_a), (x_b-x_a))-self_theta)%pi + if abs(z_hat_1-pi) < abs(z_hat_1): + z_hat_1 = z_hat_1-pi + z_hat = np.matrix([z_hat_0, z_hat_1]).getT() + + H_a = np.matrix(np.zeros((2,2))) + H_a[0,0] = (x_a - x_b)/sqrt((-x_a + x_b)**2 + (-y_a + y_b)**2) + H_a[0,1] = (y_a - y_b)/sqrt((-x_a + x_b)**2 + (-y_a + y_b)**2) + H_a[1,0] = -(y_a - y_b)/((-x_a + x_b)**2 + (-y_a + y_b)**2) + H_a[1,1] = -(-x_a + x_b)/((-x_a + x_b)**2 + (-y_a + y_b)**2) + + H_b = np.matrix(np.zeros((2,2))) + H_b[0,0] = (-x_a + x_b)/sqrt((-x_a + x_b)**2 + (-y_a + y_b)**2) + H_b[0,1] = (-y_a + y_b)/sqrt((-x_a + x_b)**2 + (-y_a + y_b)**2) + H_b[1,0] = (y_a - y_b)/((-x_a + x_b)**2 + (-y_a + y_b)**2) + H_b[1,1] = (-x_a + x_b)/((-x_a + x_b)**2 + (-y_a + y_b)**2) + + r = z - z_hat + S = R + H_a * P_a * H_a.getT() + H_b * P_b * H_b.getT() - H_a * P_ab * H_b.getT() - H_b * P_ab * H_a.getT() + S_sqrt = np.asmatrix(scipy.linalg.sqrtm(np.matrix(S))) + + D_arr = [0]*num_robots + + D_arr[index] = (P_ab * H_b.getT() - P_a * H_a.getT())*S_sqrt.getI() + D_arr[obser_index] = (P_b * H_b.getT() - P_ab * H_a.getT())*S_sqrt.getI() + + for robot_index_j in range(num_robots): + j = robot_index_j*2 + if robot_index_j != index and robot_index_j != obser_index: + D_arr[robot_index_j] = sigma_s[j:j+2,b_i:b_i+2]*H_b.getT()*S_sqrt.getI()-sigma_s[j:j+2,a_i:a_i+2]*H_a.getT()*S_sqrt.getI() + s[j:j+2] = s[j:j+2]+D_arr[robot_index_j]*r + sigma_s[j:j+2,j:j+2] = sigma_s[j:j+2,j:j+2]-D_arr[robot_index_j]*D_arr[robot_index_j].getT() + + # error.... + + ''' + for robot_index_j in range(num_robots): + j = robot_index_j*2 + for robot_index_l in range(num_robots): + l = robot_index_l*2 + if l != j: + sigma_s[j:j+2,l:l+2] = sigma_s[j:j+2,l:l+2]-D_arr[robot_index_j]*D_arr[robot_index_l].getT() + ''' + return [s, orinetations, sigma_s] \ No newline at end of file diff --git a/CoLo-AT/requests/__init__.py b/CoLo-AT/requests/__init__.py new file mode 100755 index 0000000..b6e690f --- /dev/null +++ b/CoLo-AT/requests/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/CoLo-AT/requests/__pycache__/request_response.cpython-35.pyc b/CoLo-AT/requests/__pycache__/request_response.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e79d4a633a8d51d0b273c790f2ee29e6e9bbfe70 GIT binary patch literal 3051 zcmb_e!EW0|5FJvq#86V~#EDurL7+p?fJJS^Ns9(XP`EIHURt53dr}Vzmb-Qsh@`wr zCbkgd;vV`d{Uu)e7d>@mD5{jDIH?c{I~>lAIB(y~&a&6-dT)#8zujvB{0+6sLH!Vi z5hx_U2;c{4fwbWde751zhLMG)21tiZ4k!yQ8!)obx&gAu)@EgGptS|kWvg3R9gsKR z*!QO2dPiCXnUei9>HnIm{`V8z??353esr+^^x&IEsO&%Wyu%>RUZnb<|2i6vqagM| zL^r=|)DCf&KT#;ejCfJnFb6(DxE10N2Cs0AP^r+3ngmLEgmi?)HpmX^F32v(o2;Y5 zCde(;J&?CR-ew)0w?W=vy#w+tF0NN>{i4otWip|anWTwPVFLluMR#N#j&PW-QDjK2 z1#c`kLDV+9u~}i5rw&}=6oBAmk%B&e5n98-$)Z>lZJqv}W+F<YIxid<WI@qB)oGr{ zOe1l=J!Rt%mAZZCH_$r@v!WF%V}esvxLRnDT}%{B88tr9L~hZD<oREq+o=EZcJLyN z)nJy1!EqGl;~<ODWcPXUD$;2Zt0db!N%ihgnog9)xmRlU$21Ja(UctrCwUUmKg__) z|1Bmu4H3m)Z*QPW-b|&;3EZ1p6t2L9Mwt+V#yBXzerQd1u9Cf1`Gpqw;6-;D%z6tI z<nkpEX$^f#lL2ox@Wu-*MF$^|OqGclMVn|aL<(5b`%5uvjtgPw4;+?2mtisAJIB5~ z)Km=D$KRya)^dCc|50J+uf$Mu{$LzL<@GpR!a?P=T?4R8eC74QkvHBOnHi{+^xYbO z)eO{}7jV400NfJAssiAJ)3*4e7I*c+$t&dgKv%j`dO7u!HQeFz>_6j8j0Hem74ddi zfMmK_g|0#NX}^DllU4ecK~!G<6GXiVXCS;4AiDJWS#`<t`!ysFmI`sfbpZ}7k2&e0 zQgVXl4fDZ!ky9~4LHcSckm(0C0PmpUYChf<oBO~lHtAPmw`p0kX3(#NUv369$D!Y) z#+3xI5~A>gh*O!5N$&`8mIvc<MiU?UCJE{@dW!_rjlNBSww=C1g6d!QNKiwm3F=px zYMjd0kZ;HCI5^5*qr9_6h?Db+SUJRDD5ck&p~t>cbbr?A1bgxs_vM8{jd}<t_8}^G zsJ-NRrwrq#Ljx=_;qk_&9ezq!vn^1#sl-Di(-(e&v6V#7D$&3@k^t%z70I4o;AD9e zSliaLw}5Yc4h(%q)Be?;lGq`^bgyENw%F%5c$;->P0#D|^^*$B$K|UX<12Hm=&W6j zvae`$lrCV(79g%g85Pc#^is+cQby0~Q+AZb@yDgC8{#YTBntT(WIfWJ(E9!(Z2{z3 zq*4Fcr<cx1qvxT&QM81RX(&Xw8L0Z0Pfhc+-Oi=UpD6CLvZH)QEz3~PY}(uRdd*(z EU+C&XsQ>@~ literal 0 HcmV?d00001 diff --git a/CoLo-AT/requests/__pycache__/request_response.cpython-36.pyc b/CoLo-AT/requests/__pycache__/request_response.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7d7ac821b02e807490c880a52d3f6e990057904 GIT binary patch literal 2889 zcmb_e%Wm676eWkWL{pZnyxcko0xg09DrzgPQ8X}u!iAA`(+Wk?l~Q29a>fn=ks}Yu z)E0znl%MG@aofM>s`m^ffqKM<jZm1!<y`Wfd+vieYBv4%#mm=^YL@k{Rk>W+pU_Bu zqDfeN>t{>Yf_<<Ao3Or3k|SJ_Txn07J|lTU)JU!w*&(?uJd!;lyJGW|)$vE)`=?q4 znG|i6wExIu`^TYfw~yN2K07{qe*E1t+8jRj{gWWi-Y9+C{yQ2Bq9FD|0x`cB?M`T< zf6^qazD@9039j#yu=;KZr@v9c=-0%i@IP4nx@d?kT0PMe+q7<q9nqrI7k9*6S{ve? zxKHbrctC)6i`MV*BA02#wM>U9NoDAeQCwJwH0zW``jn=O2pZdGOt3MdndmroC-&Il zgpXz>EP7+TSGZXe%c7yxUn=8KBIIS^iXaP$#<^B`A~H?RcbG;5dbDns)gh%Q%!+y} z(=<4jg{QgZ+0{^X=qQzgGYwt}ClZ(cSh_*`|K4}ss91KVBz9j#aXtvLNG1C(lXsC; zNi36W|4ixqQ>BJd)7d+@|BDKPK{PUo-LpIi@kH89=TGyYRw1G29vpOaNl!Z4%y~K( zUKJiE|Dud@ph@A6#U9$Dy=6`hW_qCw9lEe$7;?e#*m?{4>|V##b&_e>q{aAIPFo}r zg)-w)hIZ&i3QjD0^mxT&MRCC@9xzsY+Q6!?_h6azG$MYz`5nBq64*QR#0)}vErg2l zr@{b_*Te7t11WW{Vt<wOnbxNoMj~Es*!W+`;s+J`>;11NFTnU{@Vyemy5JkPQ4wEM z%&vDETA|4eQpJkcny_!vW=vI!z`vlzSB4%cGuK&}dAPNleqKt%qr4x|;Vkg02xeM0 zK~PP;DFS5ZGJ+=FJxwZc`M3h($x8k$s4ifEZ-xz11n6NU6Q=x31f~$MUxrYUKm<Rj zSpNtK%VD_Iu&Mj0VeFR;H{j5;_}dlRtHobY>~)&xQ%Mj@&I_OOSc!aq{TAmJc`ztX zbQ1=V92$K^w=ki+^<7LTG<_cvQeN+3Ler~E=uaAHjnqw{>oL!zQU08AH5wru&M#1M zLc=_=`n99{bc^P1S`Df7UYPc~@QFgVFrh>=GV3h`lhT__92*iFQ<_hhJxlb$Q-VGj znZD{c21@BSoT3}1=zvGBNj;<a6&;q1-rlxHy9==9UB1_GHA+-}iD?g$VRs#2D5R$} zOfh*(L%umZzsex}Ec7&DdQ+|?KAg8>=o>g=K81#%1!T8k2sQq7g(1i{XXsSL@n>PE z8Pc2bBnr*{hud*<w8+r{wp($8+&`>v1i9DQDC(RG6>?stI&w>cK8^EA>6*ke|1Z23 UWqbGm{U=5DbJ_NzR;^Y4A8m9zQ~&?~ literal 0 HcmV?d00001 diff --git a/CoLo-AT/requests/request_response.py b/CoLo-AT/requests/request_response.py new file mode 100644 index 0000000..122e46a --- /dev/null +++ b/CoLo-AT/requests/request_response.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Apr 3 20:18:50 2018 + +@author: william +""" + +class Request_response: + + def __init__(self, time, idx): + #self.name = name + self.message = dict([('time', time), ('robot_index', idx), ('data', None), ('groundtruth', None)]) + self.r_r_type = None + def get_message(self): + return self.message + def get_robot_index(self): + return self.message['robot_index'] + def get_data(self): + return self.message['data'] + def get_groundtruth(self): + return self.message['groundtruth'] + def get_type(self): + return self.r_r_type + + def set_time(self, time): + self.message['time'] = time + def set_robot_idx(self, idx): + self.message['robot_index'] = idx + def set_type(self, r_r_type): + self.r_r_type = r_r_type + def set_message(self, message): + self.message = message + + +class Prop_req_resp(Request_response): + + def __init__(self, time, idx): + Request_response.__init__(self, time, idx) + Request_response.set_type(self, 'odometry') + +class Meas_req_resp(Request_response): + + def __init__(self, time, idx): #r_r_type can be landmark or relative measurement + Request_response.__init__(self, time, idx) + Request_response.set_type(self, 'measurement') + + +class Comm_req_resp(Request_response): + + def __init__(self, time, idx): + Request_response.__init__(self, time, idx) + Request_response.set_type(self, 'communication') diff --git a/CoLo-AT/robots/__init__.py b/CoLo-AT/robots/__init__.py new file mode 100755 index 0000000..b6e690f --- /dev/null +++ b/CoLo-AT/robots/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/CoLo-AT/robots/__init__.pyc b/CoLo-AT/robots/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34b8c9b2e92fd1b2952ab308250dfee2ed247e0b GIT binary patch literal 212 zcmY+8%?iRW41l}sB7#0g5o%vRM3CLY%e)Dexpf$5o6&X?J@}x$hA&{MUJS{Xf0E)g zn?9c9v0*>S$#2NQoY0bH%rJInb5`+!N{|tFLQGifzcGc3|0A3zmlw2JUcnfst*pQf zrjCG4lx_r%&T1D$hhA(Ed+n(=YO%wnHgNw8%5HE?+6dC)8Do%2frF^jvcJU%omg3H M2cy^NoseF51MuE5c>n+a literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/__init__.cpython-35.pyc b/CoLo-AT/robots/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fde83e0bb0008574e83485b2e7a81e1b926fc965 GIT binary patch literal 196 zcmWgR<>jio<r*!(z`*brh~a<<$Z`PUVm=^|0z`}qISdRTDNGE(n#?a5fr6Thw-~kj zfF#38h9VZA0GRj{r=O9Zo2p-)nUj;5n5!S0nOmBZSdy8ar|X(mmRXdamz$bbqMMdq zr0blYUyxb^lq*Zs^~q08%*m_*E7VUb%}WO9DAq5^Ps%ST){l?R%*!l^kJl@xyv1RY Ro1apelWGTYLopCD000@IHID!Q literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/__init__.cpython-36.pyc b/CoLo-AT/robots/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..968f4ea9f0609e66583b9f1a61b651c8274854be GIT binary patch literal 194 zcmXr!<>jio<r*!(z`*brh~a<<$Z`PUVjduo!jQt4!w|xd!W7J)$^4QLD5S}Fi&4uD zNHVNsC}IH$fQesm`WgATsru!aIXRh$x%$DGxurRYC7Jnox~_R;nML_|xv6<2x@q}E zy3YCe1*t_qxw2GUpZw&+oXje)LjAPTykwA$V*R50r2LX%{rLFIyv&mLc)fzkTO2mI Q`6;D2sdgYY6az5>044=BssI20 literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_centralized.cpython-35.pyc b/CoLo-AT/robots/__pycache__/robot_centralized.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2923475fb218f4636ecca0048cd1f783bbc77218 GIT binary patch literal 3327 zcmb7GOK;mo5FS2cOEUdVoG0>V(k5!_s6c@N1=1pDTI5prP#*%gX$eMLJ9H^h*`?fA zNKbB0MSn<({+V9)+LQl6Pn~ZlDzxH9Oo_wca%T72`DSN#ZGOJ})jz*||3{PPU#eXm z>yP+0PgunKcPJ&=aw^@WEw|D=+VU#hr!AkJ#Qe>pU)jy012%2If3xEsa%Z&BgRCx> zl}CJ=zgehi2z1V4x#$C(^WPWUr<gmN5uKG;ikqU(P~4)pEjl;OQ5=Zgq<Eg<1<~1H zk>VxM+Y~QTydpXquTp$L^nl`v6t9WSj+ZFDEcyb)S17(JI(Kr7XLH@IJyuzvqcj<* z_`CdhUTp50LiKw-PX!mAxF7Rv4p_W)=rvKuiYtmk1uHHcl<giBKJ7L{@`R*u*P{y@ zhix$$+sz)a;~v>)+NMdbJsE>%T`D|f0tp+3i20$zLPK=ste-`FWf$V8h>R-2G<vR5 zW4%;mww(?8p~mElb+dt;=|_c5UfIS->D<_cDWXEzxm+h4izvx6W0%vshoD3SzlKq| zliLL`3-=<OL|IRDeCr#PZtDg>%s?!#_>=T9KmJR)FY><X{+y&~67{>ANq?A1XY1c& zdx_4oK99A&o$K|-c|K5@zwN2@Z)>A=w})8|!<%l2z5Ae4!rmLo9t`$vGYpd~DZ;SD z0~>%KujRCyMd!YAm!G4X$8-Fk^6Md(xIi?fBV_-@%B$b0V5XTJ2Lylp!-$@_^b7x) z59ZdRD@^efBm^hHxWSbM@X1ClQ}2NKht+5H8Ph%f?9!zv6TdX^;XeNKa*3Y8twFmp z0%*3%I9?veiN=Oxg2o)Q$Knv8)3Pna^drDZSh9YR@M{3Gc?bk-YxO9(5>U+rh4dne zj<1*aVHep-7h!1|X>FavHYC%8^ir(Aas@dk)=9QgI$Y#-gJH?J?kqbuojZJwIwx@R zw*Q1Bu!UP#!W1S;QUc*@bR50L%^g=zi$0C7iT)9Yn`~%=|C95ivONz1yExElFC6H6 zAmf-Z8jg&_u%GWCGJs&F!L3auAJ)y@t3h2qD{MzR&jVaCqY9m53D$Fs+SV9dq28|n zx^+6BLY)hPBwb10)~rc(`ce2+l;$TmP?PT0u-rWh3mndc2U%9dL>A3dOqPIUTtB5` zeO!Zc?-V$7pB^eXE<ABdg3q#og^x8Zsf_}~8IA=xojA=MhJk(H6aIKsR#&#~I4mms z3BxX-E2+`rZRgY4@F&fF+UE!ilrEV))^Ry|$Z|JzX~!#r;nm8Rq|EVQX=5xDt)cm> zhV1qUyu7iV<OuMfunMM+j>W`9XvfFa0H7Z2O7Z4BLs)A}0WFK}4c=mV*cMgDN06Qx z7uLxR>y=e^t_*FG#p;!9moM1nr`f*@;Kz0JIVKJG<Xm$`-BYH0ocAOM?@)JbkVaYD zkMvJrKN?gk25WN~Y%|TH7)D<J+!+P9vYnjDum&c4{KzkF=g623reVT|P{Momfk)5E z^OQJ-l2+KjWtl-%iN^aclX?n;b2u7>!vXW5I*oEsqAc3EvMnt32Yj?LDl@qbg|!d( z^K>+Va!W0J9<hPJasyo-I-@%$5LWlu=q%wJgtZ@rwjFZ$kB2GrAPip)qqO{@SGiYx z72+Di4G3(3`WD1(2y8R@4#ZuEdk`H6)U+CKDS_DRHP}O$GUzyPgCJ-Jp8Wj4pJ<-g tb!KdX&m)6<jnkU-`6&9rx_k=t%)Swe<A$)!hvkI6#8?IglfaRm`#+j0-2(ss literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_centralized.cpython-36.pyc b/CoLo-AT/robots/__pycache__/robot_centralized.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..50568596f2a6182b86836bd1966d5bab0f43e051 GIT binary patch literal 3106 zcma)8OK%%D5Z;%h)x+{Lj_nvu(xgoV)K<{|1q!5vQMc%&@S!;rP*V^akyh5-heEDg zTaZsqfnNGU`g3~awI~0Do;n{_Qr3!Pdj-yr;*k6}-*Cw13k$Vx|M}yWzkJL3*D8E2 z)%U5WFGz5U+mY3=jdnVY(Qd~z+Us~fSlr?6JBzy)PN&4}msZQWq;b|^7jp7BRN1GZ zG7`efM|0WSd1ujFF84@#yu{0-OT5B;(q&%dHPRJc=MB<6U*JvBRldlVNZ0r>Um;!R zt9*@ggWu!pq!;*ozCpUlH~ALnMgD+LZR_;|kz_K6!lB?lrLWWM<(bMv-1P_&K4_E! zDyl<bWREOnjU1A8=8T*RwB5`*E>S6SY8|_4wErXOF@2RuA9@P^`y-b|RykyiTkz50 zC0uf8laLUty7rPF7P`rUEKnk2QSe$sO1qIrbS)XgOaimgPSV%qILKsps!Ky5Q>9BP z3o@bWsSIh0L6{~=FGpz?dkr#bvLNcEx@pYVNg%@@>57)8Jtd+eSptYMM3cndmRu(F zU)X+=#-jau7)4<aw_k?wATpEfexIC#GEHJyYxgLXy9a677n1r;#O{xURoh2{q>JTM zJICJM%PXw=o{7Ewnf4hAlQ3hfN((E1u-vj;wrlpby+L~T@OtX@CgZwrCO+_o?HCUK zq{^wxEMkNB`Of;4zjDr<bC-B^Hz}?+sfRh^mV*|t=8hcV)IM@vfPdIgDfBq^ul9PT z*BenZW6aye&#*2Xmq}JkRQQJR(xKs50-?kayM$;}byX0#aGx+7XfF$?*?`#s1l-YC zy-J;Nm!yMh$wd+^PcD(ti)1A;mfHqWYCF^=6Gw*9T&%!y1rcVf!=#rFxJUmhENj_o zcGKRncc=_ob3Fgy_$deA0>yApqe^~`j2G;~mMz!mzm{VloBAv`ACtoi56Ms&YUhW* z#P-h1>&3nlC#)~izF9<#p^#6E_u}*fKEe8G7TNlA+pK8zQ32=fZ4SFK^3JGDKunxw zf&+)Nz-V<0EfXIX&^)>sO(yORzyw;(TBoAIUL3Fw{If6xfh_ZB0m#$afMCGg!Qf;} zykSnsj5n45WSkC72Kuak<=G8bietJ+%=n;DOhhA5(%D89H_?oALqUxLI2$g0k5C}1 ze@>mZ1@gr9ZmR;toK=@FlS#PaJLGv`^?7@r9diW*GL_joHi^Ac!R_bt+}sOpAzzs| zx!xZ&tb*(`P+t}>J)XnId+TXn0Lk=@-kCu&vU}b+-PXtMG3Db6yhVti(hRmdq3+P- z*u{k=7`+L)Vw^OmccYtU)Ozm6FyZ1<*YXA~=vk&Wfc3hGzQR6%*s@pbVf%)iUN?HW z@7r>!ZbU)C<3Rq#;-Eh{890EmNc|`cIE=mqvRjht#CG~dLa<N$zfX-~G#LMTWB(Ha zBlp66g*OjbF}$6?%`|pKPS3lEp*r3yY|tln3nI~+FQhhI&;MiDS)blKN+c?k%#iX4 zb<gg%k>7^-7$8<SI$&el9zL1FM{&$yYY7h&9An0GjZyyQg9!BoV{ZpRl=sM0npJK= zJb*xON?c&_5yWE%+!OK%#8Zf85G@E~rvh-3%y3Uj@Kd3pFtP9W4Zr5Q=I8m|wB{PS tR#}(mDbYWZct&ZD-iU9sL(fB3ohf5+-4fb=k#Fc5tfla#@NM&R{s;Gh+iU;; literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_distributive.cpython-35.pyc b/CoLo-AT/robots/__pycache__/robot_distributive.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1900e20db14dbc6e249b365145032c41259d6c67 GIT binary patch literal 5159 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 aMMD`dv;5Gm*=I=hYz62X`>ng1&i?_ebwT+6 literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_distributive.cpython-36.pyc b/CoLo-AT/robots/__pycache__/robot_distributive.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47a8be69a6c7981177a8129559bbf71301d46d2e GIT binary patch literal 4822 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 F{{vpaLGl0q literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_parameters.cpython-35.pyc b/CoLo-AT/robots/__pycache__/robot_parameters.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74164906cd1d1220b0a92c38542c179e50aed113 GIT binary patch literal 417 zcmYLFyH3L}6un7E`W6c+Kfux<%?}__2~{kJrJETlQ@g1pJC2-3p+YQ3d_pDogD!}H zg|UCYoDDJc7nrcq7Or&9J?EZdTXMJ4X+D(0>m>ku>;5Z8vw`l^00BT6EkG8K1|S=V z4afn~1att@H5PH;Q7^qpw)V0H#Dh_<9qC(ieTLD?v#Hgde1scY8#^Bcn|H0QcJghX zVqtWD^m_5NI0^r)W4`Y4^;6iZBUj+tae-=PU_%P5#<?b~Ey-py!^kzFD4j&k%PK)w ziW+8#<A~E0C|5sT!Otw1NkM}-<D6j;jF`wd&X|n-VO%gJV?pE0pGxJQOPNrmy@L9e za)LQqRKZ}H#}jiR4V1i*SsL`WWSn4y1<j~R`^jBdKNXVXoSvC~NZT4b%d@Mt53OI& CeRbym literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_parameters.cpython-36.pyc b/CoLo-AT/robots/__pycache__/robot_parameters.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b45792f8a1629a9f208525a179c2b464f765faf0 GIT binary patch literal 397 zcmYL_y-ve06os9n>3=r_FThfXGy^Lll~BckSh|@ZGPRppvg644DO89BiAO+!H|T;G zSQz^T%-IlAUxA71w1p$x<L~<1D@#7^_1gF4=;{d}^bPeV2WSYD9)VGW5w);ITiB*H zc4!;dm`g3{JlMDn)TyXJ>todKMz8_;45F83qvZ}hg0&67Hb=wtJ9L-Z_H8%CgXnJW z_55pb82m>EVzn<;k3qkQT}f`j0yoS-3=~9%IY4Iv*^FfbyQV2hCsFgVnxH(zEptiY zNU$Z+E<9e@&&;1G$^1DNf)nYFxy%L0xQe||TyU*o$>PkLD(#&ql`sui!MqDKA%ZWe xL4TUZ6SI-}T3xFw^#>aW6QYS^8Pn+?xh<O~Qqf$nQ}YjL7p!L0?5gax^$RiEb>RR2 literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_system.cpython-35.pyc b/CoLo-AT/robots/__pycache__/robot_system.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4245e57f813a10c01fb0bbf3c3b16c617c77020c GIT binary patch literal 4050 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 GRQ?BH0Mz0D literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/__pycache__/robot_system.cpython-36.pyc b/CoLo-AT/robots/__pycache__/robot_system.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..764c3acefb5a5748df2049ab1d5b37a629ec6b64 GIT binary patch literal 3636 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/robot_centralized.py b/CoLo-AT/robots/robot_centralized.py new file mode 100755 index 0000000..24f8fc3 --- /dev/null +++ b/CoLo-AT/robots/robot_centralized.py @@ -0,0 +1,73 @@ +# coding: utf-8 +import numpy as np +import math +import os +import sys + +class CentralizedRobotSystem(): + + def __init__(self, name, dataset_labels, localization_algo): + #label can choose which robot in the dataset (1-5), 0 is default + #list index in the index of the robot in the robot_list + self.name = name + self.dataset_labels = dataset_labels #subject IDs + self.num_robots = len(dataset_labels) + self.state = np.matrix(np.zeros((2*self.num_robots,1))) + self.orientaions = np.matrix(np.zeros((self.num_robots,1))) + self.localization_algo = localization_algo + self.state_variance = 0 + + + def set_starting_state(self, start_state_arr): + for i, label in enumerate(self.dataset_labels): + self.time = start_state_arr[label][0] + self.state[2*i,0] = start_state_arr[label][1] #for x-axis + self.state[2*i+1,0] = start_state_arr[label][2] #for y-axis + self.orientaions[i, 0] = start_state_arr[label][3] #for orientation + self.state_variance = self.localization_algo.state_variance_init(self.num_robots) + + + + def set_time(self, time): + self.time = time + + def set_start_moving_times(self, start_moving_times): + self.prev_prop_times = start_moving_times + + def set_state(self, state): + self.state = state + + def set_state_var(self, sigma_s): + self.state_variance = sigma_s + + + def set_orientations(self, orientaions): + self.orientaions = orientaions + + + def get_name(self): + return self.name + + def get_robot_labels(self): + return self.dataset_labels + + def get_status(self): + return [self.state, self.orientaions, self.state_variance] + + def get_trace_state_variance(self, robot_index): + robot_data = [self.state, self.orientaions, self.state_variance, robot_index] + return self.localization_algo.calculate_trace_state_variance(robot_data) + + def load_map(self, landmark_map): + self.landmark_map = landmark_map + + def state_update(self, robot_index, update_type, sensor_data): + robot_data = [self.state, self.orientaions, self.state_variance, robot_index] + [self.state, self.orientaions, self.state_variance] = self.localization_algo.algo_update(robot_data, update_type, sensor_data) + return [self.state, self.orientaions, self.state_variance, update_type] + + + + + + diff --git a/CoLo-AT/robots/robot_centralized.pyc b/CoLo-AT/robots/robot_centralized.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8919a640757c222bf23ab03e38b3216f6eb69b1f GIT binary patch literal 4426 zcmc&%TW{P%6h5{$$!;#aK)Hk#Drk|GO9&EDC8UBX0^$Yb!FfQ0!pL1uwhq25_H0O^ z^eIR@@K5-A`~djAGxp{}0ksd^Y<zsiGxnTwzHiQ)iT+$$zW1B^ekAQ*g!=<r&DRhq z{sYNHc7sk2WjE~fNOq%6@5ydYQglH^@~g<H$alL7e1B)SfNy1g;cwf$3U$ktu1@mo z*rsvysB$|;jkCqfgaAXnz|}l~u-)YNBxerzZB84i(#^)1dirEh(gjtPBwbXcFX@sh z14;X;EK532Wku3uRaPZkQDsfiRaLG?yfa*b1*0BBcWu!wxF#oooQN1Gp(=qmD50GC z=aIOc>@TQ<Mfz|*k{d94PY1Q*mM)CL7cuDan7*7uItT3c3hWnzl}2r6A!NpwWw>Ox z0)e?j%A~OF3Y0W)Nn@SKlSejhT!cqC5Lo7zX<=$Y(7<{$CvFk9B5`$g=!n{}t*b`0 z#wE@=e!Z$Qyq;uL*|_Uy=hcW{CJs+bl8-B$RmYoyq|TCZWYtzRtFifBOmkz-7}JU& zE-#ufw9Us=VK;xt@;pn5&7G{6=KAf8ugZh0uF3+lZ|qg|##U8LY>mDHyYbCABR2P@ z<%rfao8CEpGov%!eKa|8eavM{R%Xta0rZB!l4uYNf~&zWxQqLUHZquug<}5)l*8Y} z0eFBF5brO4IF^T@Ji$NU0o0MK1Mzk81Dt3dg!+K+Vo(Ss1Z2Yft{d;P=(pXWymo0w z&kyPG^|tHhYw|5$Taf)lHE5|LAV^P&(C%#|hNp;<g$x+dV@F{@0!Gm)Ac~R83L7&# zF$X9{?qz5fG1bt;j805iD8%t9G<VgHt)202Bz5hSp~@uX;hZpkiI!n4z^>Y5<=7ke z3ZK$)32p_~gWJI!T#7y8#Y?egHkhq@4KJPA9x9vZ^N>R|1hF>JniH?-BT>8!3mRG_ z&*+b0IH~P{nbg%pztx<%=QNItp(&~Z#*vdXa{`rn$_&&C2EFsV?koGx{Pj(SQC)nY zX^Km*_0HLMpW7i_qBDNFC4MLy7m1k{YFte-zqnB_w9my=%~I#UV#MY|#cQoo?H;L{ z(1+*zVyfsa%_+oz8Jx-bTsEQV^9s|_oSf-n>M;@tD~XSxci?mm@cv&;kZp5!f{4%w ztpwT{=#!^7!%b10VK(uIQ2NR(lyNizh$A&2_}x(#7DJ(le@;-bjG~v^Z>P;Yv^uZ| z0xjk~t^R!g<)8jxUmN#W!>}uoeXTN3+;psDA#urRUl+WE4%B}m7HQU?t{>TU*PqpX z8Za#k7%LA%R;Kn)Yf#^2kvgZ?y$+)oyQkUyDf$|QPJ)}yx`Wc=JSo#6sedv>GC7x_ z?xJf>-f~grRg%)8&!Bfap_2r8#*-h>_*b5Q9y6XORZ#SvM)J^~PxM8jONSM(rZ>uN zF`<A3+5VSWWDCy|W;y{qtQNDrx_TQudKU3L#vM)k*`%>$Q`LrSin;mEDaeH0m%iS> z2W<0bMH;;y3|Sqv=MN@VV{|1L)Gp~XM>FQ;7~h~^Z5orJ@jAs#idz(KQgHRfEb`(z z6f6(o_aM&vR_#R=EHS1REic}HvKS6l2g`#<f4xC(rbXUF21QQ=IE74(Vlq&VAUK0Q h)-x%NpUfZ4QKKK8qhku#eGk#+Osh>FVl~iT_%|@b9q|AF literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/robot_distributive.py b/CoLo-AT/robots/robot_distributive.py new file mode 100755 index 0000000..2e08c15 --- /dev/null +++ b/CoLo-AT/robots/robot_distributive.py @@ -0,0 +1,132 @@ +import numpy as np +import math +import os +import sys +from robot_parameters import * + +sys.path.insert(0, 'Environmen_for_Localization_Simulation/functions/algo_EKF') +class DistributiveRobot(): + + def __init__(self, labels_set, robot_index, loc_algo): + #label can choose which robot in the dataset (1-5) + #robot index in the index of the robot in the robot_list + self.label = labels_set[robot_index] #subject ID + self.labels_set = labels_set + self.robot_index = robot_index + self.num_robots = len(labels_set) + + + self.orientaions = np.matrix(np.zeros((self.num_robots,1))) + + self.localization_algo = loc_algo # create the localization algo for the robot + + #self.th_state_variance = self.bound_algo.initialization_for_state_variance(self.num_robots) + + self.state = np.matrix(np.zeros((2*self.num_robots,1))) + self.state_variance = self.localization_algo.state_variance_init(self.num_robots) + + self.freqs = [0, 0, 0] #[f_odometery, f_observartion, f_communication] + + + def set_starting_state(self, start_state_arr, known_other_start_loc = True): + self.time = start_state_arr[self.label][0] + if known_other_start_loc: + for i, label in enumerate(self.labels_set): + self.state[2*i,0] = start_state_arr[label][1] #for x-axis + self.state[2*i+1,0] = start_state_arr[label][2] #for y-axis + self.orientaions[i, 0] = start_state_arr[label][3] #for orientation + else: + i = self.robot_index + self.state[2*i,0] = start_state_arr[self.label][1] #for x-axis + self.state[2*i+1,0] = start_state_arr[self.label][2] #for y-axis + self.orientaions[i, 0] = start_state_arr[self.label][3] #for orientation + + #self.th_state_variance = self.bound_algo.initialization_for_state_variance(self.num_robots) + self.state_variance = self.localization_algo.state_variance_init(self.num_robots) + + + def set_state(self, state): + self.state = state + + def set_state_var(self, sigma_s): + self.state_variance = sigma_s + + def set_orientations(self, orientaions): + self.orientaions = orientaions + + def set_start_time(self, time): + self.time = time + + def set_freqs(self, freqs): + self.freqs = freqs + + def get_freqs(self): + return self.freqs + + def get_name(self): + return self.name + + def get_algo_name(self): + return self.localization_algo.get_name() + + def get_status(self): + return [self.state, self.orientaions, self.state_variance] + + def get_pos(self): + return self.state[2*self.robot_index:2*self.robot_index+2] + + def get_th_state_variance(self): + return self.th_state_variance + + def get_own_orientation(self): + return self.orientaions.item(self.robot_index) + + def get_labels_set(self): + return self.labels_set + + def get_index(self): + return self.robot_index + + def get_label(self): + return self.labels_set[self.robot_index] + + def get_trace_state_variance(self): + robot_data = [self.state, self.orientaions, self.state_variance, self.robot_index] + return self.localization_algo.calculate_trace_state_variance(robot_data) + + def get_bound(self): + return self.bound_algo.calculate_trace_state_variance(self.th_state_variance, self.robot_index) + + def get_th_state_variance(self): + return self.th_state_variance + + def set_start_moving_times(self, start_moving_times): + self.prev_prop_time = start_moving_times[self.robot_index] + + def load_map(self, landmark_map): + self.landmark_map = landmark_map + + def state_update(self, update_type, sensor_data): + robot_data = [self.state, self.orientaions, self.state_variance, self.robot_index] + [self.state, self.orientaions, self.state_variance] = self.localization_algo.algo_update(robot_data, update_type, sensor_data) + return [self.state, self.orientaions, self.state_variance, update_type] + + ''' + def bound_update(self, update_type, measurement_data): + if update_type == 'propagation update' : #propagation update + v = measurement_data[1] + sigma_odo = np.matrix([[0.05, 0], [0, 0.01]]) #with respect to velocity and orientationb + sensor_covariance = [sigma_odo] + elif update_type == 'communication': + sensor_covariance = 0 + else: + #sigma_obser = np.matrix([[0.0215, 0], [0,0.01]]) #with respect to range and bearing + sigma_obser = np.matrix([[0.2, 0], [0,0.2]]) + #sensor_covariance = sigma_obser + sensor_covariance = [var_dis, var_angle] + + robot_data = [self.state, self.freqs, self.th_state_variance, self.robot_index] + sensor_data = [measurement_data, sensor_covariance] + self.th_state_variance = self.bound_algo.estimation_update(robot_data, update_type, sensor_data) + return self.th_state_variance + ''' \ No newline at end of file diff --git a/CoLo-AT/robots/robot_distributive.pyc b/CoLo-AT/robots/robot_distributive.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b333a179b26b0fb5b38fb217928739b4d7d64ced GIT binary patch literal 7181 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 Qu}B5jHRaf!33tx<7wXou2><{9 literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/robot_parameters.py b/CoLo-AT/robots/robot_parameters.py new file mode 100644 index 0000000..0f60590 --- /dev/null +++ b/CoLo-AT/robots/robot_parameters.py @@ -0,0 +1,11 @@ + +max_v = 0.25 +max_a_v = 0.05 + +var_u_v = 0.25*0.25*0.05*0.05 +var_u_theta = 0.1 + +var_v = 0.25*0.25 + +var_dis = pow(0.05,2) +var_angle = pow(2.0 / 180, 2) diff --git a/CoLo-AT/robots/robot_parameters.pyc b/CoLo-AT/robots/robot_parameters.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3c36d52994e4045a8a6aef09833bc292922f897 GIT binary patch literal 441 zcmYLFF;2uV5Zok}9Cv_d;0F|GLOy`VNpPY;G}nb9GO?4h6vvU{<luy8cm@1`22s%P z3u-#vzz0|dAFQ;qGdsJsZ0~z_djC1U%E5+*b%xoVAy9x6(Sg(fI)T&$>O$%PokBVS z<{OK8@PN%=kRzZz9N5+vXaI|F8xJZmF+P&=>CwdVhP)@-MZ@|q<8P=gt$f`~@ua-l ze>wkJA0~fRxP_D2M-b#D>-E?&VtG$g)*(07|8l)#nhYC8_u4$Qk*i_TbSQ82#7>jC ztXPNw{-G^U#!D$!yy8{GiHH|mbQRHD*3rD~xstVDwT=p@qEjgwrqJtIbRlz6@%1nm u7hRp3jW$;DT54OehA1MKW~x1EZnb&bv5>T@*opa|b_XGF0(VGv&-nqYp>ECq literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/robot_system.py b/CoLo-AT/robots/robot_system.py new file mode 100644 index 0000000..ae0849f --- /dev/null +++ b/CoLo-AT/robots/robot_system.py @@ -0,0 +1,149 @@ +import os, sys +import numpy as np + + +#sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/robots') +sys.path.append(os.path.join(os.path.dirname(__file__), ".")) +from robot_centralized import CentralizedRobotSystem +from robot_distributive import DistributiveRobot + + + + +class RobotSystem: + """ + general class for robot which can be distrbutive or centralized + """ + def __init__(self, name, robot_labels, loc_algo, bound_algo = None, distr_sys = True,): + self.name = name + self.robot_labels = robot_labels + self.num_robots = int(len(robot_labels)) + self.distr_sys = distr_sys + self.time = 0 + if distr_sys: + self.robot_sys= [] + for i, label in enumerate(self.robot_labels): + dis_robot = DistributiveRobot(robot_labels, i, loc_algo) + self.robot_sys.append(dis_robot) + # create a list of distibutive robot + print('created a team of ', len(self.robot_sys), ' distibutive robots ') + + else: + self.robot_sys = CentralizedRobotSystem(name, robot_labels, loc_algo) + print('created a centralized system for ', self.num_robots, ' robots ') + + def set_starting_state(self, start_state_arr): + if self.distr_sys: + for i, label in enumerate(self.robot_labels): + self.robot_sys[i].set_starting_state(start_state_arr) + else: + self.robot_sys.set_starting_state(start_state_arr) + + def request_data(self, time): + pass + ''' + def load_map(self, landmark_map): + if self.distr_sys: + for i, label in enumerate(self.robot_labels): + self.robot_sys[i].load_map(landmark_map) + else: + self.robot_sys.load_map(landmark_map) + ''' + ''' + def set_start_moving_times(self, start_moving_times): + if self.distr_sys: + for i, label in enumerate(self.robot_labels): + self.robot_sys[i].set_start_moving_times(start_moving_times) + else: + self.robot_sys.set_start_moving_times(start_moving_times) + ''' + def load_map(self, landmark_map): + self.landmark_map = landmark_map + def set_start_moving_times(self, start_moving_times): + self.prev_prop_times = start_moving_times + + def localization_update(self, rsp): + #message format: {'time': float, 'robot_index': int, 'data': {'time': float, 'velocity': float, 'orientation': float}, 'groundtruth': None} + message = rsp.get_message() + self.time = message['time'] + robot_index = message['robot_index'] + message_data = message['data'] + rsp_type = rsp.get_type() + + valid_update = True + + if rsp_type == 'odometry': #propogation update + update_type = 'propagation' + v = message_data['velocity'] + #sigma_odo = np.matrix([[5.075*v, 0], [0, 0.1]]) #with respect to velocity and orientation for utias datasets + sigma_odo = np.matrix([[0.01, 0], [0, 0.5]]) #with respect to velocity and orientation + sensor_covariance = sigma_odo + #delta_t = message_data['time'] - self.prev_prop_times[robot_index] + delta_t = message_data['delta_t'] + ''' + if delta_t <= 0: + print('current time: ', message_data['time'] ) + print('prev_prop_time: ', self.prev_prop_times[robot_index]) + raise Exception("Error incorrect delta_t!") + ''' + sensor_input = [delta_t, v, message_data['orientation']] + self.prev_prop_times[robot_index] = message_data['time'] + + elif rsp_type == 'measurement': + + sigma_obser = np.matrix([[0.015, 0], [0,0.01]]) #with respect to range and bearing + sensor_covariance = sigma_obser + obj_id = message_data['subject_ID'] + meas_range = message_data['measurment_range'] + bearing = message_data['bearing'] + if message_data['subject_ID'] > 5: #landmark observation + update_type = 'landmark observation' + landmark_loc = self.landmark_map.get(obj_id) + if landmark_loc != None: + sensor_input = [landmark_loc, meas_range, bearing, message_data['time'], obj_id] + valid_update = True + else: + valid_update = False + else: + update_type = 'relative observation' + if obj_id in self.robot_labels: + obser_index = self.robot_labels.index(obj_id) + valid_update = True + sensor_input = [obser_index, meas_range, bearing, message_data['time'], obj_id] + else: + valid_update = False + sensor_input = None + + elif rsp_type == 'communication': + update_type = 'communication' + obj_id = message_data['subject_ID'] + sender_idx = self.robot_labels.index(obj_id) + if self.distr_sys: + [comm_rbt_state, orientaions, comm_rbt_state_variance] = self.robot_sys[sender_idx].get_status() + else: + [comm_rbt_state, orientaions, comm_rbt_state_variance] = self.robot_sys.get_status() + sensor_input = [sender_idx, comm_rbt_state, comm_rbt_state_variance] + sensor_covariance = np.matrix([[0.01, 0], [0, 0.01]]) + else: + print('undefined message type!') + + if valid_update: + sensor_data = [sensor_input, sensor_covariance] + + if valid_update: + if self.distr_sys: + [est_states, est_orientaions, est_state_variance, update_type]= self.robot_sys[robot_index].state_update(update_type, sensor_data) + trace_sigma_s = self.robot_sys[robot_index].get_trace_state_variance() + else: + [est_states, est_orientaions, est_state_variance, update_type]= self.robot_sys.state_update(robot_index, update_type, sensor_data) + trace_sigma_s = self.robot_sys.get_trace_state_variance(robot_index) + else: + if self.distr_sys: + [est_states, est_orientaions, est_state_variance]= self.robot_sys[robot_index].get_status() + trace_sigma_s = self.robot_sys[robot_index].get_trace_state_variance() + else: + [est_states, est_orientaions, est_state_variance]= self.robot_sys.get_status() + trace_sigma_s = self.robot_sys.get_trace_state_variance(robot_index) + + robot_state = {'x_pos':est_states[2*robot_index], 'y_pos': est_states[2*robot_index+1], 'trace of state variance': trace_sigma_s, 'state variance': est_state_variance, 'update_type': update_type } + return robot_state diff --git a/CoLo-AT/robots/robot_system.pyc b/CoLo-AT/robots/robot_system.pyc new file mode 100644 index 0000000000000000000000000000000000000000..621918c1802b1bc0c429dd372643cf257501cd80 GIT binary patch literal 4903 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 literal 0 HcmV?d00001 diff --git a/CoLo-AT/robots/test_robot.py b/CoLo-AT/robots/test_robot.py new file mode 100644 index 0000000..d3f852f --- /dev/null +++ b/CoLo-AT/robots/test_robot.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sun Apr 8 16:47:50 2018 + +@author: william +""" +import sys +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/robots') +import robot_system +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/localization_algos') +import centralized_ekf +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/dataset_manager') +from existing_dataset import Dataset + +dataset_path = '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/datasets/MRCLAM_Dataset1/' +dataset_labels = [1,2,3,4,5] +testing_dataset = Dataset('testing', dataset_path, dataset_labels) +lm_map = testing_dataset.create_landmark_map() +print(lm_map) +st,staring_states,d, t_arr = testing_dataset.initialization_MRCLAMDatasets(20) + +dataset_labels = [1,2,3,4,5] +loc_algo = centralized_ekf.centralized_EKF('cen_ekf') +r = robot_system.RobotSystem('r',dataset_labels,loc_algo, None, distr_sys = False) +r.set_states(staring_states) + + diff --git a/CoLo-AT/ros_compatibility.py b/CoLo-AT/ros_compatibility.py new file mode 100644 index 0000000..d32cc35 --- /dev/null +++ b/CoLo-AT/ros_compatibility.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed Aug 15 15:45:54 2018 + +@author: william +""" + + +import os, sys +import getpass +sys.path.append(os.path.join(os.path.dirname(__file__), ".")) +from dataset_manager.existing_dataset import Dataset +from simulation_process.sim_manager import SimulationManager +from robots.robot_system import RobotSystem +from simulation_process.state_recorder import StatesRecorder +from data_analysis.data_analyzer import Analyzer +from data_analysis.realtime_plot import animate_plot +from pprint import pprint + +# load algorithms +sys.path.append(os.path.join(os.path.dirname(__file__), "localization_algos")) +from centralized_ekf import Centralized_EKF +from simple_ekf import Simple_EKF +from ekf_ls_bda import EKF_LS_BDA +from ekf_gs_bound import EKF_GS_BOUND +from ekf_gs_ci import EKF_GS_CI +from ekf_gs_sci2 import EKF_GS_SCI2 + +#dataset_path = '/home/william/catkin_ws/ros_colo_dataset/' +#dataset_path = '/home/william/UTIAS-dataset/MRCLAM_Dataset3/' +#dataset_path = '/home/william/full_tests/full_test9/' +compname = getpass.getuser() +dataset_path = "/home/"+ compname +"/full_tests/full_test_v3_6/" + +dataset_labels = [1,2,3] +duration = 300 # duration for the simulation in sec +testing_dataset = Dataset('testing') +start_time, starting_states, dataset_data, time_arr = testing_dataset.load_MRCLAMDatasets(dataset_path, dataset_labels, duration, delay_start = 0) +loc_algo = EKF_GS_SCI2('algo') +robot = RobotSystem('robot', dataset_labels, loc_algo, distr_sys = True) + +sim = SimulationManager('PE-CoLo EKF_GS_SCI2') +state_recorder = StatesRecorder('recorder',dataset_labels) +sim.sim_process_naive(dataset_labels, testing_dataset, robot, state_recorder, simple_plot = True) + + +analyzer = Analyzer('analyzer', dataset_labels) +loc_err_per_run, trace_per_run, t_arr = analyzer.calculate_loc_err_and_trace_state_variance_per_run(state_recorder, plot_graphs = True) +robot_loc_time_unit = analyzer.robot_location_at_unit_time_interval(state_recorder) +data_in_time_order = state_recorder.get_data_in_time_order() +update_in_time_order = state_recorder.get_updata_type_in_time_order() +update_type_arr = state_recorder.get_update_type_arr() +recorded_data = state_recorder.get_recorded_data() +#recorded_dataline = [time, robot_label, est_x_pos, est_y_pos, trace_state_var, gt_x_pos, gt_y_pos, loc_err] diff --git a/CoLo-AT/ros_demo.py b/CoLo-AT/ros_demo.py new file mode 100644 index 0000000..7f43535 --- /dev/null +++ b/CoLo-AT/ros_demo.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 10 17:43:58 2018 + +@author: william +""" + +import os, sys +import getpass +sys.path.append(os.path.join(os.path.dirname(__file__), ".")) +from dataset_manager.existing_dataset import Dataset +from simulation_process.sim_manager import SimulationManager +from robots.robot_system import RobotSystem +from simulation_process.state_recorder import StatesRecorder +from data_analysis.data_analyzer import Analyzer +from data_analysis.realtime_plot import animate_plot +from pprint import pprint + +# load algorithms +sys.path.append(os.path.join(os.path.dirname(__file__), "localization_algos")) +from centralized_ekf import Centralized_EKF # works +from simple_ekf import Simple_EKF +from ekf_ls_bda import EKF_LS_BDA +from ekf_gs_bound import EKF_GS_BOUND +from ekf_gs_ci2 import EKF_GS_CI2 + +#dataset_path = '/home/william/catkin_ws/ros_colo_dataset/' +#dataset_path = '/home/william/UTIAS-dataset/MRCLAM_Dataset3/' +compname = getpass.getuser() +dataset_path = "/home/"+ compname +"/full_tests/full_test_v3_2/" + +dataset_labels = [1, 2] +duration = 240 # duration for the simulation in sec +testing_dataset = Dataset('testing') +start_time, starting_states, dataset_data, time_arr = testing_dataset.load_MRCLAMDatasets(dataset_path, dataset_labels, duration, delay_start = 0) +loc_algo = Simple_EKF('algo') +robot = RobotSystem('robot', dataset_labels, loc_algo, distr_sys = True) + +sim = SimulationManager('Simple_EKF') +state_recorder = StatesRecorder('recorder',dataset_labels) +sim.sim_process_naive(dataset_labels, testing_dataset, robot, state_recorder, simple_plot = False) + + +analyzer = Analyzer('analyzer', dataset_labels) +loc_err_per_run, trace_per_run, t_arr = analyzer.calculate_loc_err_and_trace_state_variance_per_run(state_recorder, plot_graphs = False) +robot_loc_time_unit = analyzer.robot_location_at_unit_time_interval(state_recorder) + +print("Animation Start: ") +animate_plot(dataset_labels, state_recorder, analyzer, lm = testing_dataset.get_landmark_map()) diff --git a/CoLo-AT/sim_demo.py b/CoLo-AT/sim_demo.py new file mode 100644 index 0000000..61eac01 --- /dev/null +++ b/CoLo-AT/sim_demo.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 10 15:37:32 2018 + +@author: william +""" + +import os, sys +sys.path.append(os.path.join(os.path.dirname(__file__), ".")) +from dataset_manager.existing_dataset import Dataset +from simulation_process.sim_manager import SimulationManager +from robots.robot_system import RobotSystem +from simulation_process.state_recorder import StatesRecorder +from data_analysis.data_analyzer import Analyzer +from data_analysis.realtime_plot import animate_plot +from pprint import pprint + +# load algorithms +sys.path.append(os.path.join(os.path.dirname(__file__), "localization_algos")) +from centralized_ekf2 import Centralized_EKF2 +from simple_ekf import Simple_EKF +from ekf_ls_bda import EKF_LS_BDA +from ekf_gs_bound import EKF_GS_BOUND +from ekf_gs_ci2 import EKF_GS_CI2 + +#need to verify these algo +''' +from ekf_ls_ci import EKF_LS_CI +from ekf_ls_ci2 import EKF_LS_CI2 +from ekf_gs_ci import EKF_GS_CI +from ekf_gs_sci2 import EKF_GS_SCI2 + +''' + + +dataset_path = '/home/william/UTIAS-dataset/MRCLAM_Dataset3/' + +dataset_labels = [1,2,3] +duration = 200 # duration for the simulation in sec +testing_dataset = Dataset('testing') +start_time, starting_states, dataset_data, time_arr = testing_dataset.load_MRCLAMDatasets(dataset_path, dataset_labels, duration, synthetic = False) + +freqs0 = [[10, 10, 10],[1, 1, 1],[0.5, 0.5, 0.5]] +freqs1 = [[10, 10, 10],[4, 4, 4],[0.5, 0.5, 0.5]] + + + +loc_algo = EKF_GS_CI2('algo') +robot = RobotSystem('robot gs ci', dataset_labels, loc_algo, distr_sys = True) + +sim = SimulationManager('sim') +state_recorder = StatesRecorder('gs ci schedule freqs0',dataset_labels) +sim.sim_process_schedule(dataset_labels, testing_dataset, robot, state_recorder, freqs0, simple_plot = True) + + +############################################################################## +testing_dataset.dataset_reset() +robot = RobotSystem('robot gs ci', dataset_labels, loc_algo, distr_sys = True) + +sim1 = SimulationManager('sim') +state_recorder1 = StatesRecorder('gs ci schedule freq1',dataset_labels) +sim1.sim_process_schedule(dataset_labels, testing_dataset, robot, state_recorder1, freqs1, simple_plot = True) + +############################################################################## +testing_dataset.dataset_reset() +robot = RobotSystem('robot gs ci', dataset_labels, loc_algo, distr_sys = True) + +sim_n = SimulationManager('sim') +state_recorder_n = StatesRecorder('gs ci naive ',dataset_labels) +sim_n.sim_process_naive(dataset_labels, testing_dataset, robot, state_recorder_n, simple_plot = True) + +print("simulation completetd") + +############################################################################## +''' +testing_dataset.dataset_reset() +bound_algo = EKF_GS_BOUND('algo') +robot_bound = RobotSystem('robot bound', dataset_labels, bound_algo, distr_sys = True) + +sim_b = SimulationManager('sim') +state_recorder_bound = StatesRecorder('gs ci bound',dataset_labels) +sim_b.sim_process_schedule(dataset_labels, testing_dataset, robot_bound, state_recorder_bound, freqs) + + +############################################################################## +testing_dataset.dataset_reset() +cen_ekf_algo = Centralized_EKF2('algo') +robot_cen = RobotSystem('robot cen', dataset_labels, cen_ekf_algo, distr_sys = False) + +sim_c = SimulationManager('sim') +state_recorder_c= StatesRecorder('cen ekf',dataset_labels) +sim_c.sim_process_naive(dataset_labels, testing_dataset, robot_cen, state_recorder_c) + + + +############################################################################## +testing_dataset.dataset_reset() +bda_algo = EKF_LS_BDA('algo') +robot_bda = RobotSystem('robot bda', dataset_labels, bda_algo, distr_sys = False) + +sim_bda = SimulationManager('sim') +state_recorder_bda= StatesRecorder('bda',dataset_labels) +sim_bda.sim_process_naive(dataset_labels, testing_dataset, robot_bda, state_recorder_bda) +''' + + +analyzer = Analyzer('analyzer', dataset_labels) +analyzer.algos_comparison([state_recorder, state_recorder1, state_recorder_n], only_trace=['gs ci bound']) +loc_err_per_run, trace_per_run, t_arr = analyzer.calculate_loc_err_and_trace_state_variance_per_run(state_recorder) +robot_loc_time_unit = analyzer.robot_location_at_unit_time_interval(state_recorder) + +print("start animation") +animate_plot(dataset_labels, state_recorder, analyzer) diff --git a/CoLo-AT/simulation_process/.DS_Store b/CoLo-AT/simulation_process/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..06a4db51b47233e945b29897ebb19e9c21ba1621 GIT binary patch literal 6148 zcmeHKOHRZv47FhvmDtRZWv<X0M5A(o9)OWr1dA!11+&j7ISUIUc>aJ|CK4Nj5VED@ zIf?DKPihhq5${f8OSC1T22GGfsfbKhmoD6R17wXc&`cxU9q!w{66h~ZN$w4@J|OQ~ zTI4^>({YjTnawnJ-FSK$h@RhGU-pl+IMY0SYjb>P`!9Pfwhc8H2nK?IU?3RyaRzW_ zi!@h;(FX&;KrryhfSeBrO)xtaLp?gsX$b(7XS51*sU^fGIcCRVh!qH%E6`loOAI!5 z%qO?Yj>XX2iM{w>-}$3>Vci|^lbRD}!{~#7U|`L_r46@o|KH%3sTTQbmly>D!N5Ob zfHz&=?eI~4x1N2T+_ed9k0v5^MHC41)gu4{IY+K_(bkjbu*;6cP@>4Zx&z}OpoByh I4EzEE?+Pt1)c^nh literal 0 HcmV?d00001 diff --git a/CoLo-AT/simulation_process/__init__.py b/CoLo-AT/simulation_process/__init__.py new file mode 100644 index 0000000..b6e690f --- /dev/null +++ b/CoLo-AT/simulation_process/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/CoLo-AT/simulation_process/__pycache__/__init__.cpython-35.pyc b/CoLo-AT/simulation_process/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f0f986567d17783310f451baffb6572a4c29fd9 GIT binary patch literal 208 zcmWgR<>jio<r*!(z`*brh~a<<$Z`PUVm=^|0z`}qISdRTDNGE(n#?a5fr6Thw-~kj zfF#38h9VZA0GRldrJs?Xo2p-)nUj;5n5!S0nOmBZSdy8ar|X(mmRXdamz$bbqMMdq zr0blYUyxb^lq*Zs^~q08%*m_*E7VUb%}WO9DAq5A>y9rd%1=%$F4m8a&&<m#iI3MS WsJz8tlbfGXnv-e=a!)Z3GXMbfc{-&4 literal 0 HcmV?d00001 diff --git a/CoLo-AT/simulation_process/__pycache__/__init__.cpython-36.pyc b/CoLo-AT/simulation_process/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d0372df15aae7b98875fd6917b810441fb19ca4 GIT binary patch literal 206 zcmXr!<>jio<r*!(z`*brh~a<<$Z`PUVjduo!jQt4!w|xd!W7J)$^4QLD5S}Fi&4uD zNHVNsC}IH$fQesO`WgATsru!aIXRh$x%$DGxurRYC7Jnox~_R;nML_|xv6<2x@q}E zy3YCe1*t_qxw2GUpZw&+oXje)LjAPTykwA$V*O&c?)ZYD{N&W)V*U8|%)HE!_;|g7 V%3B;Zx%nxjIjMFa_Y?y$0{{aqI=}z` literal 0 HcmV?d00001 diff --git a/CoLo-AT/simulation_process/__pycache__/sim_manager.cpython-35.pyc b/CoLo-AT/simulation_process/__pycache__/sim_manager.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b79a7a4b5bb36b2e46ded786be1a2c770c2d019d GIT binary patch literal 4267 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 B_V54z literal 0 HcmV?d00001 diff --git a/CoLo-AT/simulation_process/__pycache__/sim_manager.cpython-36.pyc b/CoLo-AT/simulation_process/__pycache__/sim_manager.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cfd0e6ece49a18042367124c5337d035c92bd4c GIT binary patch literal 3882 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 F{4cT<|2zNy literal 0 HcmV?d00001 diff --git a/CoLo-AT/simulation_process/__pycache__/state_recorder.cpython-35.pyc b/CoLo-AT/simulation_process/__pycache__/state_recorder.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6866b0b74fece4e734a2117774892407b77ea342 GIT binary patch literal 5019 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 Cm2T?* literal 0 HcmV?d00001 diff --git a/CoLo-AT/simulation_process/__pycache__/state_recorder.cpython-36.pyc b/CoLo-AT/simulation_process/__pycache__/state_recorder.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8bd85f9ab45ec39fe2de3ed7f2669cf30395c845 GIT binary patch literal 4620 zcma)A&2QVt73a4oQXjTs$FcLV+(ovifVI85MYnB`CMn#sU0~OT*g#OFE<tN(nOaJe zhg8-UXrO@8V|s7@fEK;?)IXuu_B5wrdnk;(^wdL7{k<Wj$X|d(@V&>GH*em|ysy#s z>UHPQe}DJtPxFfMFJ<OufPRKI-3MR_Q)8vAO02atiS@P~>OG@ph8mzHVI{OrRi>S4 zr>a_vs<x}()?=sdw%xL=)~mN0KUbK+%r^=%PqlWFsoP4+I>TJb*4SNN-{9flC`_}o zr3xcG<XMNhCO;j-GrTDW2&H0BN^R>*WBMDVZ4{#0CbL)t-xjl36}ZA2<^tQS#_GUT z)?iIwht08hV3#ehTfjB8$d-WX>^55lZm@f7g{{6(q3B&GdS5iQvmgu87hxyiEac;5 zmUPmLM}w}npKxz84$^ch=!YFrm3}5(+S5(E>2CmXHCKEk*8tT>0o1w#bqS5k%$1&c zN<5bAtw?A~SUq}@IYs|ZmEDhjrJd*}294`!x$#($RAoxpQ>seT;V)j|WUvTztK|w~ z03}6(1zC`WnI8vxVVsIOFV@9;>JSSA{b=B4Q9tzMg2l>cC|k4RVR)fSkHdj*2BW^u zlf5KMg&QXwKjhpGI2ZF74?3ZrM%{kkr?ROzD~oulAx4KBJKQpH{9(M$Y412~qEI7Y zN<IIq@C7vdZ@6)g^uvv>qd1O&{>FCHAH_iyC4;r+gVzyH2K{i5t>IYKHj`vXVx!mL z+80SDh@-J&+}IxtIy55PNT;LyAx}DCiY7X0zuXeOK0Fq-k0nQ$@7FPZdJjNRt?5%M zsYTV1&v^N~v8+!<cQhJ_pM$rGR~pA(K^*-hqvM1D;DG;#1I7`<VDuF@;)*mDrk)sO zi?*Vim?aI46N?!q74+lab3He6E3ZgsckPoZq{3<QDmf@<lVr|(Tg5lS%(A~y_E*Yp zyX-g1?`jWDO!Q%`G%IV1t60IA1hl~J+UC7)zxizSsnD@$Er&PISRAE;t>u|CD_%jX zu!7+*958MXi%XzJfVP?202ti_5)C>NIGZoeCgpR)fDon#gKSioNB%HLg?TK|G96YF z#C~ad@;qM$TvSTK6!Yf{K8^;VG_3;MBDo9X9#Y-uwD-|o9{!@*Pz|+)$H21)JXb#B z_qWeQiuKEKI<!^vBTTO}1KI){Q0b|v+_07^mw!pOE_6HZ!XIIDD$Ps1q`_tGX_TUU zq<xked;wi@wWpjaFg~3O4<?5YO9t3e?~u{yOd4FK<r*_qlvDMjB5707Hd-x=ssdMl zogAhK>;i-1q(;V=Q%gNFV5IIHrGSe{Zs#?8Nw}yiljH`BxQ>21ujX!E%NsD~W?p6X zR|@}IX0j^!p%-{HRYCl8$Sl$B<V|YH8_fO6<o}uJsTDnFk*h3C+Uix%UYNfPTFQas zYF>w{yz6ty??%b%mfsWCs+Hezyo|W@E#b<Li0Hw>BYqb<E!-|oMgx}dQFg#7lyI`E z@v^j4FWL8`iF+{DC>V4?;mTkc`V@Gjr;V+h&%b>B$Q!$Zu<OZTk37CaLK;s#@%kQ& z+(Yzz<hAOU4W`mZR13NxzeDqz`*9Lv(!4ksj4+2tW0~|vzJdnncvpF3Yp!rc9l3h4 zFsZDllrxBGxm;E*R_kU6?rG*1{wc}AN1GRYvsh;!*D37oWC&5kh;l1sD&X&tq8<TC z2{V3MD?Gah6d$86{R}`+Z9EOt*2rgxrpHkqYKxi;&jk%kEj67u3U40Yz2M8UvTx?a z6y>h*;@cCyJfBW?Naxa%KfEyi)gx}Ei43P#$CLXccQz-VOZ_ir6#D22g{~cVGrcJ8 zU9&^;q}RDf-Ja3KyF!<9%+qwMV-&qI%6T9%#0_}3mLtZYenoxsTa=UglvokjP%CLg zQfui#8w`bs8YMWEF458pAFwBeE^JvOf#Z@TlJ=9%UCf$NO{1vy)Jt|X%Xzb1qg;8- zt~E*8Oa&Iu)TKc^xMI&{SZ_8rrRZzsUXm-hSn#nK4IW;hK^Y3(Rfsp!gQ|pU^teTO z%mhv<JG(Pld~k&p7uba|wV!k4+5==svL9qg4H!1WC<jsg(0a(0$XvRlbWjGY%m624 zDihc`;+X{+<rNA&hC;7`vQ6pPIqp%&n>w-%<ux0HpOM?Qaa($;L$V>;t&8oM!_dYm znOlrGRkPZJx~rTTDARuSQi0SugM7%*dkt3PE4|lbMW)kxbIfH+tnrqzrUBj}8yeu9 zlcNmq&X*MN-Y$8y-aK8P-csIGdJCs0X4oRUXL)P9<ZUJ#-k1%Ld%R!}#K&orp8XwX zaP|*?vHgPX3f_kdCnyU!Q#OpN)9f`~eV)R7WWnyS@O4yB$ZQE8S9VbLy-Ih-){8H< zU-fs#ZU;qw$h|n+&tx+EH)g@_pHEww&>>Vb_V$t^KTCY1)dPrF-XS}^oN>oC$@WNi zeY>zp?^XZTpYC@5@O%25J;fc>I!K2Yz0=a<Wc)d%I!E6U`Y_IfwI6jyJQQ|18fH-z zBcBJ1`RQnH7$+Hjf?@nAfoYM<e~eFI$nNhFsi&hpr`v+4QY~3Xafm#Uxll;@xS*{# z?4qC+&2k1@xL9wLX1G-yBwtU;X@{hjl5}V&41iB0{B))apH|uYF{yYV)4I4i4dc)! zSv~ZpRD)8YZOB^?rBk{Q-NEx6+2UvoP2P}zk%YDJ>IE;H5x51j_zA?d=IHW8msZ~w zj_>yqHo}~~sQLckD2U6Ritpn>?)!WZWBB_7J|OUY0#pF-9}xH<0ovc0jeka;za;Q( zeUhSU0H?G;u{K==uu<#Vb9U1<?1#24AEUsM54xJT#}1GAkH9Q6TuAivIK^28DD|kc z5=JkH2BN|uF7M%3+I}RLGgtoqfpnJ+aW4&p0n0xqDztf!w99d{hubJo!YVNT98%@v cS7|To$Hjg<LCjK8irXl5^anVZn(FBP2M9)bz5oCK literal 0 HcmV?d00001 diff --git a/CoLo-AT/simulation_process/data_generation.py b/CoLo-AT/simulation_process/data_generation.py new file mode 100644 index 0000000..033695b --- /dev/null +++ b/CoLo-AT/simulation_process/data_generation.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Feb 13 16:11:36 2018 + +@author: william +""" + +class DataGenerator(): + def init_(self): + pass + + def within_map(self, loc): + ''' + For runtime self_generated data, + Parameters: + loc: array, shape = (2,1) + robot's location for [x, y] + Return: Boolean + True if within the map, False if not + ''' + center_point = [0,0] + if sqrt(pow(loc[0]-center_point[0], 2)+pow(loc[1]-center_point[1], 2)) > d_max: + return False + else: + return True + def generate_propgation_data(self, current_loc, current_orientation): + + ''' + To generate propagtion data randomly so that it will run within predefined map *assuming orientation is perfect + Parameters: + current_loc: array, shape = (2,1) + robot's current location for [x, y] + current_orientation: float + robot's current orientation in radian + Return array, shape = (2,1) + ''' + [meas_v, meas_a_v] = [random.uniform(-max_v,max_v), random.uniform(-max_a_v, max_a_v)] + actual_v = meas_v + random.normal(0, sqrt(var_u_v)) + pre_update_position = [current_loc[0] + cos(current_orientation)*actual_v*delta_t, current_loc[1] + sin(current_orientation)*actual_v*delta_t] + + while(not within_map(pre_update_position)): + [meas_v, meas_a_v] = [random.uniform(-max_v,max_v), random.uniform(-max_a_v, max_a_v)] + actual_v = meas_v + random.normal(0, sqrt(var_u_v)) + pre_update_position = [current_loc[0] + cos(current_orientation)*actual_v*delta_t, current_loc[1] + sin(current_orientation)*actual_v*delta_t] + + orientation = current_orientation + meas_a_v*delta_t + actual_loc = pre_update_position + return [actual_v, meas_v, orientation, actual_loc] + + def generate_measurement_data(self, observer_loc, observee_loc, observer_orientation): + delta_x = observer_loc[0] - observee_loc[0] + delta_y = observer_loc[1] - observee_loc[1] + dis = sqrt(delta_y*delta_y + delta_x*delta_x) + random.normal(0, sqrt(var_dis)) + bearing = atan2(delta_y, delta_x) + random.normal(0, sqrt(var_angle)) - observer_orientation + return [dis, bearing] diff --git a/CoLo-AT/simulation_process/old_code/estimation_process_centralized.py b/CoLo-AT/simulation_process/old_code/estimation_process_centralized.py new file mode 100755 index 0000000..8958800 --- /dev/null +++ b/CoLo-AT/simulation_process/old_code/estimation_process_centralized.py @@ -0,0 +1,162 @@ +import numpy as np +import numpy.matlib +import math +import os +import sys +import random +from numpy import linalg as LA + +sys.path.insert(0, 'Environmen_for_Localization_Simulation/functions/algo_EKF') + +import class_centralized_system + +def is_pos_def(x): + return np.all(np.linalg.eigvals(x) > 0) + +def find_min_match_dataline(loc_dic, datas): + + min_index = min(loc_dic, key=lambda k: loc_dic[k][1]) + min_loc = loc_dic[min_index][0] + return [min_index, min_loc] + +def update_loc_dic(robot_index, loc_dic, datas): + next_loc = loc_dic[robot_index][0] + 1 #next location if possible in the data file + try: + loc_dic[robot_index] = [next_loc, datas[robot_index][next_loc]['time']] + except IndexError: + #print 'delect the robot from request list' + del loc_dic[robot_index] + + #return next_loc + return 1 + +def estimation_process_centralized(landmark_map, start_time, start_state_arr, measurement_data, odometry_data, centralized_system, duration, robots_valid_lm_obser, comm_fail_rate): + + algo_name = centralized_system.get_algo_name() + dataset_labels = centralized_system.get_robot_labels() + general_estimation_file_name = 'est' + algo_name + + print("Estimation process Start: "+algo_name) + + num_rela_obser = 0 + + robots_invalid_lm_obser = list(set(dataset_labels) - set(robots_valid_lm_obser)) + + est_result_file_arr = [] + for i, robot_label in enumerate(dataset_labels): #text files to keep track of the robots' paths + estimation_file_name = general_estimation_file_name+'%d' %robot_label + file="/Results_files/estimation_results/"+estimation_file_name+".txt" + path=os.getcwd()+file + est_result_file = open(path, "w") + est_result_file_arr.append(est_result_file) + + num_robots = len(dataset_labels) + est_result_array = [[] for i in range(num_robots)] + + # use loc dicrionary to keep track of the location(which line)in the data files + odo_req_loc_dic = {} + meas_req_loc_dic = {} + + #feeding initialization info into each robot and request array + #req_loc_dic= {robot_index: [loc, time]} + + for i in range(num_robots): + start_loc = 1 + odo_req_loc_dic[i] = [start_loc, odometry_data[i][start_loc]['time']] + start_loc = 0 + meas_req_loc_dic[i] = [start_loc, measurement_data[i][start_loc]['time']] + + + # recording starting state + #[s, orinetations, sigma_s] = centralized_system.get_status() + for i in range(num_robots): + sigma_s_trace = centralized_system.get_trace_state_variance(i) + est_result_file_arr[i].write(str(start_time)+ '\t'+ str(start_state_arr[i][0]) + '\t' + str(start_state_arr[i][1]) + '\t' +str(sigma_s_trace) + '\n') + est_result = {'time':start_time, 'x_pos':start_state_arr[i][0], 'y_pos':start_state_arr[i][1], 'sigma_s_trace':sigma_s_trace} + est_result_array[i].append(est_result) + + t = start_time + while t < start_time + duration and len(odo_req_loc_dic) != 0 and len(meas_req_loc_dic) != 0: + [odo_index, odo_loc] = find_min_match_dataline(odo_req_loc_dic, odometry_data) + odo_time = odometry_data[odo_index][odo_loc]['time'] + [meas_index, meas_loc] = find_min_match_dataline(meas_req_loc_dic, measurement_data) + meas_time = measurement_data[meas_index][meas_loc]['time'] + + if odo_time <= meas_time: + #propagtion update + t = odo_time + delta_t = odometry_data[odo_index][odo_loc]['time'] - odometry_data[odo_index][odo_loc-1]['time'] #look the the previous like to find time interval + velocity = odometry_data[odo_index][odo_loc]['velocity'] + orientation = odometry_data[odo_index][odo_loc]['orientation'] + propagation_data = [delta_t, velocity, orientation] + [s, orinetations, sigma_s] = centralized_system.state_update('propagation update', propagation_data, odo_index) + + + #recording datas + j = odo_index * 2 + robot_pos = s[j:j+2,0] + sigma_s_trace = centralized_system.get_trace_state_variance(odo_index) + + est_result_file_arr[odo_index].write(str(t)+ '\t'+ str(robot_pos.item(0,0)) + '\t' + str(robot_pos.item(1,0)) + '\t' +str(sigma_s_trace) + '\n') + est_result = {'time':t, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace} + est_result_array[odo_index].append(est_result) + + update_loc_dic(odo_index, odo_req_loc_dic, odometry_data) + + else: + pass + #measurement update + t = meas_time + subject_ID = measurement_data[meas_index][meas_loc]['subject_ID'] + measurment_range = measurement_data[meas_index][meas_loc]['measurment_range'] + bearing = measurement_data[meas_index][meas_loc]['bearing'] + + if int(subject_ID) > 5: + pass + #landmark observation + if meas_index+1 in robots_valid_lm_obser: + landmark_loc = landmark_map[subject_ID] + landmark_measeurement_data = [landmark_loc, measurment_range, bearing] + + [s, orinetations, sigma_s] = centralized_system.state_update('landmark observation update', landmark_measeurement_data, meas_index) + + #recording datas + j = meas_index * 2 + robot_pos = s[j:j+2,0] + sigma_s_trace = centralized_system.get_trace_state_variance(meas_index) + + est_result_file_arr[meas_index].write(str(t)+ '\t'+ str(robot_pos.item(0,0)) + '\t' + str(robot_pos.item(1,0)) + '\t' +str(sigma_s_trace) + ' obser\n') + est_result = {'time':t, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace} + est_result_array[meas_index].append(est_result) + + else: + #relative observation + + obser_index = int(subject_ID)-1 + relative_measeurement_data = [obser_index, measurment_range, bearing] + + if ((algo_name == 'LS-Cen') or ((meas_index+1 in robots_invalid_lm_obser) and (obser_index+1 in robots_valid_lm_obser) and (np.random.uniform() > comm_fail_rate))): + [s, orinetations, sigma_s] = centralized_system.state_update('relative observation update', relative_measeurement_data, meas_index) + + #recording datas + j = meas_index * 2 + robot_pos = s[j:j+2,0] + sigma_s_trace = centralized_system.get_trace_state_variance(meas_index) + + est_result_file_arr[meas_index].write(str(t)+ '\t'+ str(robot_pos.item(0,0)) + '\t' + str(robot_pos.item(1,0)) + '\t' +str(sigma_s_trace) + ' obser\n') + est_result = {'time':t, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace} + est_result_array[meas_index].append(est_result) + num_rela_obser +=1 + + + else: + pass + + update_loc_dic(meas_index, meas_req_loc_dic, measurement_data) + + for j in range(num_robots): + est_result_file_arr[j].close() + + print ("Estimation Process Finished # of relative observations: " + str(num_rela_obser)) + + return est_result_array \ No newline at end of file diff --git a/CoLo-AT/simulation_process/old_code/estimation_process_cont_multirobot.py b/CoLo-AT/simulation_process/old_code/estimation_process_cont_multirobot.py new file mode 100755 index 0000000..26d3aff --- /dev/null +++ b/CoLo-AT/simulation_process/old_code/estimation_process_cont_multirobot.py @@ -0,0 +1,201 @@ + +import numpy as np +import numpy.matlib +import math +import os +import sys +#from numpy import linalg as LA +from random import randint + +sys.path.insert(0, 'Environmen_for_Localization_Simulation/functions/algo_EKF') + +class global_time(): + """docstring for """ + def __init__(self, start_time, robot_list): + self.all_possible_freqs = np.array([[round(f, 3) for f in robot.get_freqs()] for robot in robot_list]) + self.all_possible_next_time = np.array([[round(start_time+1/f, 3) for f in robot.get_freqs()] for robot in robot_list]) + def get_time(self): + self.least_index = np.unravel_index(np.argmin(self.all_possible_next_time), self.all_possible_next_time.shape) + return [self.least_index, self.all_possible_next_time[self.least_index]] #[index, time] + def get_all_freqs(self): + return self.all_possible_freqs + def time_update(self): + self.all_possible_next_time[self.least_index] = self.all_possible_next_time[self.least_index] + 1/self.all_possible_freqs[self.least_index] + + +def find_nearest_time_idx_on_data_array(data_array, start_idx, time_target): + """only for increasing order array""" + i = start_idx + if data_array[i].get('time') < time_target: + while data_array[i].get('time') < time_target: + i = i+1 + if data_array[i].get('time')-time_target < time_target-data_array[i-1].get('time'): + return i + else: + return i-1 + else: + return i + +def get_robot_actual_loc(groundtruth_data, groundtruth_indices, robot_index, current_time): + """find the actual location at a given time from groudtruth data""" + gt_index = find_nearest_time_idx_on_data_array(groundtruth_data[robot_index], groundtruth_indices[robot_index], current_time) #find the index on odometry data with closest time + robot_pos = [groundtruth_data[robot_index][gt_index].get('x_pos'), groundtruth_data[robot_index][gt_index].get('y_pos'), groundtruth_data[robot_index][gt_index].get('orientation')] + groundtruth_indices[robot_index] = gt_index + return [robot_pos, groundtruth_indices] + +def generate_observation_data(observer_pos, observee_pos, measurement_deviation): + [x_1, y_1, thera_1] = observer_pos + [x_2, y_2, thera_2] = observee_pos + distance = math.sqrt((x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2)) + np.random.normal(0, measurement_deviation) + bearing = math.atan2((y_2-y_1),(x_2-x_1)) - thera_1 + np.random.normal(0, measurement_deviation) + return[distance, bearing] + + +def estimation_process_cont_multirobot(landmark_map, start_time, start_state_arr, measurement_data, odometry_data, groundtruth_data, robot_list, duration, robots_valid_lm_obser, comm_fail_rate): + print landmark_map + algo_name = robot_list[0].get_algo_name() + dataset_labels = robot_list[0].get_labels_set() + general_estimation_file_name = 'est' + algo_name + + + print("Estimation process Start: "+algo_name) + num_comm = 0 + + robots_invalid_lm_obser = list(set(dataset_labels) - set(robots_valid_lm_obser)) + + num_robot = len(robot_list) + odometry_indices = np.zeros(num_robot, dtype = np.int) # bookkeeping a pointer for each robot for odometry data for easier searching + groundtruth_indices = np.zeros(num_robot, dtype = np.int) + + est_result_array = [[] for i in range(num_robot)] + + + for i, robot in enumerate(robot_list): + robot_freq = [20,5,1] + robot.set_freqs(robot_freq) + print robot_freq + + #sigma_s_trace = robot.get_trace_state_variance() + #est_result = {'time':start_time, 'x_pos':start_state_arr[i][0], 'y_pos':start_state_arr[i][1], 'sigma_s_trace':sigma_s_trace} + #est_result_array[i].append(est_result) + #start_time = 0 + envir_time = global_time(start_time, robot_list) + all_possible_freqs = envir_time.get_all_freqs() + [current_index, current_time] = envir_time.get_time() + + print 'current_index' + print current_index + + measurment_range_arr = [] + measurment_range = 0 + measurement_deviation = 0.2 + while current_time < start_time + duration: + robot_index = current_index[0] # determind which robot to perform opertations + if current_index[1] == 0: #odometry update + pass + + od_index = find_nearest_time_idx_on_data_array(odometry_data[robot_index], odometry_indices[robot_index], current_time) #find the index on odometry data with closest time + odometry_indices[robot_index] = od_index + delta_t = 1/all_possible_freqs[robot_index][0] # time interval = 1/freq_odometry + velocity = odometry_data[robot_index][od_index].get('velocity') + orientation = odometry_data[robot_index][od_index].get('orientation') + + propagation_data = [delta_t, velocity, orientation] + [s, orinetations, sigma_s] = robot_list[robot_index].state_update('propagation update', propagation_data) + th_sigma_s = robot_list[robot_index].bound_update('propagation update', propagation_data) + + + #record the data + robot_pos = robot_list[robot_index].get_pos() + sigma_s_trace = robot_list[robot_index].get_trace_state_variance() + bound = robot_list[robot_index].get_bound() + est_result = {'time':current_time, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace, 'bound': bound} + #print est_result + est_result_array[robot_index].append(est_result) + + ''' + if robot_index == 0: + print(str(robot_index) + ' prop') + print est_result + ''' + + elif current_index[1] == 1: #observation update + [self_loc, groundtruth_indices] = get_robot_actual_loc(groundtruth_data, groundtruth_indices, robot_index, current_time) + + #landmark observation + subject_ID = '15' + if robot_index == 0: + landmark_loc = landmark_map[subject_ID] + landmark_loc = [landmark_loc[0], landmark_loc[1], 0] #landmark doesn't have orinataion here + [measurment_range, bearing] = generate_observation_data(self_loc, landmark_loc, measurement_deviation) + landmark_measeurement_data = [landmark_loc, measurment_range, bearing] + [s, orinetations, sigma_s] = robot_list[robot_index].state_update('landmark observation update', landmark_measeurement_data) + th_sigma_s = robot_list[robot_index].bound_update('landmark observation update', landmark_measeurement_data) + ''' + #relative observation + target_robot_index = 1 + [target_loc, groundtruth_indices] = get_robot_actual_loc(groundtruth_data, groundtruth_indices, target_robot_index, current_time) + [measurment_range, bearing] = generate_observation_data(self_loc, target_loc, measurement_deviation) + relative_measeurement_data = [target_robot_index, measurment_range, bearing] + [s, orinetations, sigma_s] = robot_list[robot_index].state_update('relative observation update', relative_measeurement_data) + th_sigma_s = robot_list[robot_index].bound_update('relative observation update', relative_measeurement_data) + ''' + #record the data + robot_pos = robot_list[robot_index].get_pos() + sigma_s_trace = robot_list[robot_index].get_trace_state_variance() + bound = robot_list[robot_index].get_bound() + est_result = {'time':current_time, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace, 'bound': bound} + est_result_array[robot_index].append(est_result) + + #print(str(robot_index) + ' obser') + #print est_result + ''' + else: #communication update + pass + + if robot_index == 1: # 2nd robot + target_robot_index = 2 + [target_loc, groundtruth_indices] = get_robot_actual_loc(groundtruth_data, groundtruth_indices, target_robot_index, current_time) + [measurment_range, bearing] = generate_observation_data(self_loc, target_loc, measurement_deviation) + relative_measeurement_data = [target_robot_index, measurment_range, bearing] + [s, orinetations, sigma_s] = robot_list[robot_index].state_update('relative observation update', relative_measeurement_data) + th_sigma_s = robot_list[robot_index].bound_update('relative observation update', relative_measeurement_data) + + #record the data + robot_pos = robot_list[robot_index].get_pos() + sigma_s_trace = robot_list[robot_index].get_trace_state_variance() + bound = robot_list[robot_index].get_bound() + est_result = {'time':current_time, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace, 'bound': bound} + est_result_array[robot_index].append(est_result) + + + sender_robot_index = robot_index + receiver_index = 0 + [sender_s, sender_orientaions, sender_state_variance] = robot_list[sender_robot_index].get_status() + comm_data = [sender_s, sender_state_variance] + [s, orinetations, sigma_s] = robot_list[receiver_index].state_update('communication', comm_data) + comm_data = robot_list[sender_robot_index].get_th_state_variance() + th_sigma_s = robot_list[receiver_index].bound_update('communication', comm_data) + + #record the data + robot_pos = robot_list[receiver_index].get_pos() + sigma_s_trace = robot_list[receiver_index].get_trace_state_variance() + bound = robot_list[receiver_index].get_bound() + est_result = {'time':current_time, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace, 'bound': bound} + est_result_array[receiver_index].append(est_result) + + #print(str(robot_index) + ' comm') + #print est_result + ''' + measurment_range_arr.append(measurment_range) + prev_time = current_time + envir_time.time_update() + [current_index, current_time] = envir_time.get_time() + if prev_time > current_time: + print('prev: ' + str(prev_time) + '; current' + str(current_time)) + sys.exit("incorrect time handling!") + + #print ("Estimation Process Finished # of comm: " + str(num_comm)) + print 'measurment_range_arr' + print max(measurment_range_arr) + return est_result_array \ No newline at end of file diff --git a/CoLo-AT/simulation_process/old_code/estimation_process_multirobot.py b/CoLo-AT/simulation_process/old_code/estimation_process_multirobot.py new file mode 100755 index 0000000..f2c552f --- /dev/null +++ b/CoLo-AT/simulation_process/old_code/estimation_process_multirobot.py @@ -0,0 +1,175 @@ +import numpy as np +import numpy.matlib +import math +import os +import sys +from numpy import linalg as LA +from random import randint + + +sys.path.insert(0, 'Environmen_for_Localization_Simulation/functions/algo_EKF') + +def is_pos_def(x): + return np.all(np.linalg.eigvals(x) > 0) + +def find_min_match_dataline(loc_dic, datas): + min_index = min(loc_dic, key=lambda k: loc_dic[k][1]) + min_loc = loc_dic[min_index][0] + return [min_index, min_loc] + +def update_loc_dic(robot_index, loc_dic, datas): + next_loc = loc_dic[robot_index][0] + 1 #next location if possible in the data file + try: + loc_dic[robot_index] = [next_loc, datas[robot_index][next_loc]['time']] + except IndexError: + #print 'delect the robot from request list' + del loc_dic[robot_index] + + return next_loc + +def estimation_process_multirobot(landmark_map, start_time, start_state_arr, measurement_data, odometry_data, robot_list, duration, robots_valid_lm_obser, comm_fail_rate): + + algo_name = robot_list[0].get_algo_name() + dataset_labels = robot_list[0].get_labels_set() + general_estimation_file_name = 'est' + algo_name + + + print("Estimation process Start: "+algo_name) + num_comm = 0 + + robots_invalid_lm_obser = list(set(dataset_labels) - set(robots_valid_lm_obser)) + + + est_result_file_arr = [] + for i, robot in enumerate(robot_list): #text files to keep track of the robots' paths + estimation_file_name = general_estimation_file_name+'%d' %robot.get_label() + file="/Results_files/estimation_results/"+estimation_file_name+".txt" + path=os.getcwd()+file + est_result_file = open(path, "w") + est_result_file_arr.append(est_result_file) + + num_robot = len(robot_list) + est_result_array = [[] for i in range(num_robot)] + + # use loc array to keep track of the location(which line)in the data files + odo_req_loc_dic = {} + meas_req_loc_dic = {} + + #feeding initialization info into each robot and request array + #req_loc_dic= {robot_index: [loc, time]} + + for i, robot in enumerate(robot_list): + start_loc = 1 + odo_req_loc_dic[i] = [start_loc, odometry_data[i][start_loc]['time']] + start_loc = 0 + meas_req_loc_dic[i] = [start_loc, measurement_data[i][start_loc]['time']] + + #[s, orinetations, sigma_s] = robot.get_status() + sigma_s_trace = robot.get_trace_state_variance() + est_result_file_arr[i].write(str(start_time)+ '\t'+ str(start_state_arr[i][0]) + '\t' + str(start_state_arr[i][1]) + '\t' +str(sigma_s_trace) + '\n') + est_result = {'time':start_time, 'x_pos':start_state_arr[i][0], 'y_pos':start_state_arr[i][1], 'sigma_s_trace':sigma_s_trace} + est_result_array[i].append(est_result) + + + t = start_time + while t < start_time + duration and len(odo_req_loc_dic) != 0 and len(meas_req_loc_dic) != 0: + [odo_index, odo_loc] = find_min_match_dataline(odo_req_loc_dic, odometry_data) + odo_time = odometry_data[odo_index][odo_loc]['time'] + [meas_index, meas_loc] = find_min_match_dataline(meas_req_loc_dic, measurement_data) + meas_time = measurement_data[meas_index][meas_loc]['time'] + + if odo_time <= meas_time: + #propagtion update + t = odo_time + delta_t = odometry_data[odo_index][odo_loc]['time'] - odometry_data[odo_index][odo_loc-1]['time'] #look at the previous time stamp to find the time interval + velocity = odometry_data[odo_index][odo_loc]['velocity'] + orientation = odometry_data[odo_index][odo_loc]['orientation'] + propagation_data = [delta_t, velocity, orientation] + [s, orinetations, sigma_s] = robot_list[odo_index].state_update('propagation update', propagation_data) + + #recording datas + j = odo_index * 2 + robot_pos = s[j:j+2,0] + sigma_s_trace = robot_list[odo_index].get_trace_state_variance() + + est_result_file_arr[odo_index].write(str(t)+ '\t'+ str(robot_pos.item(0,0)) + '\t' + str(robot_pos.item(1,0)) + '\t' +str(sigma_s_trace) + '\n') + est_result = {'time':t, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace} + est_result_array[odo_index].append(est_result) + + update_loc_dic(odo_index, odo_req_loc_dic, odometry_data) + + else: + #measurement update + pass + + t = meas_time + measurment_range = measurement_data[meas_index][meas_loc]['measurment_range'] + subject_ID = measurement_data[meas_index][meas_loc]['subject_ID'] + bearing = measurement_data[meas_index][meas_loc]['bearing'] + + if int(subject_ID) > 5: + pass + #landmark observation + if meas_index+1 in robots_valid_lm_obser: + landmark_loc = landmark_map[subject_ID] + landmark_measeurement_data = [landmark_loc, measurment_range, bearing] + [s, orinetations, sigma_s] = robot_list[meas_index].state_update('landmark observation update', landmark_measeurement_data) + + #recording datas + j = meas_index * 2 + robot_pos = s[j:j+2,0] + sigma_s_trace = robot_list[meas_index].get_trace_state_variance() + + est_result_file_arr[meas_index].write(str(t)+ '\t'+ str(robot_pos.item(0,0)) + '\t' + str(robot_pos.item(1,0)) + '\t' +str(sigma_s_trace) + ' lm_obser\n') + est_result = {'time':t, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace} + est_result_array[meas_index].append(est_result) + + + else: + pass + #relative observation + observee_index = int(subject_ID)-1 + relative_measeurement_data = [observee_index, measurment_range, bearing] + [s, orinetations, sigma_s] = robot_list[meas_index].state_update('relative observation update', relative_measeurement_data) + + #recording datas + j = meas_index * 2 + robot_pos = s[j:j+2,0] + sigma_s_trace = robot_list[meas_index].get_trace_state_variance() + + est_result_file_arr[meas_index].write(str(t)+ '\t'+ str(robot_pos.item(0,0)) + '\t' + str(robot_pos.item(1,0)) + '\t' +str(sigma_s_trace) + ' rel_obser\n') + est_result = {'time':t, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace} + est_result_array[meas_index].append(est_result) + + + if (meas_index+1 in robots_invalid_lm_obser) and (observee_index+1 in robots_valid_lm_obser) and (np.random.uniform() > comm_fail_rate): + comm_robot_index = meas_index + sender_robot_index = observee_index + + + [sender_s, sender_orientaions, sender_state_variance] = robot_list[sender_robot_index].get_status() + comm_data = [sender_s, sender_state_variance] + + [s, orinetations, sigma_s] = robot_list[comm_robot_index].state_update('communication', comm_data) + + #recording datas + j = comm_robot_index * 2 + robot_pos = s[j:j+2,0] + sigma_s_trace = robot_list[comm_robot_index].get_trace_state_variance() + + est_result_file_arr[comm_robot_index].write(str(t)+ '\t'+ str(robot_pos.item(0,0)) + '\t' + str(robot_pos.item(1,0)) + '\t' +str(sigma_s_trace) + ' comm w/ robot' + str(meas_index+1) +'\n') + est_result = {'time':t, 'x_pos':robot_pos.item(0,0), 'y_pos':robot_pos.item(1,0), 'sigma_s_trace':sigma_s_trace} + est_result_array[comm_robot_index].append(est_result) + + num_comm+=1 + + update_loc_dic(meas_index, meas_req_loc_dic, measurement_data) + + + for j in range(len(robot_list)): + est_result_file_arr[j].close() + + + print ("Estimation Process Finished # of comm: " + str(num_comm)) + + return est_result_array \ No newline at end of file diff --git a/CoLo-AT/simulation_process/old_code/estimation_process_self_generated_data.py b/CoLo-AT/simulation_process/old_code/estimation_process_self_generated_data.py new file mode 100644 index 0000000..2b224c9 --- /dev/null +++ b/CoLo-AT/simulation_process/old_code/estimation_process_self_generated_data.py @@ -0,0 +1,148 @@ +import numpy as np +from numpy import random +from numpy import matrix +from math import cos, sin, atan2, sqrt +import os +import sys +from robot_parameters import * + + +d_max = 25 +delta_t = 0.5 + + +class Landmark: + def __init__(self, index, position): + self.index = index + self.position = position + + +def within_map(loc): + center_point = [0,0] + if sqrt(pow(loc[0]-center_point[0], 2)+pow(loc[1]-center_point[1], 2)) > d_max: + return False + else: + return True + +def generate_propgation_data(current_loc, current_orientation): + # assuming orientation is perfect + [meas_v, meas_a_v] = [random.uniform(-max_v,max_v), random.uniform(-max_a_v, max_a_v)] + actual_v = meas_v + random.normal(0, sqrt(var_u_v)) + pre_update_position = [current_loc[0] + cos(current_orientation)*actual_v*delta_t, current_loc[1] + sin(current_orientation)*actual_v*delta_t] + + while(not within_map(pre_update_position)): + [meas_v, meas_a_v] = [random.uniform(-max_v,max_v), random.uniform(-max_a_v, max_a_v)] + actual_v = meas_v + random.normal(0, sqrt(var_u_v)) + pre_update_position = [current_loc[0] + cos(current_orientation)*actual_v*delta_t, current_loc[1] + sin(current_orientation)*actual_v*delta_t] + + orientation = current_orientation + meas_a_v*delta_t + actual_loc = pre_update_position + return [actual_v, meas_v, orientation, actual_loc] + +def generate_measurement_data(observer_loc, observee_loc, observer_orientation): + delta_x = observer_loc[0] - observee_loc[0] + delta_y = observer_loc[1] - observee_loc[1] + dis = sqrt(delta_y*delta_y + delta_x*delta_x) + random.normal(0, sqrt(var_dis)) + bearing = atan2(delta_y, delta_x) + random.normal(0, sqrt(var_angle)) - observer_orientation + return [dis, bearing] + +def estimation_process_multirobot_generated_data(robots_list, iteration, duration): + random.seed( 9 ) + sigma_tr_arr = [0] * duration + sigma_th_tr_arr = [0] * duration + error_arr = [0] * duration + + for i in range(iteration): + print 'iteration CSK' + print i + + initial_state = matrix([1, 1, 1, 2, 2, 1, -1, -1, 1, 3], dtype=float).T + robots_act_loc = initial_state + initial_oriantation = matrix([0, 0, 0, 0, 0], dtype=float).T + for j, robot in enumerate(robots_list): + robot.set_state(initial_state) + robot.set_orientations(initial_oriantation) + + M = 1 # number of landmark + landmarks = [None] * M + for m in range(M): + landmarks[m] = Landmark(m, matrix([0.01, 0.02], dtype=float).getT()) + + for t in range(duration): + for j, robot in enumerate(robots_list): + [act_v, meas_v, orientation, actual_loc] = generate_propgation_data(robot.get_pos(), robot.get_own_orientation()) + robots_act_loc[j:j+2] = actual_loc + propagation_data = [delta_t, meas_v, orientation] + [s, orinetations, sigma_s] = robot.state_update('propagation update', propagation_data) + #th_sigma_s = robot.bound_update('propagation update', propagation_data) + + #robot 0 observes landmark + robot_idx = 0 + [measurment_range, bearing] = generate_measurement_data(robots_list[robot_idx].get_pos(), landmarks[0].position, robots_list[robot_idx].get_own_orientation()) + landmark_measeurement_data = [landmarks[0].position, measurment_range, bearing] + [s, orinetations, sigma_s] = robots_list[robot_idx].state_update('landmark observation update', landmark_measeurement_data) + #th_sigma_s = robot.state_update('landmark observation update', landmark_measeurement_data) + + + # for robot 2, it obverses robot 0 and robot 1 + robot_idx = 2 + observee_idx = 0 + [measurment_range, bearing] = generate_measurement_data(robots_list[robot_idx].get_pos(), robots_list[observee_idx].get_pos(), robots_list[robot_idx].get_own_orientation()) + relative_measeurement_data = [observee_idx , measurment_range, bearing] + [s, orinetations, sigma_s] = robots_list[robot_idx].state_update('relative observation update', relative_measeurement_data) + #th_sigma_s = robot.state_update('relative observation update', relative_measeurement_data) + + + observee_idx = 1 + [measurment_range, bearing] = generate_measurement_data(robots_list[robot_idx].get_pos(), robots_list[observee_idx].get_pos(), robots_list[robot_idx].get_own_orientation()) + relative_measeurement_data = [observee_idx , measurment_range, bearing] + [s, orinetations, sigma_s] = robots_list[robot_idx].state_update('relative observation update', relative_measeurement_data) + #th_sigma_s = robot.bound_update('relative observation update', relative_measeurement_data) + + # for robot 3, it observes landmarks and robot 4 + robot_idx = 3 + [measurment_range, bearing] = generate_measurement_data(robots_list[robot_idx].get_pos(), landmarks[0].position, robots_list[robot_idx].get_own_orientation()) + landmark_measeurement_data = [landmarks[0].position, measurment_range, bearing] + [s, orinetations, sigma_s] = robots_list[robot_idx].state_update('landmark observation update', landmark_measeurement_data) + #th_sigma_s = robot.bound_update('landmark observation update', landmark_measeurement_data) + + observee_idx = 4 + [measurment_range, bearing] = generate_measurement_data(robots_list[robot_idx].get_pos(), robots_list[observee_idx].get_pos(), robots_list[robot_idx].get_own_orientation()) + relative_measeurement_data = [observee_idx, measurment_range, bearing] + [s, orinetations, sigma_s] = robots_list[robot_idx].state_update('relative observation update', relative_measeurement_data) + #th_sigma_s = robot.bound_update('relative observation update', relative_measeurement_data) + + # communication + #robot 2 get comm info from robot 3 + sender_idx = 3 + robot_idx = 2 + comm_data = [robots_list[sender_idx].get_status()[0], robots_list[sender_idx].get_status()[2]] + [s, orinetations, sigma_s] = robots_list[robot_idx].state_update('communication', comm_data) + th_comm_data = [robots_list[sender_idx].get_status()[0], robots_list[sender_idx].get_th_state_variance()] + #th_sigma_s = robots_list[robot_idx].bound_update('communication', comm_data) + + #robot 0 get comm info from robot 2 + sender_idx = 2 + robot_idx = 0 + comm_data = [robots_list[sender_idx].get_status()[0], robots_list[sender_idx].get_status()[2]] + [s, orinetations, sigma_s] = robots_list[robot_idx].state_update('communication', comm_data) + th_comm_data = [robots_list[sender_idx].get_status()[0], robots_list[sender_idx].get_th_state_variance()] + th_sigma_s = robots_list[robot_idx].bound_update('communication', comm_data) + + + # error calculation + s = 0 + for j, robot in enumerate(robots_list): + s += pow(robot.get_pos()[0] - robots_act_loc[j],2) + pow(robot.get_pos()[0] - robots_act_loc[j+1],2) + + s = sqrt(s*0.2) + error_arr[t] = error_arr[t] + s*(1/float(iteration)) + + # covariance error + sigma_tr_arr[t] = sigma_tr_arr[t] + sqrt(0.2*robots_list[0].get_trace_state_variance())*(1/float(iteration)) + + #sigma_th_tr_arr[t] = sigma_th_tr_arr[t] + math.sqrt(0.2*robots_list[0].get_bound)*(1/float(iteration)) + + + return [error_arr, sigma_tr_arr] + diff --git a/CoLo-AT/simulation_process/old_code/simumlation_process.py b/CoLo-AT/simulation_process/old_code/simumlation_process.py new file mode 100644 index 0000000..5667e1c --- /dev/null +++ b/CoLo-AT/simulation_process/old_code/simumlation_process.py @@ -0,0 +1,28 @@ +import numpy as np +from numpy import random +from numpy import matrix +from math import cos, sin, atan2, sqrt +import os +import sys +from robot_parameters import * + +class SimulationProcess(): + def __init__(self, name): + self.name = name + + class Scheduler(): + def __init__(self): + pass + +def estimation_process(robots_list, iteration, duration, generating_data): + + + + + + + + + + + diff --git a/CoLo-AT/simulation_process/sim_manager.py b/CoLo-AT/simulation_process/sim_manager.py new file mode 100644 index 0000000..4db0376 --- /dev/null +++ b/CoLo-AT/simulation_process/sim_manager.py @@ -0,0 +1,150 @@ +import numpy as np +import numpy.matlib +import math +import os +import sys + +#sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/requests') +sys.path.append(os.path.join(os.path.dirname(__file__), "../requests")) +import request_response +from numpy import linalg as LA +from random import randint + +class SimulationManager(): + def __init__(self, name): + self.name = name + + def sim_process_naive(self, dataset_labels, dm, robot_system, state_recorder, comm = True, simple_plot = False): + #dm: dataset manager + print('******** Simulation Process Started! ********') + print('communication: ', comm) + self.dataset_labels = dataset_labels + + start_time = dm.get_start_time() + duration = dm.get_duration() + self.time = start_time + prev_time = 0 + + #recording starting states + starting_st= dm.get_starting_states() + state_recorder.set_starting_state(starting_st) + + # + robot_system.set_starting_state(dm.get_starting_states()) + robot_system.set_start_moving_times(dm.get_start_moving_times()) + robot_system.load_map(dm.get_landmark_map()) + + state_var = [] + while self.time < start_time+duration: + #print("Current time:", self.time) + g_req= request_response.Request_response(None, None) + prev_time = self.time + valid, self.time , rsp = dm.respond(g_req, self.time) + #print(rsp.get_message()) + if self.time < prev_time: + print('Time inconsistant!') + break + if valid == False : + break + robot_state = robot_system.localization_update(rsp) + state_var.append(robot_state['state variance']) + state_recorder.record_state(rsp, robot_state) + + # communication protocall + if comm: + if rsp.get_type()=='measurement': + rbt_idx = rsp.get_robot_index() + comm_rsp = request_response.Comm_req_resp(self.time, rbt_idx) + message = comm_rsp.get_message() + sender_idx = (rbt_idx+1)%(robot_system.num_robots) + sender_id = dataset_labels[sender_idx] + message['data'] = {'subject_ID':sender_id} + message['groundtruth'] = rsp.get_groundtruth + comm_rsp.set_message(message) + + robot_state = robot_system.localization_update(comm_rsp) + state_var.append(robot_state['state variance']) + state_recorder.record_state(rsp, robot_state) + + if simple_plot: + state_recorder.simple_plot(plot_title=self.name) + + print('******** Simulation Process Finished! ********') + print('End time: ', self.time) + + + return state_var + + + def sim_process_schedule(self, dataset_labels, dm, robot_system, state_recorder, freqs, simple_plot = False): + #dm: dataset manager + print('******** Simulation Process Started! ********') + req_type_list = ['odometry', 'measurement', 'communication'] + self.dataset_labels = dataset_labels + + start_time = dm.get_start_time() + duration = dm.get_duration() + self.time = start_time + prev_time = 0 + + + #recording starting states + starting_st= dm.get_starting_states() + state_recorder.set_starting_state(starting_st) + + robot_system.set_starting_state(dm.get_starting_states()) + # due to adding data + robot_system.set_start_moving_times([start_time]*len(dataset_labels)) + robot_system.load_map(dm.get_landmark_map()) + + next_possible_time_array= [ [ start_time + 1/freq for freq in f] for f in freqs] + #print(next_possible_time_array) + while self.time < start_time+duration: + min_loc = np.argwhere(next_possible_time_array == np.min(next_possible_time_array)) + req_type_idx = min_loc[0][0] + robot_idx = min_loc[0][1] + req_type = req_type_list[req_type_idx] + req_time = next_possible_time_array[req_type_idx][robot_idx] + if req_type != 'communication': + g_req = request_response.Request_response(req_time, robot_idx) + g_req.set_type(req_type) + prev_time = self.time + valid, rsp_time , rsp = dm.respond(g_req, req_time, need_specific_time = True) + if valid == False: + print('invalid responese') + break + robot_state = robot_system.localization_update(rsp) + state_recorder.record_state(rsp, robot_state) + + else: + comm_rsp = request_response.Comm_req_resp(req_time, robot_idx) + message = comm_rsp.get_message() + obser_id = (robot_idx+1)%(robot_system.num_robots) + message['data'] = obser_id + message['groundtruth'] = rsp.get_groundtruth + comm_rsp.set_message(message) + + robot_state = robot_system.localization_update(rsp) + #state_recorder.record_state(rsp, robot_state) + + #print(req_type) + #print('time:', self.time) + #print('#########') + self.time = next_possible_time_array[req_type_idx][robot_idx] + if self.time < prev_time: + print('current time:', self.time) + print(next_possible_time_array) + sys.quit('Time inconsistant!') + + next_possible_time_array[req_type_idx][robot_idx] += 1/freqs[req_type_idx][robot_idx] + + + if simple_plot: + state_recorder.simple_plot(plot_title=self.name) + + print('******** Simulation Process Finished! ********') + #print('End time: ', self.time) + + + return self.time + diff --git a/CoLo-AT/simulation_process/state_recorder.py b/CoLo-AT/simulation_process/state_recorder.py new file mode 100644 index 0000000..559fb1d --- /dev/null +++ b/CoLo-AT/simulation_process/state_recorder.py @@ -0,0 +1,139 @@ +import numpy as np +import os, sys + +#sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/requests') +sys.path.append(os.path.join(os.path.dirname(__file__), "../requests")) +import request_response +from math import sqrt +import matplotlib.pyplot as plt + + +class StatesRecorder(): + """docstring for ClassName""" + def __init__(self, name, dataset_labels): + self.name = name + self.dataset_labels = dataset_labels + self.recorded_data = {} + self.data_in_time_order = [] + self.updata_type_in_time_order = [] + self.num_robots = len(self.dataset_labels) + self.loc_err_arr = {} + self.trace_sigma_s_arr = {} + self.updata_type_arr = {} + for i, label in enumerate(self.dataset_labels): + self.recorded_data[label]=[] + self.loc_err_arr[label]=[] + self.trace_sigma_s_arr[label]=[] + self.updata_type_arr[label]=[] + + def set_starting_state(self, stating_states): + for i, label in enumerate(self.dataset_labels): + self.start_time = stating_states[label][0] + time = 0 + x_pos = stating_states[label][1] + y_pos = stating_states[label][2] + initial_trace_state_var = 0.0001 + loc_err = 0 + recorded_dataline = [time, label, x_pos, y_pos, initial_trace_state_var, x_pos, y_pos, loc_err] + self.data_in_time_order.append(recorded_dataline) + self.recorded_data[label].append(recorded_dataline) + self.loc_err_arr[label].append(0) + self.trace_sigma_s_arr[label].append(initial_trace_state_var) + self.updata_type_arr[label].append('ini') + self.updata_type_in_time_order.append('ini') + def get_dataset_labels(self): + return self.dataset_labels + + + def record_state(self, req, robot_state): + message = req.get_message() + robot_idx = message['robot_index'] + time = message['time']-self.start_time + gt = message['groundtruth'] + #print(robot_state['x_pos']) + est_x_pos = float(robot_state['x_pos']) + est_y_pos = float(robot_state['y_pos']) + trace_state_var = robot_state['trace of state variance'] + updata_type = robot_state['update_type'] + gt_x_pos = gt['x_pos'] + gt_y_pos = gt['y_pos'] + robot_label = self.dataset_labels[robot_idx] + loc_err = sqrt((est_x_pos-gt_x_pos)*(est_x_pos-gt_x_pos)+(est_y_pos-gt_y_pos)*(est_y_pos-gt_y_pos)) + + recorded_dataline = [time, robot_label, est_x_pos, est_y_pos, trace_state_var, gt_x_pos, gt_y_pos, loc_err] + + if(trace_state_var<0): + print('TIME: ', time+self.start_time) + print(updata_type) + print('neg trace: ', recorded_dataline) + + if(loc_err >= 1): + print(updata_type) + print('>1 m loc err: ',recorded_dataline) + print(req.get_message()) + + #print(recorded_dataline) + self.data_in_time_order.append(recorded_dataline) + self.updata_type_in_time_order.append(updata_type) + self.recorded_data[robot_label].append(recorded_dataline) + self.loc_err_arr[robot_label].append(loc_err) + self.trace_sigma_s_arr[robot_label].append(trace_state_var) + self.updata_type_arr[robot_label].append(updata_type) + + + def get_data_in_time_order(self): + return self.data_in_time_order + + def get_updata_type_in_time_order(self): + return self.updata_type_in_time_order + + def get_recorded_data(self): + return self.recorded_data + + def get_time_arr(self, robot_id): + time_arr = np.array(self.recorded_data[robot_id])[:,0] + return time_arr + + def get_loc_err_arr(self): + return self.loc_err_arr + + def get_trace_sigma_s_arr(self): + return self.trace_sigma_s_arr + + def get_update_type_arr(self): + return self.updata_type_arr + + def simple_plot(self, plot_title = ''): + fig = plt.figure() + plt.suptitle(plot_title + ' Correctness analysis') + fig1 = fig.add_subplot(211) + fig2 = fig.add_subplot(212) + loc_err_arr = self.get_loc_err_arr() + trace_sigma_s_arr = self.get_trace_sigma_s_arr() + for i, label in enumerate(self.dataset_labels): + time_arr = self.get_time_arr(label) + fig1.plot(time_arr, loc_err_arr[label], label= 'Robot %d' %label) + fig2.plot(time_arr, trace_sigma_s_arr[label], label= 'Robot %d' %label) + print('Robot',label, 'loc err: ', sum(loc_err_arr[label])/len(loc_err_arr[label])) + fig1.set_title('Estimation deviation error') + fig1.set_xlabel('Time[s]') + fig1.set_ylabel('RMS[m]') + #fig1.set_ylim(0, 6) + fig1.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + + fig2.set_title('Trace of state variance') + fig2.set_xlabel('Time [s]') + fig2.set_ylabel('Sigma_s [m^2]') + #fig2.set_ylim(0, 0.08) + fig2.legend(loc='center left', bbox_to_anchor=(1, 0.5)) + + fig.subplots_adjust(hspace = 0.8) + plt.show() + + return True + + + + + + \ No newline at end of file diff --git a/CoLo-AT/simulation_process/test_recorder.py b/CoLo-AT/simulation_process/test_recorder.py new file mode 100644 index 0000000..2223fd9 --- /dev/null +++ b/CoLo-AT/simulation_process/test_recorder.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Thu Apr 5 15:24:42 2018 + +@author: william +""" + +import sys +import numpy as np +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/requests') +import request_response +sys.path.insert(0, '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/functions/dataset_manager') +from existing_dataset import Dataset +from state_recorder import StatesRecorder + +dataset_path = '/Users/william/Documents/SLAM_Simulation/Simulation-Environment-for-Cooperative-Localization/datasets/MRCLAM_Dataset1/' +dataset_labels = [1,2,3,4,5] +testing_dataset = Dataset('testing', dataset_path, dataset_labels) +lm_map = testing_dataset.create_landmark_map() +print(lm_map) +st,staring_states,d, t_arr = testing_dataset.initialization_MRCLAMDatasets(20) +sr = StatesRecorder('sr',dataset_labels) +sr.set_stating_states(staring_states) + + +print('*********************************') +g_req = request_response.Request_response(None, None) +c_t,rsp = testing_dataset.respond(g_req, st) +print(g_req.get_message()) +print(g_req.get_type()) + +robot_state = {'x_pos': 1, 'y_pos':1, 'trace of state variance': 0.1 } +sr.record_state(rsp, robot_state) + + +print('*********************************') +g_req = request_response.Request_response(None, None) +c_t,rsp = testing_dataset.respond(g_req, st) +print(g_req.get_message()) +print(g_req.get_type()) + +robot_state = {'x_pos': 2, 'y_pos':1, 'trace of state variance': 0.2 } +sr.record_state(rsp, robot_state) + +print('*********************************') +g_req = request_response.Request_response(None, None) +c_t,rsp = testing_dataset.respond(g_req, st) +print(g_req.get_message()) +print(g_req.get_type()) + +robot_state = {'x_pos': 3, 'y_pos':1, 'trace of state variance': 0.3 } +sr.record_state(rsp, robot_state) + +# +print('#############') +print(dataset_labels.index(4)) +print(sr.get_loc_err_arr(1)) +print(sr.get_trace_sigma_s_arr(1)) +print(sr.get_time_arr(1)) + +''' +r_d=sr.get_recorded_data() +r_d_a = np.array(r_d[1]) +print(r_d_a[:,0]) + +''' \ No newline at end of file diff --git a/CoLo-AT/test_simulation.py b/CoLo-AT/test_simulation.py new file mode 100644 index 0000000..8080a85 --- /dev/null +++ b/CoLo-AT/test_simulation.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sun Apr 8 17:55:06 2018 + +@author: william +""" + +import os, sys +sys.path.append(os.path.join(os.path.dirname(__file__), ".")) +from dataset_manager.existing_dataset import Dataset +from simulation_process.sim_manager import SimulationManager +from robots.robot_system import RobotSystem +from simulation_process.state_recorder import StatesRecorder +from data_analysis.data_analyzer import Analyzer +from data_analysis.realtime_plot import animate_plot +from pprint import pprint + +# load algorithms +sys.path.append(os.path.join(os.path.dirname(__file__), "localization_algos")) + +from centralized_ekf import Centralized_EKF # works +from simple_ekf import Simple_EKF +from ekf_ls_bda import EKF_LS_BDA +from ekf_ls_ci import EKF_LS_CI +from ekf_gs_bound import EKF_GS_BOUND +from ekf_gs_ci import EKF_GS_CI + +#need to verify these algo +from ekf_gs_sci2 import EKF_GS_SCI2 +from ekf_ls_ci2 import EKF_LS_CI2 +from ekf_gs_ci2 import EKF_GS_CI2 +from centralized_ekf2 import Centralized_EKF2 + + +dataset_path = '/home/william/UTIAS-dataset/MRCLAM_Dataset3/' + +dataset_labels = [1,2,3] +duration = 100 # duration for the simulation in sec +testing_dataset = Dataset('testing') +start_time, starting_states, dataset_data, time_arr = testing_dataset.load_MRCLAMDatasets(dataset_path, dataset_labels, duration) + +freqs0 = [[10, 10, 10],[1, 1, 1],[0.5, 0.5, 0.5]] +freqs1 = [[10, 10, 10],[4, 4, 4],[0.5, 0.5, 0.5]] + +loc_algo = Centralized_EKF('algo') +robot = RobotSystem('robot', dataset_labels, loc_algo, distr_sys = False) + +sim = SimulationManager('sim Centralized_EKF') +state_recorder = StatesRecorder('recorder',dataset_labels) +#sim.sim_process_schedule(dataset_labels, testing_dataset, robot, state_recorder, freqs0, simple_plot = True) +sim.sim_process_naive(dataset_labels, testing_dataset, robot, state_recorder, simple_plot = True) + +analyzer = Analyzer('analyzer', dataset_labels) +loc_err_per_run, trace_per_run, t_arr = analyzer.calculate_loc_err_and_trace_state_variance_per_run(state_recorder, plot_graphs = False) +robot_loc_time_unit = analyzer.robot_location_at_unit_time_interval(state_recorder) +data_in_time_order = state_recorder.get_data_in_time_order() +update_in_time_order = state_recorder.get_updata_type_in_time_order() + +''' +############################################################################## +testing_dataset.dataset_reset() +robot = RobotSystem('robot gs ci', dataset_labels, loc_algo, distr_sys = True) + +sim1 = SimulationManager('sim') +state_recorder1 = StatesRecorder('gs ci schedule freq1',dataset_labels) +sim1.sim_process_schedule(dataset_labels, testing_dataset, robot, state_recorder1, freqs1, simple_plot = True) + +############################################################################## +testing_dataset.dataset_reset() +robot = RobotSystem('robot gs ci', dataset_labels, loc_algo, distr_sys = True) + +sim_n = SimulationManager('sim') +state_recorder_n = StatesRecorder('gs ci naive ',dataset_labels) +sim_n.sim_process_naive(dataset_labels, testing_dataset, robot, state_recorder_n, simple_plot = True) + +analyzer = Analyzer('analyzer', dataset_labels) +analyzer.algos_comparison([state_recorder, state_recorder1, state_recorder_n], only_trace=['gs ci bound']) +print('done!') +''' +''' +sim.sim_process_naive(dataset_labels, testing_dataset, robot, state_recorder, simple_plot = True) +loc_err_per_run, trace_per_run, t_arr = analyzer.calculate_loc_err_and_trace_state_variance_per_run(state_recorder) +#robot_location_at_unit_time_interval +robot_loc_time_unit = analyzer.robot_location_at_unit_time_interval(state_recorder) + + +# simulated data +data_sim = state_recorder.get_recorded_data() +le = state_recorder.get_loc_err_arr() +ud = state_recorder.get_update_type_arr() +t_S = state_recorder.get_trace_sigma_s_arr() +ud_t = state_recorder.get_updata_type_in_time_order() +data_sim_t = state_recorder.get_data_in_time_order() +get_robot_time_func = state_recorder.get_time_arr +# le, t_S is an array of 5 elements, each element has error, state variance +# based on time stamp +# print(len(t_S[1]), len(t_S[2]), len(t_S[3]), len(t_S[4]), len(t_S[5])) +# print(data_sim) +''' + +#animate_plot(dataset_labels, state_recorder, analyzer, get_robot_time_func, le, t_S) diff --git a/CoLo-AT/verifications/.DS_Store b/CoLo-AT/verifications/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**<q8>++&mCkOWA81W14cNZ<zv;LbK1Poaz?KmsK2CSc!( z0ynLxE!0092;Krf2c+FF_Fe*7ECH>lEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0<F0fCPF1$Cyrb|F7^5{eNG?83~ZUUlGt@xh*qZDeu<Z%US-OSsOPv j)R!Z4KLME7ReXlK;d!wEw5GODWMKRea10D2@KpjYNUI8I literal 0 HcmV?d00001 -- GitLab