{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Reading NMEA sentences\n",
    "\n",
    "EECE 5554 Robotics Sensing and Navigation, Lab 1. Put `nmea_gga.py` in the same folder as this notebook, then run the cells in order."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each dark box below is a code cell. Edit it, then press **Run** or **Shift+Enter**. Cells share variables from top to bottom, like Jupyter."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "from nmea_gga import nmea_checksum, ddmm_to_deg, parse_gga, SAMPLES\n",
    "\n",
    "line = SAMPLES[0]\n",
    "print(line)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. The checksum\n",
    "The two hex digits after `*` are the XOR of every character between `$` and `*`. Compute it yourself:"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "body = line[1:line.index('*')]\n",
    "cs = 0\n",
    "for ch in body:\n",
    "    cs ^= ord(ch)\n",
    "print('computed:', format(cs, '02X'), '  in the sentence:', line[-2:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Change one digit of `line` in the first cell (the altitude, say), run both cells again, and watch the two checksums stop matching."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "fields = body.split(',')\n",
    "for i, f in enumerate(fields):\n",
    "    print(i, repr(f))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. ddmm.mmmm to decimal degrees\n",
    "Latitude is field 2 with 2 degree digits; longitude is field 4 with 3 degree digits. S and W make the value negative."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "lat = ddmm_to_deg(fields[2], fields[3], 2)\n",
    "lon = ddmm_to_deg(fields[4], fields[5], 3)\n",
    "print(f'right way: {lat:.7f}, {lon:.7f}')\n",
    "print('wrong way:', float(fields[2]) / 100, float(fields[4]) / 100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. The whole sentence\n",
    "`parse_gga` does all of this and returns a dictionary, much like the message your Lab 1 driver publishes."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "r = parse_gga(line)\n",
    "{k: r[k] for k in ('time_utc', 'lat_deg', 'lon_deg', 'num_sats', 'hdop', 'fix_quality')}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Your turn\n",
    "Paste a GGA line from your own Lab 1 log between the quotes and run the cell."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "my_line = \"$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47\"\n",
    "r = parse_gga(my_line)\n",
    "print('checksum ok:', r['checksum']['ok'])\n",
    "print('lat, lon:', r.get('lat_deg'), r.get('lon_deg'))\n",
    "print('notes:', r['errors'])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}