Giter Club home page Giter Club logo

tinyodom's Introduction

TinyOdom: Hardware-Aware Efficient Neural Inertial Navigation

overview overview

Paper

https://dl.acm.org/doi/10.1145/3534594

Summary

Deep inertial sequence learning has shown promising odometric resolution over model-based approaches for trajectory estimation in GPS-denied environments. However, existing neural inertial dead-reckoning frameworks are not suitable for real-time deployment on ultra-resource-constrained (URC) devices due to substantial memory, power, and compute bounds. Current deep inertial odometry techniques also suffer from gravity pollution, high-frequency inertial disturbances, varying sensor orientation, heading rate singularity, and failure in altitude estimation. In this paper, we introduce TinyOdom, a framework for training and deploying neural inertial models on URC hardware. TinyOdom exploits hardware and quantization-aware Bayesian neural architecture search (NAS) and a temporal convolutional network (TCN) backbone to train lightweight models targetted towards URC devices. In addition, we propose a magnetometer, physics, and velocity-centric sequence learning formulation robust to preceding inertial perturbations. We also expand 2D sequence learning to 3D using a model-free barometric g-h filter robust to inertial and environmental variations. We evaluate TinyOdom for a wide spectrum of inertial odometry applications and target hardware against competing methods. Specifically, we consider four applications: pedestrian, animal, aerial, and underwater vehicle dead-reckoning. Across different applications, TinyOdom reduces the size of neural inertial models by 31x to 134x with 2.5m to 12m error in 60 seconds, enabling the direct deployment of models on URC devices while still maintaining or exceeding the localization resolution over the state-of-the-art. The proposed barometric filter tracks altitude within ±0.1m and is robust to inertial disturbances and ambient dynamics. Finally, our ablation study shows that the introduced magnetometer, physics, and velocity-centric sequence learning formulation significantly improve localization performance even with notably lightweight models.

performance summary

Code Architecture

There are seven folders in TinyOdom:

  • OxIOD, RoNIN, AQUALOC, Gundog, and EuRoC MAV contain dataset import, model training, NAS, model evaluation and deployment code for pedestrian dead reckoning, UUV localization, animal tracking, and UAV localization for the specific datasets mentioned. We provide Jupyter notebooks for easier prototyping of odometry models. The notebooks have sufficient comments for the user.
  • Each notebook is generally divided into the following parts: 1. Data import (training, validation, test) 2. Training and NAS 3. Training the best model 4. Evaluation of best model on test set and sample plots 5. Deployment on real-hardware.
  • tinyodom_tcn has actual Tensorflow Lite Micro style C++ code that can be run on Mbed-enabled boards. You must place it in your home directory in the Mbed programs folder (e.g., home/nesl/Mbed Programs/tinyodom_tcn) if you want to run HIL NAS. Refer to the TFLM guide to understand how main.cpp works: https://www.tensorflow.org/lite/microcontrollers
  • robust_depth_filter has prototyping and deployment code for the barometric g-h filter.
  • The scripts are written to be trained on GPU. If you do not have GPU, first comment this line in each notebook: os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID", then change the next line as follows: os.environ["CUDA_VISIBLE_DEVICES"]="-1"

Required items

Citation

Please cite this as:

Swapnil Sayan Saha, Sandeep Singh Sandha, Luis Antonio Garcia, and Mani Srivastava. 2022. TinyOdom: Hardware-Aware Efficient Neural Inertial Navigation. Proc. ACM Interact. Mob. Wearable Ubiquitous Technol. 6, 2, Article 71 (July 2022), 32 pages.

Acknowledgements

We thank the Structures-Computer Interaction Laboratory at the University of California - Los Angeles for providing us with their agricultural robot to perform real-world evaluation of our framework. We also thank Jason Wu from the Networked and Embedded Systems Laboratory at the University of California - Los Angeles for aiding us in the data collection phase during the real-world setup.

The research reported in this paper was sponsored in part by: the CONIX Research Center, one of six centers in JUMP, a Semiconductor Research Corporation (SRC) program sponsored by DARPA; by the IoBT REIGN Collaborative Research Alliance funded by the Army Research Laboratory (ARL) under Cooperative Agreement W911NF-17-2-0196; by the NIH mHealth Center for Discovery, Optimization and Translation of Temporally-Precise Interventions (mDOT) under award 1P41EB028242; by the National Science Foundation (NSF) under awards # OAC-1640813 and CNS-1822935; and, by and the King Abdullah University of Science and Technology (KAUST) through its Sensor Innovation research program. The views and conclusions contained in this document are those of the authors and should not be interpreted as representing the official policies, either expressed or implied, of the ARL, DARPA, KAUST, NIH, NSF, SRC, or the U.S. Government. The U.S. Government is authorized to reproduce and distribute reprints for Government purposes notwithstanding any copyright notation here on.

tinyodom's People

Contributors

swapnilsayansaha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

