{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 1.0 Introduction","metadata":{}},{"cell_type":"markdown","source":"## 1.1 Sources, inspirations, and credits","metadata":{}},{"cell_type":"markdown","source":"Inspirations:\n- [Caltech GPS Basics](http://web.gps.caltech.edu/classes/ge111/Docs/GPSbasics.pdf)\n- [2D trilateration GIS stackexchange thread](https://gis.stackexchange.com/questions/40660/trilateration-algorithm-for-n-amount-of-points)\n- [Stanford GPS course on youtube](https://www.youtube.com/watch?v=-hnkDQIZ8kY)\n    \n\nCredits:\nAuthor(s) - Jon Mayes, [Quantum Logik Consulting](https://quantumlogik.com)","metadata":{}},{"cell_type":"markdown","source":"# 2.0 Imports","metadata":{}},{"cell_type":"code","source":"#just numpy for this one\n\nimport numpy as np\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.365345Z","iopub.execute_input":"2021-06-17T15:29:22.366084Z","iopub.status.idle":"2021-06-17T15:29:22.375506Z","shell.execute_reply.started":"2021-06-17T15:29:22.365985Z","shell.execute_reply":"2021-06-17T15:29:22.374469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.rcParams[\"figure.figsize\"] = (10,5)","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.377295Z","iopub.execute_input":"2021-06-17T15:29:22.377934Z","iopub.status.idle":"2021-06-17T15:29:22.392492Z","shell.execute_reply.started":"2021-06-17T15:29:22.377895Z","shell.execute_reply":"2021-06-17T15:29:22.391303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#import qlc color scheme\nqlcGreens = ['#001a1a',\n            '#003333',\n            '#004d4d',\n            '#006666',\n            '#008080',\n            '#009999',\n            '#00b3b3',\n            '#00cccc',\n            '#00e6e6',\n            '#00ffff',\n            '#1affff',\n            '#33ffff',\n            '#4dffff',\n            '#66ffff',\n            '#80ffff',\n            '#99ffff',\n            '#b3ffff',\n            '#ccffff',\n            '#e6ffff',\n            '#ffffff']","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.394469Z","iopub.execute_input":"2021-06-17T15:29:22.395053Z","iopub.status.idle":"2021-06-17T15:29:22.407614Z","shell.execute_reply.started":"2021-06-17T15:29:22.395003Z","shell.execute_reply":"2021-06-17T15:29:22.406154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3.0 Setup","metadata":{}},{"cell_type":"markdown","source":"Let's set up a very simple problem.\n- We live in two dimensional space\n- we have 4 satelittles, located below (there will be a visual at the end of the section)\n- The transmission times are all simultaneous and we have no clock bias or anything fun like that","metadata":{}},{"cell_type":"code","source":"sat0 = [0,1]\nsat1 = [1,1]\nsat2 = [2,1]\nsat3 = [2,0]\n\nsats = np.array([sat0,sat1, sat2, sat3])\nsats","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-06-17T15:29:22.409358Z","iopub.execute_input":"2021-06-17T15:29:22.409714Z","iopub.status.idle":"2021-06-17T15:29:22.425253Z","shell.execute_reply.started":"2021-06-17T15:29:22.409680Z","shell.execute_reply":"2021-06-17T15:29:22.424158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n- The GPS device is located at (1,0)\n\n- The distance from each satellite to the truth is the pseudorange","metadata":{}},{"cell_type":"code","source":"truth = np.array([1,0])\n\npseudorange0 = np.sqrt(2) \npseudorange1 = 1 \npseudorange2 = np.sqrt(2) \npseudorange3 = 1 \npseudoranges = np.array([pseudorange0,pseudorange1,pseudorange2, pseudorange3])\npseudoranges","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.427349Z","iopub.execute_input":"2021-06-17T15:29:22.428049Z","iopub.status.idle":"2021-06-17T15:29:22.439031Z","shell.execute_reply.started":"2021-06-17T15:29:22.427997Z","shell.execute_reply":"2021-06-17T15:29:22.437801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A kludgy graph to visualize the problem","metadata":{}},{"cell_type":"code","source":"def viz_problem(sats, prs, truth, estimate):\n     \n    figure, axes = plt.subplots()\n    \n    plt.scatter(sats[:,0], sats[:,1]) \n    \n    plt.xlim(-3, 3)\n    plt.ylim(-3, 3)\n    \n    for i in range(len(sats)):\n    \n        thisSat = sats[i]\n        sat_range = plt.Circle( (thisSat[0], thisSat[1] ) , prs[i],\n                               color = qlcGreens[i],\n                               alpha = .2                          \n                              )\n        plt.annotate('Sat ' + str(i), # this is the text\n                 (thisSat[0], thisSat[1]), # this is the point to label\n                 textcoords=\"offset points\", # how to position the text\n                 xytext=(0,10), # distance from text to points (x,y)\n                 ha='center')\n              \n        axes.add_artist( sat_range )  \n       \n    plt.plot(truth[0],truth[1],'rX', markersize=16)     \n    \n    plt.annotate('True Location', # this is the text\n                 (truth[0],truth[1]), # this is the point to label\n                 textcoords=\"offset points\", # how to position the text\n                 xytext=(-5,0), # distance from text to points (x,y)\n                 color='red',\n                 ha='right')\n    \n    \n    if estimate is None:\n        pass\n    else:\n        plt.plot(estimate[0],estimate[1],'b*', markersize=12)     \n    \n        plt.annotate('Estimate', # this is the text\n                 (estimate[0],estimate[1]), # this is the point to label\n                 textcoords=\"offset points\", # how to position the text\n                 xytext=(5,-1), # distance from text to points (x,y)\n                 color='blue',    \n                 ha='left')\n     \n    axes.set_aspect( 1 )\n    plt.title( 'Current State of Iteration' )  \n    plt.show()\n    return ","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.440892Z","iopub.execute_input":"2021-06-17T15:29:22.441607Z","iopub.status.idle":"2021-06-17T15:29:22.456390Z","shell.execute_reply.started":"2021-06-17T15:29:22.441535Z","shell.execute_reply":"2021-06-17T15:29:22.454780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"viz_problem(sats, pseudoranges, truth, None)\n","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-06-17T15:29:22.457652Z","iopub.execute_input":"2021-06-17T15:29:22.458053Z","iopub.status.idle":"2021-06-17T15:29:22.733894Z","shell.execute_reply.started":"2021-06-17T15:29:22.458020Z","shell.execute_reply":"2021-06-17T15:29:22.732938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4.0 Iterations","metadata":{}},{"cell_type":"markdown","source":"## 4.1 Initial guess","metadata":{}},{"cell_type":"markdown","source":"The algorithm described in the sources above is an iterative one. That is, we need to create a guess, then the algorithm will point us in the direction in the true location.\n\nAs an initial guess, we will take the average of the satellites and label it with a blue star","metadata":{}},{"cell_type":"code","source":"sat_average = sats.mean(axis=0)\n#init = np.array([1.05,-.14])\n#init = estimate","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.736839Z","iopub.execute_input":"2021-06-17T15:29:22.737205Z","iopub.status.idle":"2021-06-17T15:29:22.741207Z","shell.execute_reply.started":"2021-06-17T15:29:22.737172Z","shell.execute_reply":"2021-06-17T15:29:22.740442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sat_average","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.742500Z","iopub.execute_input":"2021-06-17T15:29:22.742891Z","iopub.status.idle":"2021-06-17T15:29:22.759553Z","shell.execute_reply.started":"2021-06-17T15:29:22.742852Z","shell.execute_reply":"2021-06-17T15:29:22.758527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"viz_problem(sats, pseudoranges, truth, sat_average)","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.761137Z","iopub.execute_input":"2021-06-17T15:29:22.761831Z","iopub.status.idle":"2021-06-17T15:29:22.971353Z","shell.execute_reply.started":"2021-06-17T15:29:22.761784Z","shell.execute_reply":"2021-06-17T15:29:22.970254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\nWith an initial estimate, we know calculate the theoretical ranges, that is, the ranges if our guess was true.\n\nAs we will be taking difference, we calculate the residuals, that is the actual measurement versus the theoretical/assumed ranges\n","metadata":{}},{"cell_type":"code","source":"estimate = sat_average","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.973031Z","iopub.execute_input":"2021-06-17T15:29:22.973459Z","iopub.status.idle":"2021-06-17T15:29:22.978755Z","shell.execute_reply.started":"2021-06-17T15:29:22.973402Z","shell.execute_reply":"2021-06-17T15:29:22.977357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\ntheorange0 = np.sqrt((estimate[0] - sat0[0])**2 + (estimate[1] - sat0[1])**2) \ntheorange1 = np.sqrt((estimate[0] - sat1[0])**2 + (estimate[1] - sat1[1])**2) \ntheorange2 = np.sqrt((estimate[0] - sat2[0])**2 + (estimate[1] - sat2[1])**2) \ntheorange3 = np.sqrt((estimate[0] - sat3[0])**2 + (estimate[1] - sat3[1])**2) \ntheoranges = np.array([theorange0,theorange1,theorange2, theorange3])\ntheoranges","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.980349Z","iopub.execute_input":"2021-06-17T15:29:22.980693Z","iopub.status.idle":"2021-06-17T15:29:22.994980Z","shell.execute_reply.started":"2021-06-17T15:29:22.980661Z","shell.execute_reply":"2021-06-17T15:29:22.993817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"residuals = pseudoranges - theoranges\nresiduals","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:22.996227Z","iopub.execute_input":"2021-06-17T15:29:22.996535Z","iopub.status.idle":"2021-06-17T15:29:23.016093Z","shell.execute_reply.started":"2021-06-17T15:29:22.996505Z","shell.execute_reply":"2021-06-17T15:29:23.014890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From the lessons, we know we will need to calculate the design/geometry matrix.\n\nThis is G in the Stanford Lecture and A in the Caltech document.\n\nG is the Satellite positions less our estimate, normalized.\nWe normalize because we only want the direction\n\nWe will do this in a few steps to be very clear.\n","metadata":{}},{"cell_type":"code","source":"G_unnorm = sats - estimate\nG_unnorm","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.017853Z","iopub.execute_input":"2021-06-17T15:29:23.018349Z","iopub.status.idle":"2021-06-17T15:29:23.031385Z","shell.execute_reply.started":"2021-06-17T15:29:23.018302Z","shell.execute_reply":"2021-06-17T15:29:23.030234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"norm = np.linalg.norm(G_unnorm)\nnorm","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.036214Z","iopub.execute_input":"2021-06-17T15:29:23.036583Z","iopub.status.idle":"2021-06-17T15:29:23.046538Z","shell.execute_reply.started":"2021-06-17T15:29:23.036552Z","shell.execute_reply":"2021-06-17T15:29:23.045559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"G_norm = G_unnorm / norm\nG_norm","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.048857Z","iopub.execute_input":"2021-06-17T15:29:23.049166Z","iopub.status.idle":"2021-06-17T15:29:23.058067Z","shell.execute_reply.started":"2021-06-17T15:29:23.049137Z","shell.execute_reply":"2021-06-17T15:29:23.057134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So, if this were perfectly specified, that is, with our 2 dimension we had only 2 satellites, we could just take the inverse of G.\n\nHowever, we will find that we will have more satellites than dimensions (which is good since in the real world we won't have such perfect estimates). \n\nThus, we create an invertible matrix by front multiplying G by its transpose, which I will call GtG","metadata":{}},{"cell_type":"code","source":"G_norm_trans = np.transpose(G_norm)\nG_norm_trans","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.059601Z","iopub.execute_input":"2021-06-17T15:29:23.059982Z","iopub.status.idle":"2021-06-17T15:29:23.073224Z","shell.execute_reply.started":"2021-06-17T15:29:23.059937Z","shell.execute_reply":"2021-06-17T15:29:23.072476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"GtG = G_norm_trans @ G_norm\nGtG","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.074693Z","iopub.execute_input":"2021-06-17T15:29:23.075259Z","iopub.status.idle":"2021-06-17T15:29:23.091901Z","shell.execute_reply.started":"2021-06-17T15:29:23.075197Z","shell.execute_reply":"2021-06-17T15:29:23.090745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"GtGinv = np.linalg.inv(GtG)\nGtGinv","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.093181Z","iopub.execute_input":"2021-06-17T15:29:23.093589Z","iopub.status.idle":"2021-06-17T15:29:23.107790Z","shell.execute_reply.started":"2021-06-17T15:29:23.093560Z","shell.execute_reply":"2021-06-17T15:29:23.106674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trans_matrix = GtGinv @ G_norm_trans\ntrans_matrix","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.109818Z","iopub.execute_input":"2021-06-17T15:29:23.110496Z","iopub.status.idle":"2021-06-17T15:29:23.125852Z","shell.execute_reply.started":"2021-06-17T15:29:23.110445Z","shell.execute_reply":"2021-06-17T15:29:23.124964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"correction = trans_matrix @ residuals\ncorrection","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.127125Z","iopub.execute_input":"2021-06-17T15:29:23.129204Z","iopub.status.idle":"2021-06-17T15:29:23.138265Z","shell.execute_reply.started":"2021-06-17T15:29:23.129135Z","shell.execute_reply":"2021-06-17T15:29:23.136919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.linalg.norm(correction)","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.139917Z","iopub.execute_input":"2021-06-17T15:29:23.140396Z","iopub.status.idle":"2021-06-17T15:29:23.154105Z","shell.execute_reply.started":"2021-06-17T15:29:23.140350Z","shell.execute_reply":"2021-06-17T15:29:23.152770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"estimate = estimate - correction\nestimate","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.156002Z","iopub.execute_input":"2021-06-17T15:29:23.156479Z","iopub.status.idle":"2021-06-17T15:29:23.165285Z","shell.execute_reply.started":"2021-06-17T15:29:23.156436Z","shell.execute_reply":"2021-06-17T15:29:23.164290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"distance_from_true = np.sqrt((truth[0]-estimate[0])**2 + (truth[1] - estimate[1])**2)\ndistance_from_true","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.166876Z","iopub.execute_input":"2021-06-17T15:29:23.167375Z","iopub.status.idle":"2021-06-17T15:29:23.179241Z","shell.execute_reply.started":"2021-06-17T15:29:23.167327Z","shell.execute_reply":"2021-06-17T15:29:23.178287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"distance_from_true_sat_average = np.sqrt((truth[0]-sat_average[0])**2 + (truth[1]-sat_average[1])**2)\ndistance_from_true_sat_average","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.180847Z","iopub.execute_input":"2021-06-17T15:29:23.181595Z","iopub.status.idle":"2021-06-17T15:29:23.192770Z","shell.execute_reply.started":"2021-06-17T15:29:23.181540Z","shell.execute_reply":"2021-06-17T15:29:23.191850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So, we got closer, but if we visualize it, we will see that we overshot.","metadata":{}},{"cell_type":"code","source":"viz_problem(sats, pseudoranges, truth, estimate)","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.194520Z","iopub.execute_input":"2021-06-17T15:29:23.195253Z","iopub.status.idle":"2021-06-17T15:29:23.397560Z","shell.execute_reply.started":"2021-06-17T15:29:23.195206Z","shell.execute_reply":"2021-06-17T15:29:23.396747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4.2 Iteration 2 using latest estimate","metadata":{}},{"cell_type":"markdown","source":"This is an iterative method. Let's run this again with the new estimate\n\nWe will include the entire process in one cell for \"brevity\"","metadata":{}},{"cell_type":"code","source":"theorange0 = np.sqrt((estimate[0] - sat0[0])**2 + (estimate[1] - sat0[1])**2) \ntheorange1 = np.sqrt((estimate[0] - sat1[0])**2 + (estimate[1] - sat1[1])**2) \ntheorange2 = np.sqrt((estimate[0] - sat2[0])**2 + (estimate[1] - sat2[1])**2) \ntheorange3 = np.sqrt((estimate[0] - sat3[0])**2 + (estimate[1] - sat3[1])**2) \ntheoranges = np.array([theorange0,theorange1,theorange2, theorange3])\n\n\nresiduals = pseudoranges - theoranges\n\nG_unnorm = sats - estimate\nnorm = np.linalg.norm(G_unnorm)\n\nG_norm_trans = np.transpose(G_norm)\nG_norm = G_unnorm / norm\n\nGtG = G_norm_trans @ G_norm\nGtGinv = np.linalg.inv(GtG)\n\ntrans_matrix = GtGinv @ G_norm_trans\ncorrection = trans_matrix @ residuals\n\nestimate = estimate - correction\nestimate","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.398704Z","iopub.execute_input":"2021-06-17T15:29:23.399248Z","iopub.status.idle":"2021-06-17T15:29:23.413707Z","shell.execute_reply.started":"2021-06-17T15:29:23.399199Z","shell.execute_reply":"2021-06-17T15:29:23.412505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"distance_from_true = np.sqrt((truth[0]-estimate[0])**2 + (truth[1] - estimate[1])**2)\ndistance_from_true","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.415289Z","iopub.execute_input":"2021-06-17T15:29:23.415820Z","iopub.status.idle":"2021-06-17T15:29:23.424014Z","shell.execute_reply.started":"2021-06-17T15:29:23.415630Z","shell.execute_reply":"2021-06-17T15:29:23.422715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"viz_problem(sats, pseudoranges, truth, estimate)","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.425461Z","iopub.execute_input":"2021-06-17T15:29:23.425816Z","iopub.status.idle":"2021-06-17T15:29:23.633029Z","shell.execute_reply.started":"2021-06-17T15:29:23.425758Z","shell.execute_reply":"2021-06-17T15:29:23.632091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"distance_from_true = np.sqrt((truth[0]-estimate[0])**2 + (truth[1] - estimate[1])**2)\ndistance_from_true","metadata":{"execution":{"iopub.status.busy":"2021-06-17T15:29:23.634137Z","iopub.execute_input":"2021-06-17T15:29:23.634609Z","iopub.status.idle":"2021-06-17T15:29:23.641329Z","shell.execute_reply.started":"2021-06-17T15:29:23.634560Z","shell.execute_reply":"2021-06-17T15:29:23.640336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4.3 Iteration 3","metadata":{"heading_collapsed":true}},{"cell_type":"code","source":"theorange0 = np.sqrt((estimate[0] - sat0[0])**2 + (estimate[1] - sat0[1])**2) \ntheorange1 = np.sqrt((estimate[0] - sat1[0])**2 + (estimate[1] - sat1[1])**2) \ntheorange2 = np.sqrt((estimate[0] - sat2[0])**2 + (estimate[1] - sat2[1])**2) \ntheorange3 = np.sqrt((estimate[0] - sat3[0])**2 + (estimate[1] - sat3[1])**2) \ntheoranges = np.array([theorange0,theorange1,theorange2, theorange3])\n\n\nresiduals = pseudoranges - theoranges\n\nG_unnorm = sats - estimate\nnorm = np.linalg.norm(G_unnorm)\n\nG_norm_trans = np.transpose(G_norm)\nG_norm = G_unnorm / norm\n\nGtG = G_norm_trans @ G_norm\nGtGinv = np.linalg.inv(GtG)\n\ntrans_matrix = GtGinv @ G_norm_trans\ncorrection = trans_matrix @ residuals\n\nestimate = estimate - correction\nestimate","metadata":{"hidden":true,"execution":{"iopub.status.busy":"2021-06-17T15:29:23.642729Z","iopub.execute_input":"2021-06-17T15:29:23.643124Z","iopub.status.idle":"2021-06-17T15:29:23.662853Z","shell.execute_reply.started":"2021-06-17T15:29:23.643090Z","shell.execute_reply":"2021-06-17T15:29:23.661417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"viz_problem(sats, pseudoranges, truth, estimate)","metadata":{"hidden":true,"execution":{"iopub.status.busy":"2021-06-17T15:29:23.664738Z","iopub.execute_input":"2021-06-17T15:29:23.665478Z","iopub.status.idle":"2021-06-17T15:29:23.889890Z","shell.execute_reply.started":"2021-06-17T15:29:23.665428Z","shell.execute_reply":"2021-06-17T15:29:23.888900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"distance_from_true = np.sqrt((truth[0]-estimate[0])**2 + (truth[1] - estimate[1])**2)\ndistance_from_true","metadata":{"hidden":true,"execution":{"iopub.status.busy":"2021-06-17T15:29:23.891055Z","iopub.execute_input":"2021-06-17T15:29:23.891314Z","iopub.status.idle":"2021-06-17T15:29:23.898864Z","shell.execute_reply.started":"2021-06-17T15:29:23.891288Z","shell.execute_reply":"2021-06-17T15:29:23.897795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So, what do you notice? \n\nThe algoirthm is pointing us in the right direction, however, we seem to keep overshooting the target. Thus we seem to be destined to flip flop around.\n\nWhat's the fix?\n\nThink about what we do in other machine learning tasks, particularly when we are using gradient decent. Maybe this algorithm \"learns\" too fast? ","metadata":{"hidden":true}},{"cell_type":"code","source":"","metadata":{"hidden":true},"execution_count":null,"outputs":[]}]}