diff --git a/doc/source/tutorials/02c-orientation-2markers.ipynb b/doc/source/tutorials/02c-orientation-2markers.ipynb index 9f7177ef167ec8a8a3acda0656837762fa5e2a9a..b0ceeba4a707ef68c42ccfbd1c62f426f3d42c70 100644 --- a/doc/source/tutorials/02c-orientation-2markers.ipynb +++ b/doc/source/tutorials/02c-orientation-2markers.ipynb @@ -13,61 +13,12 @@ " R.v^{ref}=v^{bee}\n", " \\end{equation}\n", "$$\n", - " \n", + "\n", "here $v^{bee}$ is the vector given by the 3D coordinates of the two markers, $v^{ref}$ is the vector given by the 3D coordinates of the two markers when the orientation of the agent is null, i.e. the orientation of the matrix is equal to the identity matrix. \n", "\n", "The system has 3 equations and 9 unknown variables: the elements of the orientation matrix.\n", "\n", - "**Note** Why 9 unknown variables if we have three rotation angles? The rotation angles appear in the orientation matrix in cosine and sine function, both nonlinear function. Therefore the sine and the cosine of the rotation angle have to be treated separatly. Moreover the multiplication of two cosines, two sine, or one cosine and one sine has to be treated has variables, because multiplication is... nonlinear.\n", - "\n", - "$$\\begin{align}\n", - " v_x^{bee} & = +v_x^{ref} \\cos\\alpha \\cos\\beta + v_y^{ref}(\\cos\\alpha \\sin\\beta \\sin\\gamma - \\sin\\alpha \\cos\\gamma) + v_z^{ref} (\\cos\\alpha \\sin\\beta \\cos\\gamma + \\sin\\alpha \\sin\\gamma) \\\\\n", - " v_y^{bee} & = +v_x^{ref} \\sin\\alpha \\cos\\beta + v_y^{ref}(\\sin\\alpha \\sin\\beta \\sin\\gamma + \\cos\\alpha \\cos\\gamma) + v_z^{ref} ( \\sin\\alpha \\sin\\beta \\cos\\gamma - \\cos\\alpha \\sin\\gamma )\\\\\n", - " v_z^{bee} & = -v_x^{ref}\\sin\\beta + v_y^{ref} \\cos\\beta \\sin\\gamma + v_z^{ref} \\cos\\beta \\cos\\gamma\n", - "\\end{align}$$\n", - "\n", - "or equivalently we can look at $v^{ref}=R^Tv^{bee}$, because $R^T=R^{-1}$\n", - "\n", - "$$\\begin{align}\n", - " v_x^{ref} & = +v_x^{bee} \\cos\\alpha \\cos\\beta +v_y^{bee} \\sin\\alpha \\cos\\beta -v_z^{bee}\\sin\\beta \\\\\n", - " v_y^{ref} & = +v_x^{bee}(\\cos\\alpha \\sin\\beta \\sin\\gamma - \\sin\\alpha \\cos\\gamma) +v_y^{bee}(\\sin\\alpha \\sin\\beta \\sin\\gamma + \\cos\\alpha \\cos\\gamma)+ v_z^{bee} \\cos\\beta \\sin\\gamma \\\\\n", - " v_z^{ref} & = +v_x^{bee}(\\cos\\alpha \\sin\\beta \\cos\\gamma + \\sin\\alpha \\sin\\gamma) + v_y^{bee} ( \\sin\\alpha \\sin\\beta \\cos\\gamma - \\cos\\alpha \\sin\\gamma )+v_z^{bee} \\cos\\beta \\cos\\gamma\n", - " \\end{align}$$\n", - "\n", - "To simplify the problem, we need to remove terms in the system of equations. Removing terms is easily done by letting certain variables to be zero. We want to determine $\\alpha$, $\\beta$, and $\\gamma$. Thus we can only set to zeros $v_x^{ref}$, $v_y^{ref}$, or $v_z^{ref}$.\n", - "\n", - "### A simple case\n", - "\n", - "If we assume that the two markers are aligned with the roll axis,\n", - "i.e. $v^{ref}=(1,0,0)^T$, the problem can easily be solve as follow:\n", - "\n", - "\n", - "$$\n", - " \\begin{align}\n", - " v_x^{bee} & = +\\cos\\alpha \\cos\\beta \\\\\n", - " v_y^{bee} & = +\\sin\\alpha \\cos\\beta \\\\\n", - " v_z^{bee} & = -\\sin\\beta\n", - " \\end{align}\n", - "$$\n", - "\n", - "\n", - "$$\n", - " \\begin{align}\n", - " \\tan\\alpha & = \\frac{\\pm v_y^{bee}}{\\pm v_x^{bee}} &\\quad \\text{from L1 and L2} \\\\\n", - " \\tan\\beta & = \\frac{-v_z^{bee}}{\\pm\\sqrt{v_y^{bee}+v_x^{bee} }} &\\quad\\text{from all}\n", - " \\end{align}\n", - "$$\n", - "\n", - "We remark that the solution does not depend of the angle $\\gamma$, \n", - "the roll angle. Thus, when we do not care about the full orientation of \n", - "a body but simply care about pitch and yaw, two markers are sufficients.\n", - "\n", - "### Other cases\n", - "\n", - "The two markers may be aligned with the pitch (or yaw axis) of the body. \n", - "In such situation, the problem is slightly more complex. We can, still \n", - "solve the system of equation, but can not find a solution independent of \n", - "the pitch (or yaw angle), we need to guess the pitch (or yaw angle)." + "**Note** Why 9 unknown variables if we have three rotation angles? The rotation angles appear in the orientation matrix in cosine and sine function, both nonlinear function. Therefore the sine and the cosine of the rotation angle have to be treated separatly. Moreover the multiplication of two cosines, two sine, or one cosine and one sine has to be treated has variables, because multiplication is... nonlinear." ] }, { @@ -76,6 +27,10 @@ "source": [ "### Angles from two markers\n", "\n", + "#### Simples cases\n", + "\n", + "In navipy, only few cases have been implemented (see below to derive the equations for a custom cases). The rotation $R$ can be written as a series of rotation along x, y, and z-axis (see: Euler angles). Simple case to extract the euler angles with only two markers arise when the first applied rotation is aligned with our two markers. For example for $R=R_zR_yR_x$, and x-aligned marker, the decomposition is simple. Indeed our measure markers can be obtained by rotating the x-axis, here the first rotation along the x-axis does not change the orientation of the x-axis. Thus, the euler angle around the x-axis will not affect the euler angles around the two other axis. \n", + "\n", "Here we illustrate, how the solution of the system in three cases: \n", "roll-aligned, pitch-aligned, and yaw-aligned, varies as a function of \n", "the a priori known angle.\n", @@ -85,241 +40,170 @@ "\n", "* The rotation around x, with convention $R_zR_yR_x$, for x-aligned markers\n", "* The rotation around y, with convention $R_zR_xR_y$, for y-aligned markers\n", - "* The rotation around z, with convention $R_yR_xR_z$, for x-aligned markers\n", - "\n", - "Thus the none of the yaw pitch roll angles may match of the a priori \n", - "known angle (except for x-aligned markers, because the internal convention is the yaw pitch roll convention)" + "* The rotation around z, with convention $R_yR_xR_z$, for x-aligned markers" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from navipy.maths.homogeneous_transformations import compose_matrix\n", - "import navipy.trajectories.transformations as mtf\n", - "from navipy.trajectories.triangle import Triangle" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similar to the notebook about the background of the orientation, we place a triangle at a known position orientation" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "yaw_t = +3*np.pi/4\n", - "pitch_t = -1*np.pi/6\n", - "roll_t = -1*np.pi/12\n", - "angles = [yaw_t, pitch_t, roll_t]\n", - "euler_axes = 'rzyx'\n", - "# Create a triangle in a given orientation\n", - "# and get the x,y,z axis used as our two markers\n", - "triangle_mode = 'x-axis=median-from-0'\n", - "transform = compose_matrix(angles=angles,\n", - " axes=euler_axes)\n", - "markers = pd.Series(data=0,\n", - " index=pd.MultiIndex.from_product(\n", - " [[0, 1, 2], ['x', 'y', 'z']]))\n", - "markers.loc[(0, 'x')] = -1\n", - "markers.loc[(2, 'y')] = np.sin(np.pi / 3)\n", - "markers.loc[(1, 'y')] = -np.sin(np.pi / 3)\n", - "markers.loc[(1, 'x')] = np.cos(np.pi / 3)\n", - "markers.loc[(2, 'x')] = np.cos(np.pi / 3)\n", - "equilateral = Triangle(markers.loc[0],\n", - " markers.loc[1],\n", - " markers.loc[2])\n", - "equilateral.transform(transform)\n", - "_, x_axis, y_axis, z_axis = mtf.triangle2bodyaxis(\n", - " equilateral, triangle_mode)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If can only can get the position of two markers out of three, we have only access to a vector in 3D space and not a triangle. \n", + "from navipy.trajectories.transformations import twomarkers2euler\n", "\n", - "We need to assume that this vector is align to one axis, and that one of the three Euler angles is known. When we do not know the angle, we can look at all possible angles, for our known angles." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "known_angles = np.linspace(-np.pi, np.pi, 180)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's assume that the two markers are aligned with one the axes\n", - "1. along the x-axis,\n", - "2. along the y-axis, or\n", - "3. along the z-axis." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ + "mark0 = pd.Series(index=['x','y','z'], data=np.random.rand(3))\n", + "mark1 = pd.Series(index=['x','y','z'], data=np.random.rand(3))\n", + "known_angle = 2*np.pi*np.random.rand()\n", + "# x-aligned\n", "axis_alignement = 'x-axis'\n", - "mark0 = pd.Series(data=0, index=['x', 'y', 'z'])\n", - "mark1 = pd.Series(x_axis, index=['x', 'y', 'z'])\n", - "solution_x_axis = pd.DataFrame(index=known_angles, columns=['yaw',\n", - " 'pitch',\n", - " 'roll'])\n", - "for known_angle in known_angles:\n", - " angles_estimate = mtf.twomarkers2euler(\n", - " mark0, mark1, axis_alignement, known_angle, euler_axes)\n", - " solution_x_axis.loc[known_angle, :] = angles_estimate" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ + "euler_axes = 'zyx'\n", + "alpha, beta, gamma = twomarkers2euler(mark0, mark1, axis_alignement,\n", + " known_angle, euler_axes)\n", + "# y-aligned\n", "axis_alignement = 'y-axis'\n", - "mark0 = pd.Series(data=0, index=['x', 'y', 'z'])\n", - "mark1 = pd.Series(y_axis, index=['x', 'y', 'z'])\n", - "solution_y_axis = pd.DataFrame(index=known_angles, columns=['yaw',\n", - " 'pitch',\n", - " 'roll'])\n", - "for known_angle in known_angles:\n", - " angles_estimate = mtf.twomarkers2euler(\n", - " mark0, mark1, axis_alignement, known_angle, euler_axes)\n", - " solution_y_axis.loc[known_angle, :] = angles_estimate" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ + "euler_axes = 'zxy'\n", + "alpha, beta, gamma = twomarkers2euler(mark0, mark1, axis_alignement,\n", + " known_angle, euler_axes)\n", + "\n", + "# z-aligned\n", "axis_alignement = 'z-axis'\n", - "mark0 = pd.Series(data=0, index=['x', 'y', 'z'])\n", - "mark1 = pd.Series(z_axis, index=['x', 'y', 'z'])\n", - "solution_z_axis = pd.DataFrame(index=known_angles, columns=['yaw',\n", - " 'pitch',\n", - " 'roll'])\n", - "for known_angle in known_angles:\n", - " angles_estimate = mtf.twomarkers2euler(\n", - " mark0, mark1, axis_alignement, known_angle, euler_axes)\n", - " solution_z_axis.loc[known_angle, :] = angles_estimate" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The possible two other angles are shown below, as a function of the known angle" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA3oAAAEWCAYAAAAw+uVwAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzs3XdcleX/x/HXxZ6CDBFFRJyAe+DOnaZm2rDhHllmmdavsr2s7JulmavcKzXTsnKUe6SmmBv3QFAcgKjI5ly/Pw6OyoF64D4cPs/Hg0fCuc99v493XpzPuZbSWiOEEEIIIYQQwnbYGR1ACCGEEEIIIYRlSaEnhBBCCCGEEDZGCj0hhBBCCCGEsDFS6AkhhBBCCCGEjZFCTwghhBBCCCFsjBR6QgghhBBCCGFjpNATBU4pdUIp1Tr3z28ppSYbkKG5UiquoK8rhLBu0j4JIayRUmqtUqp/7p+7KaX+MCBDiFJKK6UcCvra4t7IjRKG0lp/anQGIYS4GWmfhBDWSGs9B5hjdA5h/aRHTwghhBBCCCFsjBR6Ik+UUuWVUklKqdq535dSSp1XSjW/xbGrlVKJSqkEpdQcpZT3Lc77gVJq9g3f91RKxeQ+991/DaP6QCn1g1JqplLqslJqn1Kq7g3PLaWUWpib67hSavANj7kqpaYrpS4opaKBepb72xFCGEkp9ZpSauG/fjZGKfX1TY6V9kkIUWCUUk8qpVJu+MpQSq29yXHFlVK/5bYRF3L/HHSLc/ZWSm284fsHlVIHlVIXlVLjlVLrbhjm2VsptVEpNTL3vMeVUg/d8FwvpdQUpVS8UuqUUmq4Uso+9zH73OclKKWOAR0s/fcj8pcUeiJPtNZHgTeA2UopN2AaMENrvfYmhyvgM6AUEAaUAT640zWUUuHAeKAbEAh4AaX/dVgnYB7gDfwCjM19rh3wK7Ar9zmtgCFKqba5z3sfKJ/71RbodedXLYQoJGYD7a4WbLnzR54CZt7kWGmfhBAFRms9X2vtobX2wNzuHAPm3uRQO8zvrcoCwUAauW3I7Sil/IAfgTcBX+Ag0Ohfh9XP/bkf8D9gilJK5T42HcgGKgC1gAeB/rmPPQt0zP15XeDxO75gYVWk0BN5prWeBBwB/sL8RuftWxx3RGu9QmudobU+D3wFNMvDJR4HftVab9RaZwLvAfpfx2zUWi/VWucAs4AauT+vB/hrrT/SWmdqrY8BkzC/2QPoCnyitU7SWscCY/L6uoUQ1k1rHQ+sB57I/VE7IEFrvf0mx0r7JIQocLkf+HwPrNVaf/vvx7XWiVrrhVrrVK31ZeAT8tY2tQf2aa0Xaa2zMbcfZ/51TIzWelJu2zQD83u4AKVUQO7zh2itr2itzwGj+GfbNFprHau1TsL8IZkoRGQxFnG3JmH+pHqA1jpDKdUUWJb7WIzWOiK34fgaaAp4Yv5A4UIezl0KiL36jdY6VSmV+K9jbmy8UgGX3E/vywKllFLJNzxuD2y42bmBmDzkEUIUHjOAgZjbqO7ALGmfhBBW5BPMbc5gpVQwEH31Aa21R+5oqVGYP6gqnvuQp1LKPrdAu5V/t01a/XfV3jM3PJ6a25nnAfgAjkD89Q4+7G44n7RNhZwUeiLPlFIewGhgCvCBUmqh1noD5sbiRp9i/qS7mtY6SSnVmTwMPwDigco3XM8V8zCEvIgFjmutK97m3GWAfbnfB+fxvEKIwuFnYIJSqirmoUava61PIu2TEMJgSqmngKeBelrrLOBmbdOrmNuY+lrrM0qpmsAOzMPNbyceuDaXL3dI5k3n9t1ELJAB+OX2Bt7s3GVu+F7apkJGhm6Ku/E1EKW17g8sASbe4jhPIAW4qJQqDbyWx/P/CDyslGqklHLCPG/mTg3cVVuBy0qpN3IXNrBXSlVVSl1d1OAH4M3cyc5BwEt5PK8QohDQWqdjbkO+B7bmFnk3I+2TEKLAKKVqAd8AnXOHi9+KJ+Z5eclKKR/Mc3fzYglQTSnVOXcEwSCgZF6emDvs/Q/gS6VUMaWUnTIvWHV1yOgPmHsgg5RSxYFhecwkrIQUeiJPlFKPYB5OMDD3R68AtZVS3W5y+IdAbeAi5gZoUV6uobXeh/kNzjzMnyKlAOcwf9p0p+fmYP4UvyZwHEgAJmNeMOFqppjcx/7APH9GCGFbZgDVuP2/b2mfhBAF6RHMQzE33rDy5rKbHDcacMXcPmwBlufl5FrrBMzzk/8HJALhQBR5aJty9QScMA8lvYD5Q63A3McmAb9jXkjqb/LYXgrrobT+91xyIaxD7lDRZKCi1vq40XmEENYtd97LAaCk1vpSPl9L2ichhNXJXfQlDuimtV5jdB5hLOnRE1ZFKfWwUspNKeUOjAT2ACeMTSWEsHa5b25eAeblV5En7ZMQwhoppdoqpbyVUs7AW5iHlW8xOJawAlLoCWvzCHA696si8JSWbmchxG3kFl6XgDbkfV7LvZD2SQhhjRoCRzEP+3wY83zANGMjCWsgQzeFEEIIIYQQwsZIj54QQgghhBBC2JhCtY+en5+fDgkJMTqGEMKCtm/fnqC19jc6x/2QtkkI2yTtkxDCGuW1bSpUhV5ISAhRUVFGxxBCWJBSKsboDPdL2iYhbJO0T0IIa5TXtkmGbgohhBBCCCGEjZFCTwghhBBCCCFsjBR6QgghhBBCCGFjCtUcPSGEEELkv6ysLOLi4khPTzc6SoFwcXEhKCgIR0dHo6MUCLm/QhQNUugJIYQQ4h/i4uLw9PQkJCQEpZTRcfKV1prExETi4uIoV66c0XEKhNxfIYoGGbophBBCiH9IT0/H19fX5osAAKUUvr6+RaZ3C+T+ClFUSKEnhBBCiP8oCkXAVUXptV5VlF5zUXqtQtxICj0hhEX9dPgn1sWuMzqGEEIIIYTVM5k0o1Yc4uCZyxY/txR6QgiL0FozYdcE3tv0HosOLzI6jrByB89c5mJqltExhBBCCMNkZOcw9IedfL3qMEt2n7b4+WUxFiHEfcsyZTF8y3AWHV5Ep/Kd+KDRB0ZHElau7ej1FHNxYPcHbY2OIoQQQhS4i2lZPD9rO5uPJfJ6u8oMbFbe4tcwrEdPKeWilNqqlNqllNqnlPrQqCxCiHuXmpXK4NWDWXR4Ec9Vf47hjYfjaCdLWIs7u5SeTXaOyegYwgq99957jB49+tr3b7/9Nl9//TWtWrWidu3aVKtWjcWLFwPwxRdfMGbMGACGDh1Ky5YtAVi9ejXdunUr+PDijuT+iqLudHIaXSduJiomiVFP1uCF5hXyZS6pkT16GUBLrXWKUsoR2KiUWqa13mJgJiHEXUhIS2DQqkEcSDrAew3f44lKTxgdSRQyUTEXaBDqa3QMcRsf/rqP6NOXLHrO8FLFeP/hiFs+3rdvXx599FGGDBmCyWRi3rx5bNq0iT59+lCsWDESEhJo0KABnTp1omnTpnz55ZcMHjyYqKgoMjIyyMrKYsOGDTzwwAMWzW2L5P4KUbAOnLlE76nbSMnIZnqfSBpX8Mu3axlW6GmtNZCS+61j7pc2Ko8Q4u4cv3icgSsHkpSexJgWY2hWppnRkUQhtDL6rBR64j9CQkLw9fVlx44dnD17llq1auHj48PQoUNZv349dnZ2nDp1irNnz1KnTh22b9/OpUuXcHZ2pnbt2kRFRbFhw4ZrPUHCusj9FUXVpiMJPDdrO27O9vzwXEPCSxXL1+sZOkdPKWUPbAcqAOO01n/d5JgBwGuAt7+/fwEnFELczM5zO3lx9YvYK3umtp1KVb+qRkcqcNI23R9nBzsysk0s3RPPm+3DsLeT5c+t1e16ZvJT//79mT59OmfOnKFv377MmTOH8+fPs337dhwdHQkJCSE9PR1HR0fKlSvH9OnTadSoEdWrV2fNmjUcOXKEsLAwQ7Ib7W7aJ7m/QhSMn3ec4rUfd1HOz53pfSIp5e2a79c0dNVNrXWO1romEAREKqX+825Ra/2d1rqi1to/ODi44EMKIf5hZcxK+v/RH29nb2Y/NLtIFnkgbdP90kA5P3dOX0xn1f6zRscRVqhLly4sX76cbdu20bZtWy5evEiJEiVwdHRkzZo1xMTEXDu2adOmjBw5kgceeICmTZsyceJEatWqVWT3TysM7ZPcX1FUaK0Zv/YIQ+bvpE7Z4ix4vlGBFHlgJdsraK2TgTVAO6OzCCFubc7+Obyy9hUq+1Rm1kOzKFOsjNGRRCGltebB8AACvVyYuTnmzk8QRY6TkxMtWrSga9eu2Nvb061bN6KioqhWrRozZ86kSpUq145t2rQp8fHxNGzYkICAAFxcXGjatKmB6cWdyP0VRUGOSfPu4r38b/lBHq5Rihl9I/FyLbgF6wwbuqmU8geytNbJSilXoA3wuVF5hBC3ZtImRm0fxfR902lZpiUjHhiBq0PBfBolbJNJg4O9onuDsnzx+0F2xyVTPcjb6FjCiphMJrZs2cKCBQsA8PPzY/PmzTc9tlWrVmRlXd+X8dChQwWSUdw7ub/C1qVl5vDS3B2s3H+W55qF8kbbKtgV8DQFI3v0AoE1SqndwDZghdb6NwPzCCFuIjMnk2HrhzF933SeqvwUXzX/Soo8cd+01tgpRc+GZfFxd2LEsgOY1+gSAqKjo6lQoQKtWrWiYsWKRscRFib3V9i6xJQMnp60hVUHzvJhpwjefCiswIs8MHbVzd1ALaOuL4S4s0uZl3h59ctEnY1iaJ2h9InoI3MihEWYNCil8HRx5KWWFfjw12hWRJ/lwYiSRkcTViA8PJxjx44ZHUPkE7m/wpbFJF6h19StxF9MZ0K3OrSratzvNauYoyeEsD7xKfH0WtaLned3MqLpCPpW7StFnrCIqz13V/9v6la/LFVKevL2z3tJTs00LpgQQghxH3bGJvPo+E0kp2Xx/bP1DS3yQAo9IcRNHEw6SPel3Tlz5Qzftv6WDqEdjI4kbMjVEZp2uR8cODnYMfKJGly4kslrP+7GZJIhnEIIIQqXldFneeq7zbg527NwYCPqlPUxOpIUekKIf9p8ejO9lvdCKcWMh2YQGRhpdCRhY0y5ld6N0xWqlvbizfZhrIg+y+hVhw1KJoQQQty9OX/FMGBWFBVLeLJoYGPK+3sYHQkweMN0IYR1+fXor7z353uU8y7H+FbjKeku86WE5V3tsPv3SOC+jUM4EH+JMasO4+PmSO/G5Qo+nBBCCJFHWmtG/nGQcWuO0qKyP2OfqY27s/WUV9KjJ4RAa82k3ZN4a+Nb1Amow4x2M6TIE/lGkztH71+VnlKKTx+txoPhAXzwazSjVx6SlTjFf/Tv35/o6GgAPv300zse37t3b3788cf8jiUsRO6vKCwys028umAX49Yc5al6ZZjUs65VFXkghZ4QRV62KZvhW4YzZscYOoR2YELrCXg6eRodS9iwf8/Ru5GjvR1jn6nN43WCGL3yMEPm7yQ9K6eAEwprNnnyZMLDw4G8FQKicJH7KwqDy+lZ9J2+jUV/n+KVNpX47NFqONhbX1llfYmEEAUmNSuVoWuG8sOhH+hXtR+fNvkUR3tHo2MJG3d1jt6tFnF1crDji8er81rbyizeeZrO4/5k76mLBZhQWIMTJ05QpUoVunXrRlhYGI8//jipqak0b96cqKgohg0bRlpaGjVr1qRbt24AzJw5k+rVq1OjRg169Ohx7Vzr16+nUaNGhIaGSu+PlZD7KwqrMxfTeWLiZrYcS+SLx6szuFVFq12V3Lr6F4UQBSYxLZGXVr/EvsR9vF3/bZ6q8pTRkUQRcb1H79bHKKUY1KICYYGeDFu4h0fG/ckLzcszsHl53JzkV1eBWjYMzuyx7DlLVoOHRtzxsIMHDzJlyhQaN25M3759GT9+/LXHRowYwdixY9m5cycA+/btY/jw4WzatAk/Pz+SkpKuHRsfH8/GjRs5cOAAnTp14vHHH7fs6ynM5P4KkWeHzl6m99StXEzLYkrvejSr5G90pNuSHj0hiqCYSzH0WNaDwxcOM6r5KCnyRIG6vurmnT8BbVklgBVDm/FIjVJ8s/oIzb9Yy9ytJ8nOMeV3TGEFypQpQ+PGjQHo3r07GzduvOWxq1ev5oknnsDPzw8AH5/rS5t37twZOzs7wsPDOXv2bP6GFnkm91cUJpuPJvLYhE1kmTTzn2to9UUeSI+eEEXOrvO7eGnVSwBMbjuZGv41DE4kipq73SbPy82Rr56syTP1g/ls2QHeXLSH8WuP0L9JKE/UDZIevvyWh56Z/HKzBXvuhbOz87U/ywI//yL3V4g7+mXXaf7vh12U8XFlRt9Igoq7GR0pT6RHT4giZM3JNfT/vT8eTh7Maj9LijxhjNssxnI7dUN8+PH5hkzuWZcSni68/8s+Gny6ind/3sueuIvyBs8GnTx5ks2bNwPw/fff06RJk3887ujoSFZWFgAtW7ZkwYIFJCYmAvxjaJ+wTnJ/hbXTWjNp/TEGz91BjTJeLBzYqNAUeSCFnhBFxvwD8xmydggVvCsw66FZlC1W1uhIooi62YbpeaWUonV4AAsHNmLhwIY0r1yC+VGxPDx2Iw99vYFv1x0lJvGKhRMLo1SuXJlx48YRFhbGhQsXGDhw4D8eHzBgANWrV6dbt25ERETw9ttv06xZM2rUqMErr7xiUGqRV3J/hTXLMWk+/DWaT5bup321kszqVx9vNyejY90VVZg+Aa1bt66OiooyOoYQhYpJmxjz9xim7J1Cs6Bm/O+B/+HmaD2fRimltmut6xqd435I23R3ElMyqDN8JR92iqBXo5D7Pt/FtCx+3XWaBdvj2BWbDECVkp60jShJyyolqFraC/t7qSqLsP379xMWFmZohhMnTtCxY0f27t1bINe72Wu21fZJ7q8Qt5eelcOQeTtZvu8M/ZqU4+32YdhZ0e+RvLZNNjmx4cNf9xF9+pLRMYQwnCab044zuGj/F8WzH+Dckafoc2RXvl83vFQx3n84It+vIwqnqx8vWup3pperI90blKV7g7LEJqXy+74z/L7vDGNWH+brVYfxdnOkcXk/Glfwo2lFP8r4WM8HHUIIIazLhSuZ9J8Zxd8nL/BOhzD6Nw01OtI9s8lCTwgBOaQS6ziRVPsDlMjqgm9OOxTW82mUKLqu76Nn+f8fy/i40b9pKP2bhpKQksGfRxLYcDiBjYcTWLInHoDS3q7UDSlO3RAf6pYtTqUAT+nxs0IhISEF1tsjCp7cX2GNYpNS6TV1K3HJaYx9ujYdqgcaHem+2GShJz0Joqg7c+UML6x6gczk43za+FMeLv+w0ZGEuObqjIH83l/Wz8OZR2qW5pGapdFac/R8ChsOJ7DtRBKbjiayeOdpADydHahdtji1g4tTvYwXNYK88XEvXPMwhBBC3J89cRfpM30rWTma2f3qE1nO585PsnI2WegJUZQdvnCYgSsHkpKVwrjW42hUqpHRkYT4B32Pq27eD6UUFUp4UqGEJ30al0NrTWxSGlExSWw7cYGoE0msP3z+Wrag4q7UKONNjSAvqgd5U7W0Fx7O8itTCCFs0ZqD5xg052+Kuzkxb0A9KpTwNDqSRchvLSFsyNb4rQxZMwRXB1dmtJtBZZ/KRkcS4j/uZ9VNS1FKEezrRrCvG4/WDgLgcnoWe05dZHfcRXbHJbPzZDJLdsfnHg8V/D2oHuRNjdxevyqBnjg72Bv3IoQQQty3+dtO8tZPe6lS0pNpvetRopiL0ZEsRgo9IWzEkmNLeOfPdyjrWZYJrScQ6FG4x5UL23Vtjp6VzRn1dHGkUXk/GpX3u/azhJQM9sRdZFdcMrvjLrLu0DkW/h0HgJO9HWGlilGrjDc1y3hTo4w3Ib5u+TL3UAghhGVprRm18jBjVh3mgUr+jO9W2+ZGbtjWqxGiCNJaM23fNEZtH0XdgLqMbjEaL2cvo2MJcUsFNUfPEvw8nGlRpQQtqpQAzP/eTl9MZ1dsMrtik9kRm8z8bbFM33QCMK8AWiO38KuZ2/Pn6+Fs4CuwfSEhIURFReHn54eHhwcpKSlGRxIWJPdX5IesHBNvLdrDgu1xPFEniE8frYajve1tLy6FnhCFWI4phxFbRzDv4DweCnmI4U2G42Qvi0gI62bEHD1LUUpR2tuV0t6utK9m7jXPzjFx5HwKO08msysumR0nkxm7+jCm3NdZoYQH9cv50CDUl/qhPpTwtJ1hQQVFa43WGjs723sjJuT+ioKVkpHNC3P+Zv2h87zcqiJDWle02ZEYUugJUUilZafxxvo3WBO7ht4RvRlaZyh2Sn5JCut3fXsFg4NYiIO9HVVKFqNKyWI8FRkMQGpmNnviLrL95AW2Hk9i8c7TzPnrJAChfu7UD/WhWSV/mlT0t7mhQpZy4sQJ2rZtS/369dm+fTuvv/46I0eORGtNhw4d+Pzzz42OKO6D3F9hhHOX0ukzfRsHzlxmxKPVrrXZtsqw3y5KqTLATCAA8/6532mtvzYqjxCFyYX0C7y4+kX2nN/DsMhhdAvrZnQkIfLs+obpNlLp3YSbkwP1Q32pH+rLC83NvX7R8Zf461gSfx1P5Lfd8czdGoujvSKynA8tKpegVVgA5fzcjY7+H59v/ZwDSQcses4qPlV4I/KNOx53+PBhZsyYQXBwMA0aNGD79u0UL16cBx98kJ9//pnOnTtbNFdRJPdXFBVHzl2m19RtJF3JZHLPuteG5NsyIz9GzAZe1Vr/rZTyBLYrpVZoraMNzCSE1Yu9HMvAlQM5c+UMXzX/itZlWxsdSYi7Yms9ennhYG9H9SBvqgd58+wDoWTnmNgec4HVB86x+sA5hi/Zz/Al+wkPLEbnWqXoVKM0Jb1kiGfZsmVp0KABixcvpnnz5vj7+wPQrVs31q9fL4VAISf3VxSUbSeS6D8jCkd7xfznGlA9yNvoSAXCsEJPax0PxOf++bJSaj9QGpBCT4hb2Juwl0GrBpGjc5j04CRqlahldCQh7pq+VugVoUrvXxzs7a71+L3ZPozYpFT+iD7LLztP8enSA3y27ACNy/vRvUEwrcMCcDBwkYC89MzkF3d36+vhtDVyf4WtW7onniHzdxLk7cr0PpEE+7oZHanAWMWEHqVUCFAL+Osmjw1QSh1WSp0/efJkQUcTwmqsj1tP39/74urgyqyHZkmRZzBpm+7d9cVYjM1hTcr4uNGvSTkWv9iE1a82Y3DLihxPuMLzs/+m6f/WMGn9MVIzs42OaZjIyEjWrVtHQkICOTk5zJ07l2bNmhkdy2oVtvZJ7q/IL1M2HmfQ939TrbQXCwc2KlJFHlhBoaeU8gAWAkO01pf+/bjW+jutdUWttX9wsG1PmBTiVhYcWsBLq1+inFc5ZrefTTmvckZHKvKkbbp3pkK86mZBCPX3YGibSqx/vQWTetalnJ87nyzdT9PP1/Dd+qNkZOcYHbHABQYGMmLECFq0aEGNGjWoU6cOjzzyiNGxrFZha5/k/gpLM5k0H/8Wzce/RfNgeABz+tenuHvRW5Xc0KW+lFKOmIu8OVrrRUZmEcIaaa0Zu3Ms3+3+jialm/Blsy9xcyxan0YJ23N9w3RxO/Z2ijbhAbQJD2B7TBKjVx7m06UHmLs1lg86RdCskr/REfNVSEgIe/fuvfb9008/zdNPP/2f406cOHHtz7LHWuEh91fkl/SsHF5dsIslu+Pp3SiEdzuGY19Eh5AY1qOnzJMzpgD7tdZfGZVDCGuVZcrinT/f4bvd3/FoxUcZ03KMFHnCJlzfML1o/uK9F3XK+jCrX31m9o1EAb2mbuWV+Tu5klF0h3MKIcS/Jadm0nPKVpbsjuet9lV4/+GiW+SBsT16jYEewB6l1M7cn72ltV5qYCYhrEJKZgqvrH2FzfGbeaHmCzxf/Xl5UyxsxtUevSL8u/eePVDJn2VDmjJ+zVG+WX2YnXHJjO9WmyolixkdTQghDBV3IZXe07ZxMjGVMU/XolONUkZHMpyRq25uREbuCPEf51LPMWjVIA5fOMxHjT6iS8UuRkcSwqKkR+/+ODvYM7RNJRqE+jJ43g46j/uTsU/XpnV4gEWvo7UuMvfo6kqwRYncX2FL9p66SJ/p20jPymFG30galvc1OpJVMHwxFiHEdUeTj9J9aXdOXjrJuFbjpMgTNkkjPXqW0LC8L0sHN6VygCfPzd7Or7tOW+zcLi4uJCYmFok3yFprEhMTcXEpOvsWyv0VtmT9ofM8+e1mHO0UCwc2kiLvBoYuxiKEuC7qTBSD1wzG2d6Zae2mEe4bbnQkIfKFrLppOf6eznz/bAP6TNvG0Pk7cXe2p2WV++/ZCwoKIi4ujvPnz1sgpfVzcXEhKCjI6BgFRu6vsBULomJ5c9EeKpTwYHqfSEp6SUF/Iyn0hLACy08s560NbxHkGcSE1hMo7VHa6EhC5BvTtbGbxuawFe7ODkzpXZenJ21h8Nyd/DyoERVKeN7XOR0dHSlXTrZxsVVyf0Vhp7Vm7OojfLniEI0r+DKxex08XRyNjmV1ZOimEAabuW8mr617jap+VZn10Cwp8oTN09KjZ3GeLo5816MuLo52PD/7b9Kzit5ee0KIoiE7x8RbP+3hyxWH6FKrNNN6R0qRdwtS6AlhkBxTDp9v/Zwvor6gTdk2THpwEl7OXkbHEiLfaVl1M1+U8nZl1JM1OXIuhVErDhkdRwghLO5KRjbPzoxi7tZYBrUoz1dda+DkIOXMrcjfjBAGSM9O57X1rzF7/2y6h3VnZLORONs7Gx1LiAJhujZyUyo9S2ta0Z9n6gfz3YZj7I+/ZHQcIYSwmPOXM3h60hbWHTrP8M5Vea1tlSKzcuy9kkJPiAKWnJ7MgBUDWBmzktfqvsYbkW9gp+Sfoig6pEcvf73etjKezg58vvyA0VGEEMIijp1P4dEJf3Lo7GW+61GX7g3KGh2pUJB3l0IUoLjLcfRY1oN9Cfv4otkX9IzoaXQkIQqcSfbRy1febk4MalGBtQfPs/V4ktFxhBDivmyPucBjEzaRmpHDvAENLb5nqC2TQk+IAhKdGE33pd1JTE/kuwe/o21IW6MjCWGIqz16Uufln16NQiju5si0P48bHUUIIe7Z7/vO8MykLXi5OrJwYCNqlvE2OlKhIoWeEAVg46mN9F7eGyd7J2Y9NIs6AXWMjiSEYa5u0SyrbuYfF0fZ9/i1AAAgAElEQVR7utYrwx/RZzmdnGZ0HCGEuGszN5/g+dnbqRJYjIUDGxHi5250pEJHCj0h8tlPh3/ixVUvUrZYWWa3n0157/JGRxLCUCaZo1cgutcvi0lr5m09aXQUIYTIM5NJ89my/by3eB+tqpRg3rMN8PWQBevuhRR6QuQTrTUTdk7gvU3vUT+wPtPbTaeEWwmjYwlhuOtz9IzNYevK+LjRoJwvy/edMTqKEELkSUZ2DkPm7+Tbdcfo3iCYid3r4Opkb3SsQksKPSHyQZYpi/c3vc/4XeN5pPwjjG01FndHGXIgBFzv0ZPFWPJfm/AADp1NISbxitFRhBDiti6mZdFr6lZ+2XWa19tV5uNHquJgL6XK/ZC/PSEsLDUrlZdWv8RPR37i+RrP83Hjj3G0czQ6lhDWI7dHT+bo5b82uavTrYg+a3ASIYS4tdPJaTwxcRPbYy4w6skavNC8gnwYaAEORgcQwpYkpCXwwsoXOHThEO83fJ/HKz1udCQhrI7M0Ss4ZXzcqFLSk5XRZ+jvsRlWvAvpRXwj9aF7wbOk0SmEELn2x1+iz7RtXMnIZnqfSBpX8DM6ks2QQk8ICzl+8TgDVw4kKT2JMS3H8EDQA0ZHEsIqXZujh1R6BaFRqBeVoz6ExasguBEENzA6krEc3YxOIITI9eeRBJ6ftR13Zwd+eL4hYYHFjI5kU6TQE8ICdpzbwUurX8Je2TOt7TQi/CKMjiSE1ZJ99ApQ5hWejXuXQLt1JNV6EZ+HPwI7WdhACGG8n3bE8fqPuynn5870PpGU8nY1OpLNuWWhp5R6JQ/Pv6K1/taCeYQodFbErGDY+mEEegQyofUEyniWMTqSEFbNJHP0CkbKefj+CUqe38VbWf2oFzyQLlLkCSEMprVm/NqjfPH7QRqE+vBtj7p4ucpaBvnhdouxvAZ4AJ63+Xo1vwMKYc3m7J/Dq2tfJcw3jFkPzZIiT4g8kB69ApB4FKa0hnMHMHWdzSK7Nuw9VcTn5gkhDJdj0ry7eC9f/H6QTjVKMaNvpBR5+eh2Qzdnaa0/ut2TlVKyXrwokkzaxFdRXzEjegatglsxoukIXBxcjI4lRKGQ26EnPXr5JXYbfN8VlB30XoJ9UB3CAv9k76mLRicTQhRhaZk5vDR3Byv3n+X5ZuV5vW1l7GRVrnx1y0JPa/36nZ6cl2OEsDWZOZm8vfFtlp9YztNVnuaNem9gL8OhhMgzWXUzHx1YAj/2hWKloNuP4FsegKqlvPh5xylMJi1vrIQQBS4xJYN+M6LYFZfMR49E0LNhiNGRioR7nqOntf7K8nGEsG4XMy4yZM0Qos5G8UqdV+gd0Vv2eRHiLl1bdVP+6VjW1kmw7HUoVRuemQ/u15cor1TSk8sZ2Zy7nEFJLxl9IIQoOCcSrtB72lbiL6YzoVsd2lWV7U0Kyu2Gbnrm/rcyUA/4Jff7h4Gtlri4Umoq0BE4p7WuaolzCpFf4lPiGbhyIDGXY/i86ee0D21vdCQhCqXrc/Sk0rMIkwlWfQh/jobK7eGxKeD0zy0E/D2cAEi8IoWeEKLg7Dh5gX4zotBa8/2zDahTtrjRkYqU2w3d/BBAKbUeqK21vpz7/QfAEgtdfzowFphpofMJkS8OJB3ghZUvkJ6dzretvyUyMNLoSEIUWlpW3bSc7AxYPAj2LIC6/aD9FzfdPsHH3RmApCuZBZ1QCFFErYg+y0tz/8bf05kZfSIJ9fcwOlKRk5d99AKAG38zZOb+7L5prdcrpUIscS4h8sum05t4Ze0reDh6MOOhGVQsXtHoSEIUalfn6EmZd5/SkmF+dzixAVq9D02G3nI8rI+7eVU7KfSEEAVh9pYY3lu8l6qlvZjSqx7+ns5GRyqS8lLozQS2KqV+yv2+MzAj/yIJYT1+OfoL7//5PqHeoYxvNZ4Ad4t8xiFEkSY9ehZwMQ7mPAEJh6HLd1DjydsefrVHLzFFCj0hRP7RWjPyj4OMW3OUllVKMPaZWrg55aXcEPnhjn/zWutPlFLLgSa5P+qjtd6Rv7GuU0oNwLynn7e/v39BXVYUcVprJu2ZxDc7vqF+YH1GNR+Fp5PnnZ8oigxpm+6dSfbRuz9n98HsxyEzBbr/CKHN7/gUb1dH7JT06BUV0j4JI2Rmmxi2cDeLdpzi6cgyfPxIVRzsb7dlt8hvefrb11pvB+YCPwGJSqngfE31z2t/p7WuqLX2Dw4usMuKIizblM3HWz7mmx3f0CG0AxNaTZAiT/yHtE33Tsuqm/fu2DqY2s785z7L8lTkAdjZKYq7OZEohV6RIO2TKGiX0rPoM30ri3ac4tU2lfi0SzUp8qzAHXv0lFKdgC+BUsA5IBg4AETkbzQhCl5qViqvr3+ddXHr6F+tP4NrDZaVAYWwMM3VffTk39Zd2f0D/PwC+FU075HnVfqunu7j7kTSlYx8CieEKKrOXEyn97StHDmXwhePV+eJumWMjiRy5aXU/hhoABzSWpcDWgNbLHFxpdRcYDNQWSkVp5TqZ4nzCnEvEtMS6fd7Pzac2sA79d/h5dovS5EnRD4wyRy9u6M1bPgKFj0LwQ3MPXl3WeTB1UJPevSEEJZz8Mxluoz/k9ikVKb2ridFnpXJy+zILK11olLKTillp7Veo5QabYmLa62ftsR5hLhfMZdieH7F8ySkJTC6+WhaBLcwOpIQNkvm6N0FUw4sfQ2ipkDVx6HzeHC4t9XrfD2cOHDmsoUDCiGKqs1HExkwKwpXR3t+eL4hEaW8jI4k/iUvhV6yUsoDWA/MUUqdA67kbywhCs6u87t4cdWLKBRT2k6hun91oyMJYdNkjl4eZabCwv5wcAk0HmLeQsHu3ue8SI+eEMJSftl1mv/7YRfBvm5M71OPoOJuRkcSN5GXQu8RIA0YCnQDvICP8jOUEAVl9cnVvL7+dUq4lWBi64kEF5NJ60LkN61ljt4dXUmA75+EU9uh/UiIfPa+T+nj7kxyahbZOSZZJEEIcU+01kzacIxPlx4gMsSHST3r4uXmaHQscQu3LfSUUvbAb1rrFoAJ2T9P2JB5B+bx2dbPiPCN4JuW3+Dr6mt0JCGKhKtz9KTMu4WkYzD7Mbh0Gp6cDWEdLXJaX3cnAC6kZsnmxUKIu5Zj0nz8WzTTN52gQ7VAvuxaAxdHe6Njidu4baGntc5RSpmUUl5a64sFFUqI/GTSJr7++2um7p1K86DmfP7A57g5ypADIQqK9OjdRtx2+L4raBP0+hXKRFrs1D7XCr1MKfSEEHclPSuHl+ft4Pd9Z+nfpBxvtQ/Dzk7acGuXl6GbKcAepdQKbpibp7UenG+phMgnmTmZvPvnuyw9vpSulbryZv03cbDLyz8DIYSlyKqbt3BwGSzoAx4loPsi8Ktg0dNf7dHbcfICWTkmi567MKkU4ImjDF0VIs8uXMmk34xt7IhN5t2O4fRrUs7oSCKP8vIOd1HulxCF2qXMSwxdM5StZ7bycu2X6Ve1n2yfIIQBTFrGbv5H1FRY8ioE1oBnfjAXexZW0ssFgDcW7rH4uQuTrW+1okQxF6NjCFEoxCal0mvqVuKS0xj3TG3aVws0OpK4C3cs9LTWMi9PFHpnrpxh4MqBnLh4gk+bfMrD5R82OpIQRZ6M+sG8BOnq4bBhJFRsC09MAyf3fLlUqL8H8wc0IDktK1/OX1gUc5WFI4TIi91xyfSdvo2sHM2c/vWpF+JjdCRxl25Z6CmlvtNaD7jdk/NyjBBGO3ThEANXDuRK1hXGtx5Pw1INjY4kRJFmkjl6ZtmZ8Otg2DUXaveCDl+Bff4OJa8fKotOiSJGa/MqtklHIfkkXDkPKefMP7tyHtIuQHY6ZGdATob5v6YcsHcCByewdzb/19Ed3H3BzQ/c/cDdHzwCwCfU/OXsYejLzDHlcPrKaU5eOknMpRjOpp4lMS2RpPQkktKTSMtOIzMnk0xTJtmmbJzsnXC2d8bZ3hk3Bzf8XP3wdfXFz9WPku4lSbrgxcglSRR3Kc68AfWoUMLT0Ncn7s3tfqN0Vkql3+ZxBciu0sKq/RX/F0PWDMHNwY0Z7WZQ2aey0ZGEKPJMso8epF+CH3rAsbXQ8h1o+n9F/C9ECAtITYLTOyB+J5yNNhd3iUch49I/j7NzNA+PdvcD1+Lg5msu5hxcwMEZlB3kZOUWf5nmr8wrkHAErmyGtCTzgkk38ggAn/LmubWBNSCwJgREgKOrxV9mlimLQ0mH2Je4j+jEaPYl7uNo8lGyTNd76x3sHPBx8cHXxRcfVx9KOZTCyd4JJzsnHOwczEVfTibpOelcybrC8YvHiTobRXJG8rVz2JcDnLwYsaMKEX4RRPhGUM2vGoEeMnyzsLhdofdaHp6/wVJBhLC0JceW8M6f7xBSLIQJrSdQ0r2k0ZGEEFzfML3I9uhdOg1znoDzB6DzBKj5jNGJhCh8tDYXcTF/mr9Objb32F3lFQy+5aH6k+b/+lYA77LmAs/F6/4+WDHlmHsCL502b4eSdNT838RjsP83+Hum+ThlDwHhENwIyuZ+3cP8W5M2EZ0YzV/xf7Ht7DZ2nN1Banaq+WU6exHuE073sO6ULVb22pefq99dr0OgtWbkimjGb4iierlMOtZx4NSVGPYn7Wdm9EyyTdkAlHIvRb2S9YgMjKR+yfoEuAfc9WsSBeOWhZ7MzROFldaaqXunMvrv0dQrWY/RLUZTzKmY0bGEELmuDt0sknXeuf0w+3FITzYvulKhldGJhCg8Mi6be8EP/Q5HVsLlePPP3f3NRVTdflCqprlHzbV4/uWws88dvukHgdX/+ZjWcOkUxO+C0zsh9i9z4bf1W/PjAVWhYhuo+CAERd5yuHZadhp/xf/F2ti1rItbR0JaAgDlvcrzcPmHqRtQl6p+VSntUdoiC8tl5Zh4c9EeftwexxN1avLpo9X+sTptZk4mhy4cYtf5XUSdiWJt3FoWH10MQJhPGC2CW9CiTAsqF68sC91ZEVlXXtiUHFMOn239jPkH5/NQyEMMbzIcJ3sno2MJIW5wdR89VdSW3Ty+AeZ1Mw/l6rPsv28QhRD/lZYMB36DfT/B8fXmYZTOxaB8SwhtDmUbg19F6/nkSCnwCjJ/Velg/ll2prnwO7EBjqyCP8fAxlHmnsUqHSGiC4Q2J01nsy52HUuPL2Xz6c2k56Tj4ehB49KNaRbUjIalGuLn6mfxyCkZ2bww52/WHzrPy60qMqR1xf8Ua072TlT1q0pVv6p0C+uGSZs4dOEQf576k7Wxa5mwcwLjd44n0D2QlsEtaV+uPdX8qknRZzAp9ITNSMtO4431b7Amdg19IvowpM4Q7JTslSSEtbk+dNPYHAVqz4/w80AoXg66/wjewUYnEsJ6ZWfCwaWwax4cXWUu7ryDIXIAVGoHwQ3AvhCtnurgBGXqmb+avgLpF+HoGji4jOz9v7Ll4EKWeBVnlasLaeRQwq0Ej1V6jGZBzagbUBfHfHyt5y6l02f6Ng6cucznj1XjyXp5a5vslB1VfKpQxacK/ar1IyEtgQ1xG1gdu5oFBxcwZ/8cyniWoUNoBzqU60CIV0i+vQZxa3ku9JRSblrr1PwMI8S9upB+gRdXv8ie83sYFjmMbmHdjI4khLiFIrVhutaweSz88Y655+GpOfk7pEyIwizhCPw9A3Z+D6kJ4FnKXNxFPAqla1tPr939cvEitkwdFqaf4OesgySmJ+KJPe1TrtDh8kXqFHPHrow3eFfO14L2yLnL9Jq6jQupmUzuVZcWle99/04/Vz+6VOxCl4pduJx5mZUxK1lybAnf7vqWibsmUt2vOo9Veox2Ie1wc3Sz4KsQt3PHQk8p1QiYDHgAwUqpGsBzWusX8jucEHkReymWgasGcubKGUY1H0WrsjLnRQhrVmTm6Jly4Pe34K+J5qFZnSeCo2zULcQ/mHLMQzO3TjIPbVT2UPkhqNPbPDzTzt7ohBaTlZPFmtg1LDi0gC3xW7BX9jQNakrnCp1pWropTlnpsHehudhd/gaseA/CH4GGg8xzDy1o6/Eknp0ZhaO9HfMHNKRakJfFzu3p5Hmt6Dt75SzLji/jpyM/8f6m9/li2xd0DO3IE5WfoFLxSha7pri5vPTojQLaAr8AaK13KaUeyNdUQuTR3oS9DFo1iBydw+QHJ1OzhGUbQiGE5eV26Nn23I2sNFj0LOz/FRq+CG0+BjsZSi7ENZmpsHMObB4HF46bV8Rs9R7U7AaetrVKdnxKPPMPzuenIz+RlJ5EoHsgg2oOokuFLv9csdLeCer2MX/F7zYv4rJrHuz5Aco9AI0GQ4XW9/0p2ZLd8Qz9YSdBxV2Z0SeSMj7518MW4B5A76q96RXRi7/P/c2CQwtYdHgR8w7Oo4Z/DbpW7krbkLY42zvnW4aiLE9DN7XWsf/6hZyTP3GEyLt1set4bf1r+Lj4MKH1BMp5lTM6khAiD7TWtj0/LzUJ5j4FsVuh7WfQUAbACHFNahL89S1smwSpiVC6LrT50LwoiQ313gHsOr+LWdGzWBmzEo2mWVAzHq/0OI1LNcb+Tq81sDp0GAmt3oXtM2DLBJjzOPiHQaOXoHrXexrWOWXjcYYviaZ2cHEm96xLcfeCWbBOKUWdgDrUCajDsHrDWHx0MT8e+pG3N77Nl1Ff8lTlp+hauSu+rr4FkqeoyEuhF5s7fFMrpRyBl4H9+RtLiNv74eAPfPLXJ1TxqcK4VuPyZRUqIUT+MGltu715F07A7McgORaemA4RnY1OJIR1SLtg7r3bMgEyU6DSQ9B4MAQ3tKlx3NmmbFadXMXM6JnsPr8bT0dPeoT34Jkqz9zbRuMuXua/p/rPm1ce3fQNLH4B1n8BzV6Hal1vuUXDjUwmzSdL9zNl43HaRZRk9FM1cXE0prD2dvGmV0Qveob35K8zfzErehbjd41n8p7JdCzfkR5hPahQvIIh2WxNXgq954GvgdLAKeAPYFB+hhLiVrTWfLPjGybtmUTT0k0Z2WykTOoVopDR2kZX3Dy9w7wRek4W9FwMZRsanUgI46VfNBd3m8dBxiUI7wzNh0GJMKOTWdTlzMssOryI7/d/z+krpynjWYZhkcPoXKEz7o7u938BByeo8aS5J+/Q77DmE/NKvutHQrM3oNrjt+wRTc/K4dUfdrFkTzy9G4Xwbsdw7K2gEVZK0SCwAQ0CG3Ds4jHmRM/hl6O/sOjwIhqVakTP8J40KtXIdj8YLAB3LPS01gmALGEoDJeVk8UHmz/gl6O/8FjFx3inwTs42MkOIUIUNiZtg/PzDq+AH3qBmy/0Xgr+ssiAKOKyM8wLEW34CtKTzUMzm78JJasancyiEtMSmb1/NvMOzCMlK4W6AXV5I/INmgU1u/PwzHuhFFRuB5XawoElsHYE/DQANoyE1h9A5fb/6CFNTs3k2ZlRbDtxgbfbh9G/aTmrbH9DvUJ5t+G7vFTrJRYcWsDcA3N5fuXzVPCuQL9q/WgX0k7e892DW/6NKaW+4fqc+f/QWg/Ol0RC3ERKZgqvrH2FzfGbGVRzEM9Vf84qGyohxJ1prW1rq/S/Z8KvQyAgArotsLmFJIS4K1pD9GLzipHJMVChDbR8x+KrRhotPiWe6fums/DwQjJzMnkw5EH6VO1DhG9EwQRQCsI6mgu7A7/Cqo9h3jPmbVwe/BhK1yE2KZXe07YSm5TGmKdr0alGqYLJdh+8Xbx5tvqz9I7ozbITy5i2dxpvbniTsTvG0ieiD50rdpaFW+7C7UrjqAJLIcRtnEs9xwsrX+Bo8lE+bvwxnSvInBchCjONjeyhpzWs/QzWfQ7lW0HXGeDsaXQqIYxzegcsfwtOboIS4dB9EVSwrS2PTlw8wZS9U/jt6G8APFz+YfpU7WPcgnB2duYtGCq3N2/LsHYETGpJcvlOvBjTjvPZfszsF0mD0MK1yImjvSOdyneiY2hH1sWuY/KeyQz/azgTd0+kR3gPulbqioeTh9Exrd4tCz2t9YyCDCLEzRy5cISBqwZyKeMSY1uNpXHpxkZHEkLcJ5PJBlbdzMky9+LtnA01u8PDo/N1Y2MhrNqleFj1Eeyaax6+3HEU1OqZp0VCCosDSQeYvGcyf5z4A2d7Z56s8iS9wnvd2wIr+cHeEer1h+pPEvPLZ5TYO4kFaikpNfriExhpdLp7ZqfsaBHcguZlmrPtzDYm75nMqO2jmLxnMk9Vforu4d3xcfExOqbVysuG6b/y3yGcFzH3+H2rtU6/14srpdphXujFHpistR5xr+cStmfbmW28vOZlnO2dmd5uOmG+tjVxW4iiqtDP0cu4bJ6Pd3QVNBtmXliiML8eIe5VZqp5Fcg/R4Mp27w6ZNNXzStF2ogd53YwafckNpzagIejB/2r9adbWDer3QZgwZ5k3tzRhAb+9ZgU9Ds+uybBoQXm+ZF1+xbaD6SUUkQGRhIZGMm+hH1M3jOZyXsmMyt6Fo9VeozeEb0p6S7D5v8tLx+1HAP8gbm53z8JXAYqAZOAHvdyYaWUPTAOaAPEAduUUr9oraPv5XzCtiw/vpy3Nr5FkGcQE1tPpJSH9Y8rF0LkjUYX3rro8hnzyppn90Gnb6B2T6MTCVHwTCbYswBWfQiXTpmHDrb+EHxsYz9brTWbTm9i0p5JbD+7neLOxRlcazBPVnmSYk7FjI53U1prvll9hK9WHKJJBT8mdK+Nq0sXaDoIfn8Llr0O2ybDg8Oh4oOF+sOpCL8IRrUYxbGLx5i6ZyrzD8xn/oH5PFz+YfpW7UuIV4jREa1GXgq9Rlrrejd8/6tSapvWup5Sat99XDsSOKK1PgaglJoHPAJIoVeEaa2ZGT2TkVEjqV2iNmNajsHL2XY+GRRCXN1eoRC+yTh/EGY/bt7k+Zn5ULGN0YmEKHgnt8DyN+H03xBYEx6bDGUbGZ3KIkzaxKqTq5i0exL7k/YT4BbAsMhhPFrxUVwdXI2Od0vZOSbe+Xkv87bF8mit0ox4rDpODnbmB0tWg56/wKHl8Mc78H1XCG0BbT8xLyBViIV6hTK8yXAG1Rx0bWGcn4/8TJuybehfrb+MBCNvhZ6HUipYa30SQCkVDFyd/Zh5H9cuDcTe8H0cUP/fBymlBgCvAd7+/v73cTlh7XJMOYyMGsns/bNpU7YNnzX9TFZWElZL2qZ7Z94w3egUdylmM8x9CuydoM8SKFXL6ERC3FK+tE8XYmDl++ZNuz0DofNEqP6keTGQQi7LlMWy48uYvGcyxy8ep2yxsnzU6CM6hnbE0cqHOl7JyObF7/9mzcHzvNiiAq8+WOm/Q+OVgsoPmReNippiXrBlYhPziIQWb4NHCWPCW0igRyBv1n+TAdUHXNvq4o+YP2hSugnPVnuW2gG1jY5omLwUeq8CG5VSRwEFlANeUEq5A/m+YIvW+jvgO4C6devecrsHUbilZ6fz1sa3WBGzgh7hPfi/uv+HnSr8vzyE7ZK26d4Vuh69fT/DogHgHQzdf4TiIUYnEuK2LNo+pV+CjV/B5vGg7MzzUhsPBicLbAJusPTsdH468hPT907n9JXTVC5emS+afUGb4Db5sweehZ2/nEHf6dvYd/oin3SpSrf6ZW//BAcnaDDQXKCv+9w8lHPPQmj6CjR4ARxdCiZ4PvF19eXl2i/Tp2of5h+Yz6zoWfRa3ovaJWrzbPVnaVyqceGeH34P8rJh+lKlVEWgSu6PDt6wAMvo+7j2KaDMDd8H5f5MFDHJ6ckMXjOYned28lrd1+gZIXNehLBlJl2IVt3cPN48v6VMJDw9D9xkdTdRRORk5y7X/xlcOQ81noaW74JXaaOT3bfLmZeZf9BcCCSlJ1HTvyZvN3ibpqWbFppC4Nj5FHpN20rC5Uwm9axLq7CAvD/ZzQce+ty8Sucf75rnWm6fZp5nGdGlUM/fAyjmVIxnqz9L9/DuLDq8iGl7pzFw5UDCfMLoX60/rYJbFYpC3hLyuu5tHSAk9/gaSim01jPv89rbgIpKqXKYC7yngGfu85yikIm7HMfAlQM5nXKaL5p9QduQtkZHEkLkM5MGrH3LdJPJPJ9lyzgIexgenQSO1jtHRwiL0RoO/Q4r3oWEQ+YNuJ/5AUoX/uFviWmJzNk/h7kH5pKSlULjUo3pX60/dQLqFJoCD2B7TBL9Z0RhpxRzBzSgZhnvezuRX0V4Zh4cWwu/vw0/9oG/JkLbzyCojkUzG8HVwZVuYd3oWqkrvx37jSl7p/DqulcJKRZCv2r96BDaAUc76x6ae7/ysr3CLKA8sBPIyf2xBu6r0NNaZyulXgR+x7y9wlSt9f0s7iIKmX2J+xi0chBZpiy+e/A76gQU/kZFCJEXVt6jl5UOPz0H0T9D/eeh7adQRD79FUXc6Z3mDzhObADfCvDUXPPcrkJUBN1MfEo80/dNZ9HhRWTkZNC6bGv6V+tPuG+40dHu2vK9Z3h53g4CvVyY0TeSsr4WGEIb2hyeWw87ZsPq4TC5JVTrCq3fB6+g+z+/wRztHelSsQudyndixckVTN49mXf/fJfxO8fTO6I3j1Z8FBcHKxi2qrXF/63lpUevLhCutbb4HBSt9VJgqaXPK6zfhrgNvLruVYo7F2dq26mEeocaHUkIUUBMJiueo5eaBPO6wclN5mXIG75Y6N/kCnFHWsPiQbBzjnnD8/YjoU7vQrvn2lWHLhxi5r6ZLDm2BICO5TvSt2pfynkVzm0gZmw6wQe/7qNGkDdTetXF18OCC9bZ2UOdXlD1Udg4CjaNhf2/QqOXzHMynT0tdy2D2NvZ0y6kHW3LtmXjqY1M2jOJz7Z+xre7v6VHeA+erPwknk4GvM6TW8wFdq3uUOMpi546L4XeXqAkEG/RK4sia9HhRXy0+SMqFa/EuFbj8HeTFQuFKEqsZdXNjJwMktKSSEpPIiUrhdTkGNLWjSAtNYHUps+S5uFM5s5xmLQJjb7236ufezraOeJk74SzvTNO9k7X/uzh6EExp2J4Onni5exFMadiuJTyVHEAACAASURBVDm6GfxqhbgNpcDJAxoPMS/MUYg3PL+6B96MfTPYHL8ZF3sXulbuSu+I3gR6BBod756YTPr/27vv8KiqtY3Dv5VGQqgp1AABpXcIiGgABRXsHLGiUkQUFRHbsXusx4L6WbHTBRF7wUITFBBCh1CkE0ogCSRACCmzvj8mcFCBBJLJnvLc15WLTDLZ+0kgL/PutfZavPjjGt6bvZEeTavz5vVtiQjz0CyDchWh+xPuRn/af2D2S+5FWzoPhY6DoVyFoo7g9YwxJMYlkhiXyKLURXyw/ANeX/w6H6/4mKsaXcX1Ta4vm/2bty+CGc/BhukQWQ1P3NJQnEYvBkg2xiwADh/5oLX28lJPI37NWsvIZSMZuWwk59Q6h1e6vUJkqO+v2iUip8bi+RE9ay3pOelsydpCyv4UUg6ksH3/drYf2M6eQ3vIyMngYN7Bf35hBBBRGVJ+cr8BwSYYYwwGQ5AJIsgEYa0l15WLy7qKlScyNJJq5atRvXz1o3/WrVSX+Erx1K9cX/uFivMufsnpBCVyuOAw32/8nnHJ41i/bz2xEbEMazeMqxtd7dO/X4fzC7j/s+V8u2wHN3aqy1OXtyC4LOa+V6kLfT6GTne6F+SZ/hTMews63w0db/WLVVcB2ldvT/sL2rMqfRWjVo5iXPI4xiWPo3vd7tzU7CZax7Yu/fs3dy53/0zX/gARUXDB0+6FcTzwMy1Oo/efUj+rBJw8Vx5Pz3uar9Z/xZVnXskTZz/h9zfAisjxeWJEL/NwJkm7klietpy1GWtZnbGajJyMo583GKpHVqd2hdq0iGlBdHg0UeFRRIVHUXXvNirOeY3yoRWIuOx1yldvQURIBOVDyhe5h1a+K5/cglz3myuXw/mH2Z+3n6zcLLIOZ5GVm0Xm4Uz2HNrD7uzdpB5M5Y+df5B2KI0CW3D0ONHh0TSLbkbLmJY0j2lO69jWPv3iVKSspB9KZ/K6yUxaM4mMnAwaV23M8+c+T8/4nl6/B15RMg/lcdu4JOZvzODfPZtwe9cGZb9oTFx797Yy2xa6m5NpT8LcN6HT7ZBwi9+sRNw8ujkjuo5g54GdTFw7kSnrpvDzlp9pEd2CG5vdyIXxF5bsdau17ntff38d1k9zj5qf/5j7PnAPTostzvYKv3rs7BIQDuYd5L5Z9/H7jt8Z0noIQ1oP8anVrUSkdJXG/eYFrgIW717Mr9t+ZcGuBazJWIPFEhIUQsMqDekS14XGVRtTv3J94irGUTOyJmHBYf880JIJ8NMzENsU+n4GlU5taldIUAghQSGnPDUzz5XH9v3b2Zy1mc2Zm/lz358kpyfz2/bfsFiCTBAtYlpwbu1zSaydSLPoZtpbVKSQtZak1CQmr53MtK3TyHfl0yWuCzc3u5mONTr6xWuMHfsO0X/UAjalHeT/rm3DlW0d3taiTge46QvYtsC9B9+MZ2HOq9DmBvcefNFnOJuvlNSsUJN729/L7a1u55sN3zBh9QQemvMQrya9yjWNr6F3w95UK38KG8wX5MPqb9wN3s6l7ima5z/uHsGLOM3VUk+BKWqNFWNMJ+BNoCkQhnuFzIPW2koeT/c3CQkJNikpqaxPKyWQdiiNO6bdwbq963i80+Nc1egqpyOJlzHGLLLWJjidoyRUm07NsElLWLptH78+cN4pf+2mzE1MXjuZHzf/SNqhNMKCwmhTrQ0danSgY42OtIxpWbyr+NbC7Jdh5nPuFeeuGQfhZf7f2j8czDtIcnoyC3ct5Lftv7EybSUWS63IWlx+5uVcfsbl1KlYp+gDSalQffIumYcz+XbDt0xeN5lNmZuoFFaJK868gqsbXe2zC6wcz+qdWfQftYDswwW8d1N7Op8Z43Skf0pNhnlvw4rJUJAHTS5xT+mM7wJB/nNRymVd/Lb9N8Ylj2P+zvkEm2AS4xLp07AP59Y+98T78e1PhaXjYdFo2LcVos5wL2rT6rpS2Zi+uLWpOI1eEu497j7DvQLnzUAja+3DJU55ivypWAWCjZkbuWPaHWTkZDCi6wi6xHVxOpJ4Ib2QCjx3T1zCiu2ZzLy/W7G/ZlHqIt5f/j5zd8wlJCiErnFd6Rnfky5xXU59oZOCfPj+Xvdm0K2ug8vfhJDjjPZ5gYycDH7f/jvfbfyOeTvmAXBBvQu4tdWtNIlq4nA6/6f65LwCVwELdi3gu43f8fPmn8kpyKFVbCuuaXQNF8Vf5B3L4pei39encdu4RVQoF8KoAR1oWtP5C1AntT8VFrwPSR/Bob1QpZ579cg2N/jF1gzH2pq1lc///Jyv139Nek461ctXp3fD3vQ+s7d78RaXCzbOdDd3a38AVz7EJ7oXsWlySalu01OqjZ61NsEYs9xa26rwY0ustW1LKWux+XqxCiSLUxczdMZQQoJCeKf7OzSPae50JPFSeiEVeO76ZDHJO7OYcV+3Ip+7KXMTry16jZnbZhITEcO1ja+lT6M+xESc5hXuwwfcmwL/+TMk3u++R8JHpnntOriLSWsmMWntJA7mHaRXfC8e7Pjg6f8spEiqT85Zm7GW7zZ+xw8bf2D3od1UDK1Iz/o9uabxNX57keOLxSk8OGU5Z8RWYPTADtSsHOF0pOLLy4E137kvoG2aDSYIzugOra6Fxj39YnuGI/Jcefy67Vem/DmFudvnYrG0C4uh1740LtyTQlR4VXej264/xJzpkQzFrU3FWYwl2xgTBiw1xryEe5sF/xmTlVL3y5ZfeGj2Q9SqUIt3eryjaUYi8hfWFr2ItLWWiWsm8krSK4QGh3J327u5sdmNRISU4IXPgd3wyTWwcxlc+hokDDz9YzmgRmQN7ml/DwNaDGBs8lhGrRzFbzt+4/6E++l9Zm+/uC9JApe1luT0ZKZvnc6MrTPYkLmBEBPCuXHn8u8G/6Zrna6UCy7FfeO8iLWWd2Zt4OWf1nJ2g2jevak9lSN8bCGZ0HBo2cf9lrHJvSfjkgnwxSAILgcNL4BmV8KZ3X1+AZdQgukREkWP4LpsP5DEd3mpTI3M47nyobxQrw6danbiovrt6RJZlWiHsxan0bsJd2N3FzAcqAPoRis5rvHJ43lp4Uu0jm3Nm+e/SZVwz99oKiK+xb3YyImbkszDmTz+++PM3DaTxNqJPH3O0yUftUpbD+P/BQf3wHUT3VeYfVTlcpUZ2nYolzS4hKfnPc2Tc5/kj51/8FTnp/xuGpv4t0P5h1iSuoRZKbOYsXUGqdmpBJtg2ldvz7VNrqVnfE+qhld1OqZH5Re4ePKbVUz4YytXtKnFS31aUS7EQ3vklZWo+u7ZEt0egW1/QPJXkPy1e8TPBEHtBHfjd0Z3qNkagovTjjhsfyps+Q02zHTPCDmQCiaI2nU7c1uLIQxuejnrcjOYumkqUzdN5Ym5T2AwtIxtSde4rkcXCCvrC3JFTt30Jr46/SAQuKyLV5JeYWzyWLrX7c4LiS/oBYcUi6ZGBZ7bxy1iU9pBfhr+z/t292TvYfAvg9mctZnh7YZzU7ObSv4f49Y/YOJ17hcYN0x2LxfuJ1zWxYcrPuStJW/Rtlpb3ur+FhXD/GeKlNNUn0pXdl42q9JXsTh1MfN3zmfZnmXkufIIDw6nc63OnF/3fLrGdQ2Yi8TZufncPXEJ01bvZki3M3jgwsYElcUeeU5wudwbhK//Bf78BXYsASyERrpX9KzbGeIS3I1fpMPT0QvyYc8ad8btSbD5d0j/0/25cpXdo5KNerqb1eOMTlprSc5IZnbKbGZvm83K9JUAVIuoRvsa7UmonkD76u1pUPn0t8sozambvmfqQ7BrhdMpAsZhLI+adH4y2dxgK/Dg5nUEb9agb0Cr0RJ6veB0CvFSJ9pHL/NwJoN+HsTOgzsZ2WMknWp2KvnJVn8Lnw+CSrWg7xS/WQL8iCATxOBWg6lbsS4Pz3mYO6ffyfsXvK8LbXLKFu5aSJAJok7FOsRGxJboAou1ll0Hd7ExcyMb9m1g/b71rEhbwcbMjbisC4OhSVQT+jbtS6eanWhXvV3JpmX7oLQDh7llTBLLU/bx9BXNufnseKcjeVZQkLuhq9MBznsEDqa57+XbOg+2zHPv0Ufh4FPFWlCzFcQ0co8ORjWAqvXdi7uU4oIm5B50TzNNX/+/t7Q/IXUV5B9yP6dcJajbCdrdBPHnQo2iRyCNMTSPbk7z6OYMaT2EtENpzEmZw9wdc0nalcTUTVPd32ZoRRpHNaZJVBOaRjelbbW2pX67k382elJmMnExzOxhkTnMfa4q9KMipsi7b0QkkFn4x4vIPFced8+4m237t/HeBe/RoUaHkp/oj/dh6oNQuz3c8KnzV4k9qGf9nhhjeODXB3jkt0d4pesrumdPTsnLC19mdcZqAMKDw4mrGEdMRAxVy1WlSngVKperTGhQKMEmmJAg98vHQ/mHyM7P5lDeIfYd3sfu7N3sObSH3dm7OVxw+Oixq5SrQvOY5lxQ7wJaxLSgVUyrgBm1O57NaQfpN2oBuzJzePfG9lzUvIbTkcpeZAy0+Jf7DSAn033/9M5lsHO5e8BmwwwoyP3f1wSFQoVq7lG08jFQPtr9FlYegsMgONT9Z1AouPLcC8TkF77lHYLsdPe92gd3u//MPfDXTBVruS8GJgyEWm3db1ENSrxdRExEjHt1zoa9sdaSsj+FpNQkVqatZE3GGqasm0JOQQ6DWw1maNuhJTrX35200TPGBAMvWmvvL9WzeppGEsrEjgM7GDJtCNv2u3jp3JfoVb+X05FExAdYa/n77KS3l7zN4t2LeSHxhZI3eS4XTP+Pe4PaxhfDVR+5Xwj4uYviL2LngZ28sugVJq6ZyA1Nb3A6kviQV7q+wpb9W9i2fxsp+1PYtn8bGTkZ7Dy4k705e8nKzTru14UGhRIREkHlcpWpVr4aLWJaUC2iGnUr1aV+5fqcUeUMosJ9e/GN0rRk615uGZOEtZZPbu1E+3r+fQ9isYVXhvpd3G9HuFywfwdkbHSPvO3d5G7QstPdI4J7N0N2hnv07diG8FhBIRAS4V4sJiLK3SjWbAMVqkOFWKgaD9Fnuve5K1fB49+mMYY6lepQp1IdejfsDUC+K58tWVsoH1L6/0+dtNGz1hYYY84t9bOKz1uTsYY7pt1BTn5O6V19F5GA4LJ/3dFg6e6lfLzyY65qeBWXNLikZAfPPwxf3QErp0DCLXDxy6U71cfL9Wvej4WpCxmRNIJzap9DvUr1nI4kPuLIi88TcVkXBa4C8m0+Ba4CLJaIkIijo3tStF+SUxk6cTHVKoYzekAHGsR6vrHwaUFB7umaleP+2gAej7XufesKct1vQaEQEu4TC72EBIVwRhXP3FZQnLHIJcaYb4wxNxlj/nXkzSNpxCfM3T6XflP7ERwUzNheY9XkicgpcY/ouTs9l3Xx3wX/JTYilgc7PFiyAx/aB+Ovcjd5Pf4Dl7wSUE0euK8WP9X5KcKCwxixcITTccSPBJkgQoPdo3cVwipQMayimrxTMH7+Fm4bl0Tj6hX54o7OavJKmzHuqZthkRBR1T065wNNnqcVp9ELB9KB84HLCt8u9WQo8V5fr/+aO6ffSVzFOMb3Gs+ZVT2zEaSI+C/3iJ670ft+4/ckpydzb8K9lA8twbSVzBT4uCdsnQ//+gDOHe4zG6GXtpiIGG5rdRuzUmYxf+d8p+OIBDRrLS/9uIbHvlrJeY2rMXFwJ2Iq+Od+gOJ9imx1rbUDyiKIeDdrLe8vf5+3lr7FWTXP4v+6/R8VwnQ1SkROnctaDO66MmrVKBpWbcjF9S8+/QPuWgkT+rhXULtxCjToVkpJfVffpn0ZlzyOUStHlc7qpSJyynLzXfz78+V8uWQ713esyzNXNCckuGQLe4iciiL/tRljGhljphtjVhY+bmWMeczz0cRb5LvyeXr+07y19C0ubXApI7uPVJMnIiUSZGDeznn8ufdP+jXrd/orRG6c5R7Jw8CAqWryCoUFh3F9k+uZu2Muf+790+k4IgEnKyePAaMX8OWS7dx/YSOe791CTZ6UueL8i/sAeBjIA7DWLgeu82Qo8R7ZedkMmzmMKeumcGvLW3n+3OcJDQ51OpaI+DBX4T16k9ZMIiYi5vRX7F32KYzvA1XqwKBpUKNF6Qb1cVc3uprw4HA+Xfup01FEAsquzByueXcef2zMYMTVrbnr/Iba7kQcUZxGr7y1dsHfPpbviTDiXdIOpTHwp4H8tv03Hu/0OHe3u1uFSkRKzOUCl8nh9+2/0zO+J2HBYad2AGthzivw5WD3RrYDpkLl2p4J68OqhFehS1wXpm2ZRoGrwOk4IgFh7a799H7nd1L2HmLUgA70aR/ndCQJYMVp9NKMMWdQuF29MaYPsNOjqcRxmzM3c9MPN7Fh3wZeP+91rml8jdORRMRPWCzZwSvJdeXSo16PU/vignz4/l6Y/jS06AM3fg4RgbvxclEuqHcB6TnpLNuzzOkoIn5v3oZ0+rw7lwKX5dPbOpHYMNbpSBLgirPu6J3A+0ATY8x2YBNwo0dTiaOW7l7K0BlDCTJBfHzRx7SMbel0JBHxIy4L+0OWEBUeRZvYNsX/wtyDMOUWWDcVzrkHuj/p3mdJTigxLpHQoFCmbZ1Gu+rtnI4j4re+XrqdBz5bTr3o8owe2JHaVSKcjiRS9IietXajtbYHEAs0sdaea63dXJKTGmOuNsasMsa4jDEJJTmWlK7pW6cz6OdBVAqrxLhe49TkiUipc9kCDgSt4rw65xFc3H3uDuyBMZfBuh/h4hFwwVNq8oohMjSSs2udzeyU2U5HEfFL1lre+3UDwyYtpU3dKky5vbOaPPEaJxzRM8bce4KPA2CtfbUE510J/At4rwTHkFI2cc1EXljwAs2jm/NW97eICo9yOpKI+KHDpOIyh2hbrW3xviB9g3sj9P074drx0FRbuZ6KttXaMjtlNlm5WVQKq+R0HBG/UeCyPP3tKsbM28IlrWryytWtCQ8t5sUrkTJwsqmbFT11UmvtakALe3gJl3Xx+uLX+Xjlx3SL68ZLXV8iIkRXo0TEMw4FbQageXTzop+ckgSfXONegKXft1Cno2fD+aFm0c0ASE5P1p56IqUkJ6+AYZOW8NOqVG5NrM/DvZoSFKTXteJdTtjoWWufKssg4ozcglwe//1xftj0A9c2vpaHOj5ESFBxbt0UETk9OWYLQTaM+pXrn/yJa36AKQOhQjW48QuIObNsAvqZIw31qrRVavRESkHGwVwGjVnIkm37eOLSZgw8t4haJuKQIl/RG2NGUbji5rGstQOL+LppQI3jfOpRa+3XxQ1ojBkMPABUiY3V6kWlKSs3i+Ezh7Ng1wKGtRvGLS1u0SirSDGpNp2+nOAtRFDv5PfnLfwIfrgfaraGGya7mz05LZXLVaZ2hdqsSl/ldBQpI6pPnrM1PZv+oxaQsu8Q79zQjl4tazodSeSEijN0890x74cDvYEdRX1R4QIuJWatfR/3qp8kJCT8o+GU07Pr4C6GTBvC5qzNPH/u81x2xmVORxLxKapNpyfflU9u0DYq0+34T7DWvXXCb69Cw4vg6lEQFlmmGf1R8+jmavQCiOqTZyxP2cfA0QvJK7B8MugsEuK1loF4tyIbPWvt58c+NsZMBH7zWCLxuHV71zFk2hCy87IZ2WOkpvKISJnZkrUFa/KItPX++cn8XPjmLlj+KbTrB5e8CsGaSl4amkU34+ctP2tBFpHTNHPNbu6YsJioyDAmDe7ImdUqOB1JpEinszZ1Q6BEc2iMMb2NMSnA2cD3xpifSnI8Kb4/dv5Bv6n9ABjdc7SaPBEpU7uzdwMQbqL/+omcTJjQx93knf8YXPa6mrxSVDPSPb0sLTvN4SQivmfigq0MGpvEGdUi+fLOzmryxGcU5x69/bjv0TOFf+4C/l2Sk1prvwS+LMkx5NR9t/E7Hv/9ceIrxTOyx0hqRB7vFkoREc/Zm7MXgDCOGVXK2gETroY9a+DKkdDmBofS+a+q4VUByMjJoAENHE4j4hustbz2yzremLGero1iebtvOyqU0wUo8R3FmbrpsW0WpGxYa/lo5Ue8vvh1OtTowP+d93+auiMijsjIyQAg9Eijl5rsHsnLyXQvunJmdwfT+a8j+6Ie+fmLyMnlFbh4+IsVTFmUwjUJcTzXuyWhwaczEU7EOcUZ0TNAX6C+tfYZY0xdoIa1doHH00mJFbgK+O+C//Lp2k/pVb8Xz57zLGHBYU7HEpEAlZGTATaIsKBI2DQHJvWF0AgYMBVqtnI6nt860ugdGVEVkRM7cDifIeMXMefPNO7p0ZBh3RtqVXLxScUZf34HcAHnA88A+4HPgQ4ezCWl4FD+IR6c/SCzts1iQIsB3NPuHoKMrkaJiHMycjIIspGclT0Txr8MVevDjVOgSl2no/m1KuFVAI3oiRRld1YO/UctZG3qfl66qhXXdKjjdCSR01acRu8sa207Y8wSAGvtXmOMhoS8XEZOBkOnD2VF2goe7vgwNzTVPS8i4ry9OXupUuBi4K7noN45cN0EiKjqdCy/FxoUSqWwSmr0RE5i/e799Pt4IXuzc/mwXwLnNdb+neLbitPo5RljgincNN0YE4t7hE+81Lasbdw+7XZSs1N5rdtrdK+ne15EvEJ2Bvz5s9MpHJWR8gcN89NZVKEb7W/8FELDnY4UMKLCo9ToiZzAgk0ZDBqzkLCQYD4dfDYt4yo7HUmkxIrT6L2Be4XMasaY54A+wGMeTSWnbcWeFdw14y5c1sWHF35Im2ptnI4kIkfs2wJf3uZ0CkftjatFmK3L2FpP0F5NXpmKCo9i72Hdoyfyd98v38nwyUuJqxrBmAEdqRNV3ulIIqWiOKtuTjDGLAK6495i4Upr7WqPJ5NTNmvbLB749QGiI6J5t8e7xFeOdzqSiByrWjO4e4nTKRyV8WNfcjObUCdI9wuXtajwKDZlbnI6hohX+XDORp77YTXt61blg5sTqBqpu5PEfxRrMxBr7RpgjYezSAlMXjuZ5/54jqZRTXmr+1vERMQ4HUlE/i6kHEQF7h5meQV57M87QLirAkFawa7MVQ2vyuLdi52OIeIVXC7Ls9+v5uPfN9GrRQ1eu7YN4aHBTscSKVXa9dHHWWt5c8mbfLDiAxJrJzKi6wjKh2rKgYh4n6P3hxVUQH1e2YsKj2Jvzl4KXAUEB+kFrQSunLwC7p28lB9W7KJ/53gev7QZwUEqSuJ/1Oj5sLyCPJ6c+yTfbvyWqxpexWOdHiMkSH+lIuKdjtwfZlwVMOhFVVmrGl4ViyUzN/PovnoigWZfdi63jk1i4ea9PHZJU245t772yBO/pa7ARx3IPcDwWcOZv3M+d7W5i8GtBqtQiYhXyzj0vxE9XTwve9Hh0YD770GNngSibRnZ9B+1gG0Zh3jz+rZc1rqW05FEPEqNng9KPZjKHdPvYOO+jTxzzjNceeaVTkcSkWI4mHeQ5PRkp2M45uj9YQWRukfPAVXD3fsVzt85P6BX32wd25qwYC24EWhWbs9kwOiFHM4rYNwtHTmrQbTTkUQ8To2ej1m/dz1Dpg8h63AWb3d/m861OzsdSUSKaXPWZgb+NNDpGI4KCQrB5lfSPXoOqBXpHr14ceGLDidx1oyrZxBbPtbpGFKGfl23hzvGL6JK+TA+GXQWDatXdDqSSJlQo+dDFu5ayLAZwwgPCWdMrzE0iWridCQROQXxleL5+KKPnY7hqOiIaK59a6OmmjugTqU6TLlsClm5WU5HcVTlctoIO5BMTtrGw1+soFH1iowe0IHqlbR/pwQONXo+YuqmqTz626PUqViHkT1GUquC5pWL+JrI0Eg61OjgdAzHWbtB9+g5pHFUY6cjiJQJay1vTF/Pa9PWkdgwhnf6tqNieKjTsUTKlBo9L2etZWzyWEYkjaBdtXa8cf4buhopIj7NZdHUTRHxmLwCF499uZJPk7bxr3a1eeFfrQgLCXI6lkiZU6PnxQpcBbyc9DITVk/gwnoX8nzi85QLLud0LBGRErHWajEWEfGIg4fzufOTxcxau4eh55/JvRc00lRxCVhq9LxUTn4OD895mGlbp3Fzs5u5L+E+goyuRomI73NZ1OiJSKnbs/8wA0cvZNWOTJ7v3ZIbzqrrdCQRR6nR80L7cvYxdMZQlu1ZxoMdHuSmZjc5HUlEpNS4rHU6goj4mQ17DtB/1ALS9ufywc0JdG9a3elIIo5To+dlUvanMGTaEHYc2MGIriO4MP5CpyOJh+Tl5ZGSkkJOTo7TUcpEeHg4cXFxhIbqZviApxE9ESlFi7ZkcMuYJIKNYdLgTrSuU8XpSCJeQY2eF1mVvoo7pt1BviufDy78gHbV2zkdSTwoJSWFihUrEh8f7/f3D1hrSU9PJyUlhfr16zsdRxzmslarbopIqfhx5U6GTVpKrSoRjB7QgXrRkU5HEvEauunLS8xJmcOAHwcQHhzOuF7j1OQFgJycHKKjo/2+yQMwxhAdHR0wo5dyclp1U0RKw+jfNzFkwmKa1arElNvPVpMn8jca0fMCX/z5BU/Pe5pGVRvxdve3iS0f63QkKSOB0OQdEUjfq5ycRatuisjpc7ksL/y4hvdnb+SCZtV547q2RIQFOx1LxOs40ugZY14GLgNygQ3AAGvtPieyOMlayzvL3uHdZe9yTq1zeKXbK0SG6mqUiPg394ieGj0ROXWH8wu4/7PlfLtsBzd1qsd/Lm9OsOaCixyXU1M3fwFaWGtbAeuAhx3K4Zg8Vx5PzH2Cd5e9y5VnXsmb3d9UkyciAcFaq6mbInLKMg/lcfNHC/h22Q4e6tWEp69QkydyMo6M6Flrfz7m4XygjxM5nHIw7yD3zbqP33f8zpDWQxjSeoiubotIwLAWLcYiIqdk+75DDBi1gE1pB3n9ujZc0aa205FEvJ433KM3EPj0RJ80xgwGHgCqxMb6/r1re7L3cOf0O1m3dx1PdX6KfzX8l9ORxAs89e0qkndkHS7ZagAAF65JREFUleoxm9WqxJOXNT/pc5544gmioqK45557AHj00UepVq0a33zzDXv37iUvL49nn32WK664gpdffply5cpx9913M3z4cJYtW8aMGTOYMWMGH330ERMmTCjV/N7O32pTWXKvuqlOT8RT/K0+Je/IYsDoBWQfLmDMwI50PiPG6UgiPsFjUzeNMdOMMSuP83bFMc95FMgHTvgK0Vr7vrW2obU2tm7dup6KWyY27tvIjT/cyOaszbx5/ptq8sRxAwcOZOzYsQC4XC4mTZrEddddx5dffsnixYuZOXMm9913H9ZaEhMTmTNnDgBJSUkcOHCAvLw85syZQ5cuXZz8NhzhT7WprLksqM0T8Rx/qk+//ZnGNe/Nw2D4bMjZavJEToHHRvSstT1O9nljTH/gUqC7tdZ6Koe3WJy6mKEzhhIaFMqonqNoHn3ykRYJLEWNvHlKfHw80dHRLFmyhNTUVNq2bUtUVBTDhw9n9uzZBAUFsX37dlJTU2nfvj2LFi0iKyuLcuXK0a5dO5KSkpgzZw5vvPGGI/nF9xwp95quLiJF+WJxCg9OWc4ZsRUYPbADNStHOB1JxKc4tepmT+BBoKu1NtuJDGXp580/8/Cch6lVoRYje4wkrmKc05FEjho0aBCjR49m165dDBw4kAkTJrBnzx4WLVpEaGgo8fHx5OTkEBoaSv369Rk9ejSdO3emVatWzJw5k/Xr19O0aVOnvw3xEUcu62nqpoiciLWWd2Zt4OWf1nJ2g2jeu7k9lcJDnY4l4nOcWnXzLaAi8IsxZqkx5l2HcnjcuORx3P/r/TSLbsa4XuPU5InX6d27Nz/++CMLFy7koosuIjMzk2rVqhEaGsrMmTPZsmXL0ecmJiYyYsQIunTpQmJiIu+++y5t27bV6IwUm6uw09NiLCJyPPkFLh77aiUv/7SWK9vUYszAjmryRE6TU6tununEecuSy7oYkTSCccnj6FG3B/9N/C/hIeFOxxL5h7CwMM477zyqVKlCcHAwffv25bLLLqNly5YkJCTQpEmTo89NTEzkueee4+yzzyYyMpLw8HASExMdTC++xlU4oqdrAyLyd9m5+dw9cQnTVu9mSLczeODCxgTpqpDIafOGVTf9zuGCwzwy5xF+3vIzfZv25YGEBwgOCnY6lshxuVwu5s+fz2effQZATEwM8+bNO+5zu3fvTl5e3tHH69atK5OM4j8sukdPRP4p7cBhbhmTxIqUfTxzRXNuOjve6UgiPk+NXinLPJzJ3TPuZvHuxdyfcD83N7tZL2jEayUnJ3PppZfSu3dvGjZs6HQcCQC6R09E/m5z2kH6jVpAalYO797Yngub13A6kohfUKNXinYc2MGQaUPYtn8bL3V5iV71ezkdSeSkmjVrxsaNG52OIQHEdXTVTYeDiIhXWLJ1L7eMSQLgk1s70a5uVYcTifgPNXqlZHX6au6YfgeHCw7z3gXv0aFGB6cjiYh4nf+N6DmbQ0Sc90tyKkMnLqZ6pXBGD+hI/ZhIpyOJ+BWnVt30K3O3z6X/j/0JCQphbM+xavJERE7gf6tuqtMTCWTj5m/htnFJNK5ekc+HdFaTJ+IBGtEroa/Wf8VTc5/ijCpn8E6Pd6hWvprTkUREvNaRVTdFJDC5XJaXf17LyFkb6N6kGm/e0JbyYXo5KuIJ+s06TdZa3lv+Hm8vfZtONTvxWrfXqBBWwelYIiLeTYuxiASs3HwXD05ZxldLd3DDWXV5+vLmhARrcpmIp+i36zTku/J5at5TvL30bS5rcBnvdH9HTZ74lUGDBpGcnAzA888/X+Tz+/fvz5QpUzwdS/yANkwXCUxZOXn0H7WAr5bu4IGLGvPclS3U5Il4mEb0TlF2Xjb3/3o/c7bP4daWtzK07VBtnyB+58MPPzz6/vPPP88jjzziYBr/sS87l1/X7XE6hqNCC1/YqW6KBI6dmYcYMGoh63cf4JWrW3NV+zinI4kEBDV6pyDtUBp3Tb+L1RmrebzT41zT+BqnI4m/mPoQ7FpRuses0RJ6vXDSp2zevJmePXvSvn17Fi9eTPPmzRk7diwXX3wxI0aMYMqUKRw6dIg2bdrQvHlzJkyYwNixYxkxYgTGGFq1asW4ceMAmD17Nq+++iq7du3ipZdeok+fPqX7/fiBbRmHGDZpqdMxvIJG9EQCw9pd++k/agH7c/IZNaADiQ1jnY4kEjDU6BXT5szN3D7tdjJyMnjjvDfoWqer05FESsXatWv56KOPOOeccxg4cCDvvPPO0c+98MILvPXWWyxd6m5OVq1axbPPPsvcuXOJiYkhIyPj6HN37tzJb7/9xpo1a7j88svV6B1Hw+oVmHFf4NaOGWt28+z3qwGN6IkEgrkb0rht3CLKhwUz+bazaVarktORRAKKGr1iWLp7KUNnDCXIBPHRhR/RMral05HE3xQx8uZJderU4ZxzzgHgxhtv5I033jjhc2fMmMHVV19NTEwMAFFRUUc/d+WVVxIUFESzZs1ITU31bGgfFR4aTIPYwL2fd/u+Q0ffV58n4t++Xrqd+z9bRnx0JKMHdqR2lQinI4kEHN0FW4TpW6Yz6OdBVAqrxPhe49Xkid/5+8jK6Y60lCtX7uj71moNffmnqMiwo+9r1U0R/2St5d1fNzBs0lLa1a3KlNs7q8kTcYgavZOYuGYiw2cNp3HVxoy7eBx1KtVxOpJIqdu6dSvz5s0D4JNPPuHcc8/9y+dDQ0PJy8sD4Pzzz+ezzz4jPT0d4C9TN0WKEh35v4sBukdPxP8UuCz/+WYVL0xdw6WtajL2lo5ULh/qdCyRgKVG7zhc1sWri17l+T+ep2udrnx40YdEhUcV/YUiPqhx48a8/fbbNG3alL179zJkyJC/fH7w4MG0atWKvn370rx5cx599FG6du1K69atuffeex1KLb6oauT/XvAZ1OmJ+JOcvAKGjF/EmHlbGNylAW9c15ZyIcFOxxIJaLpH729yC3J57PfHmLppKtc2vpaHOz5McJAKlfivkJAQxo8f/5ePzZo16+j7L774Ii+++OLRx/369aNfv35/ef7o0aP/8vjAgQOlnlN837Ev+jRzU8R/ZBzMZdCYhSzZto8nL2vGgHPqOx1JRFCj9xdZuVncM/MeFu5ayD3t7mFgi4FaGU5EpBQZA9bqHj0Rf7E1PZt+oxawY98hRvZtR88WNZ2OJCKF1OgV2nVwF0OmDWFz1mb+m/hfLm1wqdORRDwuPj6elStXOh1DAkhU+TDSD+ZqRE/EDyzbto9bxiwk32WZMOgsEuJ1m4uIN1GjB6zNWMsd0+4gOz+bkT1G0qlmJ6cjiYj4pSrlQ0k/mKsRPREfN2NNKndOWEJ0hTBGD+jImdUCd+sYEW8V8IuxzN85n/4/9gcDo3uOVpMnIuJBVcq7t1hQnyfiuyYu2MqtYxdxRrVIvrijs5o8ES8V0CN63274lifmPkF8pXhG9hhJjcgaTkcSEfFrVY82eur0RHyNtZbXflnHGzPW07VRLO/0bUdkuYB+KSni1QLyt9Nay0crP+L1xa/TsUZHXjvvNSqFVXI6loiI36tauKdW9uF8h5OIyKnIK3Dx0Ocr+HxxCtcm1OHZ3i0IDQ74iWEiXs2R31BjzDPGmOXGmKXGmJ+NMbXK6tz5rnyenf8sry9+nYvrX8zIHiPV5IkUIT4+nrS0NAAqVNAUHTl9VSPdI3p7s/McTiIixbU/J4+Boxfy+eIUhvdoxAtXtVSTJ+IDnBrRe9la+ziAMeZu4Angdk+fNDsvm3/P/jezUmYxsMVAhrUbRpBRoRIB90i3tZagIP1OiOccmbq5LzvX4SQiUhypWTkMGLWQtan7ealPK65JqON0JBEpJkcaPWtt1jEPIwHr6XNm5GRw1/S7WJm2kkfOeoTrm1zv6VOKFNuLC15kTcaaUj1mk6gm/Lvjv0/6nM2bN3PRRRdx1llnsWjRIh588EFGjBiBtZZLLrnkLxuli5SGBrGRAFSKCHU4iYgU5c/U/fQftZC92bl81C+Bbo2rOR1JRE6BY/foGWOeA24GMoHzTvK8wcADQJXY2NjTOtfWrK0MmTaE1OxUXjvvNbrX7X5axxHxR3/++Sdjxoyhbt26dOrUiUWLFlG1alUuvPBCvvrqK6688kqnI3ql0qhNgejCZtV576b2nN9ELxhFPKU06tOCTRkMGrOQsJBgJt92Ni1qVy7VjCLieR5r9Iwx04DjLWP5qLX2a2vto8CjxpiHgbuAJ493HGvt+8D7AAkJCac88rd8z3Lumn4XFsuHF35Im2ptTvUQIh5X1MibJ9WrV49OnTrx9ddf061bN468KOjbty+zZ89Wo3cCJa1NgcoYw0XNtcKxiCeVtD59v3wnwz9dSlxUBGMGdKROVPlSzyginuexRs9a26OYT50A/MAJGr2SmLl1Jg/OfpCYiBhG9hhJfOX40j6FiM+LjIx0OoKIiHiJD+ds5NnvV5NQryof9ks4uveliPgep1bdbHjMwyuA0r05CZi8djL3zLqHM6ucyfiLx6vJEylCx44d+fXXX0lLS6OgoICJEyfStWtXp2OJiEgZKHBZnvp2Fc9+v5peLWowftBZavJEfJxT9+i9YIxpDLiALZTyiptvL32bd5e9S5e4Lrzc5WXKh2rKgUhRatasyQsvvMB55513dDGWK664wulYIiLiYQUuy9CJi/lhxS4GnBPP45c0IyjIOB1LRErIqVU3r/Lk8eMrxXN1o6t55KxHCAkKyD3hRYolPj6elStXHn18/fXXc/31/1yRdvPmzUffP3DgQFlEExGRMhIcZKgfE8ljlzRlUGIDp+OISCnxyy7okgaXcEmDS5yOISIiIuITHrioidMRRKSUaWdkERERERERP6NGT8RB1gbOqvyB9L2KiIiIOE2NnohDwsPDSU9PD4gGyFpLeno64eHhTkcRERERCQh+eY+eiC+Ii4sjJSWFPXv2OB2lTISHhxMXF+d0DBEREZGAoEZPxCGhoaHUr1/f6RgiIiIi4oc0dVNERERERMTPqNETERERERHxM2r0RERERERE/IzxpRX/jDF7gC0lOEQMkFZKcUqDN+XxpiygPCfjTVmg5HnqWWtjSyuME0qhNoF3/b16UxbwrjzelAWU52RKI4vqk3f9nYJ35fGmLOBdebwpC/hfnmLVJp9q9ErKGJNkrU1wOscR3pTHm7KA8pyMN2UB78vjq7zp5+hNWcC78nhTFlCek/GmLL7M236O3pTHm7KAd+XxpiwQuHk0dVNERERERMTPqNETERERERHxM4HW6L3vdIC/8aY83pQFlOdkvCkLeF8eX+VNP0dvygLelcebsoDynIw3ZfFl3vZz9KY83pQFvCuPN2WBAM0TUPfoiYiIiIiIBIJAG9ETERERERHxe2r0RERERERE/EzANXrGmGeMMcuNMUuNMT8bY2o5nOdlY8yawkxfGmOqOJjlamPMKmOMyxjj2BK0xpiexpi1xpj1xpiHnMpRmOVjY8xuY8xKJ3MUZqljjJlpjEku/Hsa5nCecGPMAmPMssI8TzmZx9epNhWZx/H6pNp0wiyqTX7Om+qTatNxM6g2nYA31ScnalPA3aNnjKlkrc0qfP9uoJm19nYH81wIzLDW5htjXgSw1v7boSxNARfwHnC/tTbJgQzBwDrgAiAFWAhcb61NLusshXm6AAeAsdbaFk5kOCZLTaCmtXaxMaYisAi40sGfjQEirbUHjDGhwG/AMGvtfCfy+DrVpiLzOFqfVJtOmkW1yc95U31SbfrH+VWbTp7Ha+qTE7Up4Eb0jhSqQpGAo52utfZna21+4cP5QJyDWVZba9c6df5CHYH11tqN1tpcYBJwhVNhrLWzgQynzn8sa+1Oa+3iwvf3A6uB2g7msdbaA4UPQwvfAuvKUSlSbSoyj9P1SbXpBFSb/J831SfVpn9QbToJb6pPTtSmgGv0AIwxzxljtgF9gSecznOMgcBUp0M4rDaw7ZjHKTj4gsFbGWPigbbAHw7nCDbGLAV2A79Yax3N4+tUm7yaalMxqDb5Ly+tT6pNqk3F5g31qaxrk182esaYacaYlcd5uwLAWvuotbYOMAG4y+k8hc95FMgvzORoFvFuxpgKwOfAPX+7ylrmrLUF1to2uK+odjTGOD5Nw5upNpU8j3gv1Sbf5k31SbVJSpu31Keyrk0hnjy4U6y1PYr51AnAD8CTHoxTZB5jTH/gUqC79fBNk6fws3HKdqDOMY/jCj8mQOGc7s+BCdbaL5zOc4S1dp8xZibQE/CKG7C9kWpTyfI4TLXpJFSbfJ831SfVplOi2lQEb6xPZVWb/HJE72SMMQ2PeXgFsMapLOBeKQl4ELjcWpvtZBYvsRBoaIypb4wJA64DvnE4k1covIn3I2C1tfZVL8gTawpXOzPGROC+EdzR3ydfptrk9VSbTkC1yf95U31SbfoH1aaT8Kb65ERtCsRVNz8HGuNeIWkLcLu11rErH8aY9UA5IL3wQ/MdXMmqN/AmEAvsA5Zaay9yIMfFwP8BwcDH1trnyjrDMVkmAt2AGCAVeNJa+5FDWc4F5gArcP/7BXjEWvuDQ3laAWNw/z0FAZOttU87kcUfqDYVmcfx+qTadMIsqk1+zpvqk2rTcTOoNp04j9fUJydqU8A1eiIiIiIiIv4u4KZuioiIiIiI+Ds1eiIiIiIiIn5GjZ6IiIiIiIifUaMnIiIiIiLiZ9ToiYiIiIiI+Bk1egHIGDPXA8eMN8bcUNrHPc55uhljvjvF52caY0q0jK4xpr8x5q3C94cbY7YeeSwipUO16bTOq9okUgZUn07rvKpPDlOjF4CstZ09cNh4wOPF6jTNsdZe/PcPGmNCTudg1trXgCdKnEpE/kK1yU21ScT7qD65qT75FjV6AcgYc6Dwz27GmFnGmCnGmDXGmAnGGFP4uc3GmJeMMSuMMQuMMWcWfny0MabP348FvAAkGmOWGmOG/+18FYwx040xiwuPd0Xhx+ONMauNMR8YY1YZY342xkQUfq6DMWZ54fFeNsasPM73EWmM+bgw35Ijxy3ie+9mjJljjPkGSC782FfGmEWFGQYf89wBxph1xpgFwDmn8jMWkVOn2qTaJOKtVJ9Un3yRGj1pC9wDNAMa8NdfykxrbUvgLeD/ijjOQ7iv/rQpvGpzrBygt7W2HXAe8MqRogg0BN621jYH9gFXFX58FHCbtbYNUHCCcz4KzLDWdiw87svGmMgicgK0A4ZZaxsVPh5orW0PJAB3G2OijTE1gadw/zzOxf3zEZGyo9qk2iTirVSfVJ98gho9WWCtTbHWuoCluKcRHDHxmD/PLsE5DPC8MWY5MA2oDVQv/Nwma+3SwvcXAfHGmCpARWvtvMKPf3KC414IPGSMWQrMAsKBusXIs8Bau+mYx3cbY5YB84E6uAvoWcAsa+0ea20u8GkxjisipUe1SbVJxFupPqk++YTTmmcrfuXwMe8X8Nd/E/Y47+dTeIHAGBMEhBXjHH2BWKC9tTbPGLMZd2E53vkjip3cXQSvstauPYWvATh49ADGdAN6AGdba7ONMbOOySYizlFtUm0S8VaqT6pPPkEjenIy1x7z55ErRJuB9oXvXw6EFr6/H6h4guNUBnYXFqrzgHonO6m1dh+w3xhzVuGHrjvBU38Chh4zN77tyY57kmx7CwtVE6BT4cf/ALoWTkUIBa4+jWOLiGeoNqk2iXgr1SfVJ6+hRk9OpmrhlIFhwJGbhD/A/Uu8DPeUhCNXeJYDBcaYZX+/oRiYACQYY1YANwNrinHuW4APCqcWRAKZx3nOM7iL5XJjzKrCx6fqRyDEGLMa903R8wGstTuB/+Au0r8Dq0/j2CLiGapNqk0i3kr1SfXJaxhrbdHPkoBTOEUgwVqb5tD5K1hrj6xw9RBQ01o77DSO0w2431p7aSnn64/753NXaR5XRE5OtanI4/ZHtUnEEapPRR63P6pPZUojeuKtLilcHnglkAg8e5rHyQVamBJu+nmswqtuDwNZpXVMEfEZqk0i4q1Un+QvNKInIiIiIiLiZzSiJyIiIiIi4mfU6ImIiIiIiPgZNXoiIiIiIiJ+Ro2eiIiIiIiIn1GjJyIiIiIi4mf+H1q817FJG35VAAAAAElFTkSuQmCC\n", - "text/plain": [ - "<Figure size 1080x288 with 3 Axes>" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, axarr = plt.subplots(1, 3, figsize=(15, 4),\n", - " sharey=True)\n", - "ax = axarr[0]\n", - "solution_x_axis.plot(ax=ax)\n", - "ax.set_title('x-aligned')\n", - "ax = axarr[1]\n", - "solution_y_axis.plot(ax=ax)\n", - "ax.set_title('y-aligned')\n", - "ax = axarr[2]\n", - "solution_z_axis.plot(ax=ax)\n", - "ax.set_title('z-aligned')\n", - "\n", - "for ax in axarr:\n", - " ax.set_xlabel('input angle [rad]')\n", - " ax.set_ylabel('euler angle [rad]')\n" + "euler_axes = 'yxz'\n", + "alpha, beta, gamma = twomarkers2euler(mark0, mark1, axis_alignement,\n", + " known_angle, euler_axes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We observe that when the markers are aligned with the x-axis, the yaw and pitch can be determined (without having to guess the roll), because yaw and pitch are constant. However we can not obtain the roll angle. \n", + "#### Advance cases\n", + "\n", + "The few cases above may be a bit limiting. We will illustrate, how the solution of the system can be done for other axis. Note that, although the method will not expose a general solution, it will hopefully serve as basis for deriving euler angles in custom cases. \n", + "\n", + "We focus on the following euler angle sequence: $R=R_zR_yR_x$.\n", + "\n", + "We start with the following equation:\n", + "$v^{bee}=R.v^{ref}$\n", + "\n", + "here:\n", + "* $v^{bee}$ is a vector formed by our two markers\n", + "* $v^{ref}$ is the vector formed by our two markers when the bee will have a null orientation (yaw=pitch=roll=0)\n", + "* $R$ the rotation matrix\n", + "\n", + "We write the transformation with a matrix of cosine and sine of euler angles\n", + "\n", + "$$\\begin{align}\n", + "v^{bee}&=Rv^{ref}\\\\\n", + " &=R_zR_yR_xv^{ref}\\\\\n", + " &=\\begin{pmatrix}\\cos\\gamma & \\sin\\gamma & 0 \\\\\n", + " -\\sin\\gamma & \\cos\\gamma & 0 \\\\\n", + " 0 & 0 & 1 \\end{pmatrix}\n", + " \\begin{pmatrix}\\cos\\beta & 0 & -\\sin\\beta \\\\\n", + " 0 & 1 & 0 \\\\\n", + " \\sin\\beta & 0 & \\cos\\beta \\end{pmatrix}\n", + " \\begin{pmatrix}1 & 0 & 0 \\\\\n", + " 0 & \\cos\\alpha & \\sin\\alpha \\\\\n", + " 0 & -\\sin\\alpha & \\cos\\alpha \\end{pmatrix}v^{ref}\\\\\n", + " &=\\begin{pmatrix}\n", + "\\cos\\gamma \\cos\\beta & \\cos\\gamma \\sin\\beta \\sin\\alpha + \\sin\\gamma \\cos\\alpha & -\\cos\\gamma \\sin\\beta\\cos\\alpha + \\sin\\gamma \\sin\\alpha \\\\\n", + "-\\sin\\gamma \\cos\\beta & -\\sin\\gamma \\sin\\beta \\sin\\alpha + \\cos\\gamma \\cos\\alpha & \\sin\\gamma \\sin\\beta \\cos\\alpha + \\cos\\gamma \\sin\\alpha \\\\\n", + "\\sin\\beta & -\\cos\\beta \\sin\\alpha & \\cos\\beta \\cos\\alpha\\end{pmatrix}v^{ref}\\\\\n", + "\\end{align}$$\n", "\n", - "When the two markers are aligned with the y-axis or z-axis, the pitch or the yaw needs to be apriori known to get the two other angles, repectively. " + "To simplify the problem, we need to remove terms in the system of equations. Removing terms is easily done by letting certain variables to be zero. We want to determine $\\alpha$, $\\beta$, and $\\gamma$. Thus we can only set to zeros $v_x^{ref}$, $v_y^{ref}$, or $v_z^{ref}$.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Solving pitch aligned markers with yaw, pitch, roll convention\n", - "\n", - "$v^{ref}=(0,-1,0)^T$\n", + "##### Case 1: $v^{ref}$ is y-aligned\n", "\n", - "$$\\begin{align}\n", - " v_x^{bee} & = -\\cos\\alpha \\sin\\beta \\sin\\gamma + \\sin\\alpha \\cos\\gamma &\\quad \\text{from L1}\\\\\n", - " v_y^{bee} & = -\\sin\\alpha \\sin\\beta \\sin\\gamma - \\cos\\alpha \\cos\\gamma &\\quad \\text{from L2}\\\\\n", - " v_z^{bee} & = -\\cos\\beta \\sin\\gamma &\\quad \\text{from L3}\n", - " \\end{align}$$\n", + "We know that the two markers are aligned with the y-axis and thus: $v^{ref}=[0, 1, 0]^T$. The system of equation is then simplified as follow:\n", "\n", - "#### for $v_z^{bee}\\neq0 \\Rightarrow \\sin\\gamma\\neq0$\n", + "$$\n", + "v^{bee} = \\begin{pmatrix} x \\\\ y \\\\ z \\end{pmatrix}^{bee}= \\begin{pmatrix} \\cos\\gamma\\sin\\beta\\sin\\alpha + \\sin\\gamma\\cos\\alpha \\\\ \n", + "-\\sin\\gamma\\sin\\beta\\sin\\alpha + \\cos\\gamma\\cos\\alpha \\\\\n", + "-\\cos\\beta\\sin\\alpha \\end{pmatrix}\n", + "$$\n", "\n", - "$$\\begin{align}\n", - " \\cos\\gamma & = v_x^{bee}\\sin\\alpha -v_y^{bee}\\cos\\alpha &\\quad \\text{from L1 and L2} \\\\\n", - " \\cos\\beta & = -\\frac{v_z^{bee}}{\\sin\\gamma } &\\quad\\text{from L3}\n", - " \\end{align}$$\n", + "The simplest equation is $z=-\\cos\\beta\\sin\\alpha$. If we know $\\beta$ and that $\\beta$ is different of $\\pm\\pi/2$, we have the following relation:\n", "\n", - "From the two last equation $\\gamma$ and $\\beta$ can be found as a function of $\\alpha$ and $v^{bee}$\n", + "$$ \\alpha = \\arcsin\\frac{z}{-\\cos\\beta} + k\\pi ,\\quad k\\in\\mathbf{Z}$$ \n", "\n", - "#### for $v_z^{bee}=0$\n", - "$$\\begin{align}\n", - " \\tan\\alpha & = -\\frac{v_x^{bee}}{v_y^{bee}} &\\quad \\text{from L1 and L2}\\\\\n", - " \\cos\\gamma & =\\pm\\sqrt{ \\left(v_x^{bee}\\right)^2 + \\left(v_y^{bee}\\right)^2 } &\\quad \\text{from L1 and L2}\\\\\n", - " \\end{align}$$\n", + "We found $\\alpha$, know we can look for $\\gamma$ by using the two other equations. We recognise that the two equations share many term and that we can probably extract $\\sin\\gamma$ and $\\cos\\gamma$ out of the two equations. \n", "\n", - "for $\\beta$ known, and $\\beta\\neq\\pm\\pi/2$:\n", + "$$\n", + "\\begin{align}\n", + "x\\sin\\beta\\sin\\alpha + y\\cos\\alpha &= \\cos\\gamma\\sin^2\\beta\\sin^2\\alpha + \\sin\\gamma\\sin\\alpha\\sin\\beta\\sin\\alpha - \\sin\\gamma\\sin\\alpha\\sin\\beta\\cos\\alpha + \\cos\\gamma\\cos^2\\alpha \\\\\n", + " &= \\cos\\gamma(\\sin^2\\beta\\sin^2\\alpha + \\cos^2\\alpha) \\\\\n", + "x\\cos\\alpha - y\\sin\\beta\\sin\\alpha &= \\cos\\alpha\\cos\\gamma\\sin\\beta\\sin\\alpha + \\sin\\gamma\\cos^2\\alpha + \\sin\\gamma\\sin^2\\beta\\sin^2\\alpha - \\cos\\gamma\\cos\\alpha\\beta\\sin\\alpha \\\\\n", + " &= \\sin\\gamma(\\cos^2\\alpha + \\sin^2\\alpha\\sin^2\\beta)\n", + "\\end{align}$$\n", "\n", - "$$\\begin{align}\n", - " \\sin\\gamma & = \\frac{v_z^{bee}}{-\\cos\\beta} \\\\\n", - " \\tan\\left(\\alpha+\\theta\\right) & = \\frac{v_x^{bee}}{-v_y^{bee}} \\\\\n", - " \\tan\\theta&=\\frac{v_z^{bee}\\tan\\beta}{\\pm\\sqrt{1-\\sin^2\\gamma}}\n", - " \\end{align}$$\n", + "The two equations above yield to:\n", "\n", - "for $\\gamma$ known, and $\\gamma\\neq 0 + k2pi$:\n", + "$$\\tan\\gamma = \\frac{\\sin\\gamma}{\\cos\\gamma}$$\n", "\n", - "$$\\begin{align}\n", - " \\sin\\left(\\alpha+\\theta\\right) & = \\frac{\\cos\\gamma}{\\sqrt{ \\left(v_x^{bee}\\right)^2+\\left(v_y^{bee}\\right)^2}} \\\\\n", - " \\cos\\beta & = -\\frac{v_z^{bee}}{\\sin\\gamma } \\\\\n", - " \\tan\\theta&=\\frac{v_y^{bee}}{v_x^{bee}}\n", - " \\end{align}$$" + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-0.06706145865876341 -0.06706145865876341\n", + "0.3759553148789634 0.3759553148789634\n", + "-0.5011653731009601 -0.5011653731009601\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from navipy.trajectories.transformations import twomarkers2euler\n", + "from navipy.maths.euler import matrix as euler_rot\n", + "\n", + "def twomarker_yaligned_zyx(vbee, beta_th):\n", + " # Get alpha knowing beta\n", + " beta = beta_th\n", + " alpha = np.arcsin(vbee.z/(-np.cos(beta)))\n", + " # Get gamma knowing the two others\n", + " nominator = vbee.x*np.cos(alpha) - vbee.y*np.sin(beta)*np.sin(alpha)\n", + " nominator /= np.cos(alpha)**2 + (np.sin(alpha)**2) * (np.sin(beta)**2)\n", + " denominator = vbee.x*np.sin(beta)*np.sin(alpha)+vbee.y*np.cos(alpha)\n", + " denominator /= np.cos(alpha)**2+(np.sin(alpha)**2)*(np.sin(beta)**2)\n", + " gamma = np.arctan2(nominator, denominator)\n", + " return alpha, beta, gamma\n", + "\n", + "# Get the position of two markers\n", + "# knowing the euler angles\n", + "# in order to test our function above\n", + "euler_axes = 'zyx'\n", + "alpha_th = np.pi*(np.random.rand()-0.5)\n", + "beta_th = np.pi*(np.random.rand()-0.5)\n", + "gamma_th = np.pi*(np.random.rand()-0.5) #2*np.pi*np.random.rand()\n", + "rotmat = euler_rot(gamma_th, beta_th, alpha_th, axes=euler_axes)[:3, :3]\n", + "axis_alignment = np.array([0, 1, 0]).transpose()\n", + "\n", + "mark0 = pd.Series(index=['x','y','z'], data=0)\n", + "mark1 = pd.Series(index=['x','y','z'], \n", + " data=rotmat.dot(axis_alignment))\n", + "# Call the function\n", + "vbee = mark1-mark0\n", + "alpha, beta, gamma = twomarker_yaligned_zyx(vbee, beta_th)\n", + "\n", + "# Check the results\n", + "print(alpha_th, alpha)\n", + "print(beta_th, beta)\n", + "print(gamma_th, gamma)" ] } ],