tinyodom's Issues

Code Crashing in Pedometer

I am trying to work through your code and I cannot get past line 79 in data_utils.py
p = Pedometer(gx=acc_x, gy=acc_y, gz=acc_z, sr=sampling_rate)

It gives the following errors:

AssertionError Traceback (most recent call last)
File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\internals\construction.py:969, in _finalize_columns_and_data(content, columns, dtype)
968 try:
--> 969 columns = _validate_or_indexify_columns(contents, columns)
970 except AssertionError as err:
971 # GH#26429 do not raise user-facing AssertionError

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\internals\construction.py:1017, in _validate_or_indexify_columns(content, columns)
1015 if not is_mi_list and len(columns) != len(content): # pragma: no cover
1016 # caller's responsibility to check for this...
-> 1017 raise AssertionError(
1018 f"{len(columns)} columns passed, passed data had "
1019 f"{len(content)} columns"
1020 )
1021 elif is_mi_list:
1022
1023 # check if nested list column, length of each sub-list should be equal

AssertionError: 3 columns passed, passed data had 61773 columns

The above exception was the direct cause of the following exception:

ValueError Traceback (most recent call last)
Cell In[12], line 2
1 #Training Set
----> 2 X, Y_disp, Y_head, Y_pos, x0_list, y0_list, size_of_each, x_vel, y_vel, head_s, head_c, X_orig = import_oxiod_dataset(type_flag = 2,
3 useMagnetometer = True, useStepCounter = True, AugmentationCopies = 0,
4 dataset_folder = f,
5 sub_folders = ['handbag/','handheld/','pocket/','running/','slow_walking/','trolley/'],
6 sampling_rate = sampling_rate,
7 window_size = window_size, stride = stride, verbose=False)

File c:\Users\jakem\OneDrive - xonano.com\Documents\Python Scripts\TinyOdom_OxIDOD\data_utils.py:81, in import_oxiod_dataset(type_flag, useMagnetometer, useStepCounter, AugmentationCopies, dataset_folder, sub_folders, sampling_rate, window_size, stride, verbose)
78 mag_z = cur_train['Mag_Z'].to_numpy().reshape((acc_x.shape[0],1))
80 if(useStepCounter):
---> 81 p = Pedometer(gx=acc_x, gy=acc_y, gz=acc_z, sr=sampling_rate, data=None)
82 step_count, step_locations = p.get_steps()
83 loc = np.zeros(cur_train.shape[0])

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\pydometer_init_.py:54, in Pedometer.init(self, gx, gy, gz, sr, data)
52 self.sr = 1.0/secs_per_sample
53 elif gx is not None and gy is not None and gz is not None:
---> 54 self.data = pd.DataFrame([gx, gy, gz], columns=['gx','gy','gz'])
55 else:
56 raise ValueError("Must provide data, or gx/gy/gz.")

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\frame.py:746, in DataFrame.init(self, data, index, columns, dtype, copy)
744 if columns is not None:
745 columns = ensure_index(columns)
--> 746 arrays, columns, index = nested_data_to_arrays(
747 # error: Argument 3 to "nested_data_to_arrays" has incompatible
748 # type "Optional[Collection[Any]]"; expected "Optional[Index]"
749 data,
750 columns,
751 index, # type: ignore[arg-type]
752 dtype,
753 )
754 mgr = arrays_to_mgr(
755 arrays,
756 columns,
(...)
759 typ=manager,
760 )
761 else:

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\internals\construction.py:510, in nested_data_to_arrays(data, columns, index, dtype)
507 if is_named_tuple(data[0]) and columns is None:
508 columns = ensure_index(data[0]._fields)
--> 510 arrays, columns = to_arrays(data, columns, dtype=dtype)
511 columns = ensure_index(columns)
513 if index is None:

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\internals\construction.py:875, in to_arrays(data, columns, dtype)
872 data = [tuple(x) for x in data]
873 arr = _list_to_arrays(data)
--> 875 content, columns = _finalize_columns_and_data(arr, columns, dtype)
876 return content, columns

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\internals\construction.py:972, in _finalize_columns_and_data(content, columns, dtype)
969 columns = validate_or_indexify_columns(contents, columns)
970 except AssertionError as err:
971 # GH#26429 do not raise user-facing AssertionError
--> 972 raise ValueError(err) from err
974 if len(contents) and contents[0].dtype == np.object
:
975 contents = _convert_object_array(contents, dtype=dtype)

ValueError: 3 columns passed, passed data had 61773 columns

could not open port '/dev/ttyACM0'

I am drawing a blank again on another error and wonder if there is anyone that knows how to overcome this. I am using a windows 11 machine but cannot figure out where '/dev/ttyACM0' would be and what files would be required.

Here is the complete error:

SerialException Traceback (most recent call last)
Cell In[8], line 61
59 tuner = Tuner(param_dict, objfunc,conf_Dict)
60 all_runs = []
---> 61 results = tuner.maximize()
62 all_runs.append(results)
63 save_res(all_runs,log_file_name[0:-4]+'.p')

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\mango\tuner.py:152, in Tuner.maximize(self)
151 def maximize(self):
--> 152 return self.run()

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\mango\tuner.py:143, in Tuner.run(self)
141 def run(self):
142 if self.config.is_bayesian:
--> 143 self.results = self.runBayesianOptimizer()
144 elif self.config.is_random:
145 self.results = self.runRandomOptimizer()

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\mango\tuner.py:185, in Tuner.runBayesianOptimizer(self)
182 def runBayesianOptimizer(self):
183 results = dict()
--> 185 X_list, Y_list, X_tried = self.run_initial()
188 # evaluated hyper parameters are used
189 X_init = self.ds.convert_GP_space(X_list)

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\mango\tuner.py:166, in Tuner.run_initial(self)
163 else:
164 # getting first few random values
165 X_tried = self.ds.get_random_sample(self.config.initial_random)
--> 166 X_list, Y_list = self.runUserObjective(X_tried)
168 # in case initial random results are invalid try different samples
169 n_tries = 1

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\mango\tuner.py:337, in Tuner.runUserObjective(self, X_next_PS)
334 def runUserObjective(self, X_next_PS):
335 # initially assuming entire X_next_PS is evaluated and returned results are only Y values
336 X_list_evaluated = X_next_PS
--> 337 results = self.objective_function(X_next_PS)
338 Y_list_evaluated = results
340 # if result is a tuple, then there is possibility that partial values are evaluated

Cell In[8], line 44, in objfunc(args_list)
41 norm_flag=hyper_par['norm_flag']
42 dil_list = hyper_par['dil_list']
---> 44 objective = objective_NN(epochs=model_epochs,nb_filters=nb_filters,kernel_size=kernel_size,
45 dilations=dil_list,
46 dropout_rate=dropout_rate,use_skip_connections=use_skip_connections,
47 norm_flag=norm_flag)
48 objective_evaluated.append(objective)
50 end_time = time.time()

Cell In[7], line 33, in objective_NN(epochs, nb_filters, kernel_size, dilations, dropout_rate, use_skip_connections, norm_flag)
31 if(HIL==True):
32 convert_to_cpp_model(dirpath)
---> 33 RAM, Flash, Latency, idealArenaSize, errorCode = HIL_controller(dirpath=dirpath,
34 chosen_device=device,
35 window_size=window_size,
36 number_of_channels = input_dim,
37 quantization=quantization)
38 score = -5.0
39 if(Flash==-1):

File c:\Users\jakem\OneDrive - xonano.com\Documents\Python Scripts\TinyOdom\OxIOD\hardware_utils.py:89, in HIL_controller(dirpath, chosen_device, window_size, number_of_channels, quantization)
87 j = 0
88 while(masterError==0):
---> 89 RAM, Flash, Latency, err_flag = HIL_spec(dirpath,chosen_device,arenaSizes,j,
90 window_size,number_of_channels,quantization=False)
91 print('Before change:',masterError)
92 if(err_flag == 0): #already got minimum required arena size, everything ok

File c:\Users\jakem\OneDrive - xonano.com\Documents\Python Scripts\TinyOdom\OxIOD\hardware_utils.py:30, in HIL_spec(dirpath, chosen_device, arenaSizes, idx, window_size, number_of_channels, quantization)
28 def HIL_spec(dirpath="tinyodom_tcn/",chosen_device="NUCLEO_F746ZG",
29 arenaSizes=np.arange(10,300,30),idx=0,window_size=200,number_of_channels=10,quantization=False):
---> 30 ser = serial.Serial('/dev/ttyACM0') #COM Port where board is attached
31 RAM = -1
32 Flash = -1

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\serial\serialwin32.py:33, in Serial.init(self, *args, **kwargs)
31 self._overlapped_read = None
32 self._overlapped_write = None
---> 33 super(Serial, self).init(*args, **kwargs)

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\serial\serialutil.py:244, in SerialBase.init(self, port, baudrate, bytesize, parity, stopbits, timeout, xonxoff, rtscts, write_timeout, dsrdtr, inter_byte_timeout, exclusive, **kwargs)
241 raise ValueError('unexpected keyword arguments: {!r}'.format(kwargs))
243 if port is not None:
--> 244 self.open()

File c:\Users\jakem\AppData\Local\Programs\Python\Python310\lib\site-packages\serial\serialwin32.py:64, in Serial.open(self)
62 if self._port_handle == win32.INVALID_HANDLE_VALUE:
63 self._port_handle = None # 'cause del is called anyway
---> 64 raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))
66 try:
67 self._overlapped_read = win32.OVERLAPPED()

SerialException: could not open port '/dev/ttyACM0': FileNotFoundError(2, 'The system cannot find the path specified.', None, 3)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.