{ "cells": [ { "cell_type": "markdown", "id": "87f56cc0", "metadata": {}, "source": [ "# Getting Started with `pyhelios`\n", "***" ] }, { "cell_type": "markdown", "id": "24c3ac0f", "metadata": {}, "source": [ "\n", "\n", "This page will give an introduction on using HELIOS++ python bindings with `pyhelios`. \n", "\n", "`pyhelios` allows you to:\n", "\n", "- Access and modify simulation configurations\n", "- Launch one or multiple simulations from your python script\n", "- Read point measurements and process them further in combination with other python modules" ] }, { "cell_type": "markdown", "id": "520a9126", "metadata": {}, "source": [ "## Importing `pyhelios`\n", "The package `pyhelios` is contained in the distribution root folder. It consists of different python scripts and the python-helios bindings. These bindings are actually present in the `run`-folder as `_pyhelios.pyd/[.so]`, but are imported when you import `pyhelios`. The python scripts contain functions to create and work with simulations (e.g., `SimulationBuilder`) and a `util` subpackage, where tools for scene generation and flight planning are found.\n", "\n", "Before importing, make sure that the HELIOS++ root directory is either the current working folder or added to the PATH environment variable.\n", "As this notebook is not located in the HELIOS++ root directory, we add the path to the HELIOS++ root directory to the PATH environment variable with `sys.path.append`." ] }, { "cell_type": "code", "execution_count": 1, "id": "190276b5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.1.1\n" ] } ], "source": [ "import sys\n", "import os\n", "from pathlib import Path\n", "\n", "current_folder = globals()[\"_dh\"][0]\n", "helios_path = str(Path(current_folder).parent)\n", "sys.path.append(helios_path) # add helios-plusplus directory to PATH\n", "import pyhelios\n", "\n", "os.chdir(helios_path)\n", "\n", "print(pyhelios.getVersion())" ] }, { "cell_type": "markdown", "id": "9e3bfd6d", "metadata": {}, "source": [ "## Logging Level and Random Seed" ] }, { "cell_type": "code", "execution_count": 2, "id": "5411a736", "metadata": {}, "outputs": [], "source": [ "# pyhelios.loggingQuiet()\n", "# pyhelios.loggingSilent()\n", "pyhelios.loggingDefault()\n", "# pyhelios.loggingVerbose()\n", "# pyhelios.loggingVerbose2()\n", "\n", "# Set seed for default random number generator.\n", "pyhelios.setDefaultRandomnessGeneratorSeed(\"123\")" ] }, { "cell_type": "markdown", "id": "3e626d46", "metadata": {}, "source": [ "## Building a Simulation" ] }, { "cell_type": "code", "execution_count": 3, "id": "5e5fd46a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SimulationBuilder is building simulation ...\n", "SimulationBuilder built simulation in 0.3059422999999999 seconds\n" ] } ], "source": [ "simBuilder = pyhelios.SimulationBuilder(\n", " \"data/surveys/toyblocks/als_toyblocks.xml\", \"assets/\", \"output/\"\n", ")\n", "# simBuilder.setNumThreads(1) # use only one thread (to ensure reproducibility)\n", "simBuilder.setLasOutput(True)\n", "simBuilder.setZipOutput(True)\n", "simBuilder.setCallbackFrequency(10) # Run with callback\n", "simBuilder.setFinalOutput(True) # Return output at join\n", "# simBuilder.setExportToFile(False) # Disable export point cloud to file\n", "simBuilder.setRebuildScene(True)\n", "\n", "sim = simBuilder.build()" ] }, { "cell_type": "markdown", "id": "536c6232", "metadata": {}, "source": [ "## Starting, Pausing and Getting the Simulation Status" ] }, { "cell_type": "markdown", "id": "27469b06", "metadata": {}, "source": [ "Simulations can also be paused, resumed and stopped:\n", "```python\n", "sim.start()\n", "sim.pause()\n", "sim.resume()\n", "sim.stop()\n", "```\n", "\n", "With various functions, we can find out the simulation status.\n", "```python\n", "sim.isStarted()\n", "sim.isRunning()\n", "sim.isPaused()\n", "sim.isStopped()\n", "sim.isFinished()\n", "```" ] }, { "cell_type": "code", "execution_count": 4, "id": "b744c735", "metadata": { "pycharm": { "is_executing": true } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Simulation is started!\n", "Simulation is paused!\n", "Simulation is not running.\n", "Simulation is resumed!\n", "Simulation is running since 0 min and 18 sec. Please wait.\n", "Simulation has finished.\n" ] } ], "source": [ "import time\n", "\n", "sim.start()\n", "\n", "if sim.isStarted():\n", " print(\"Simulation is started!\")\n", "\n", "time.sleep(1.0)\n", "sim.pause()\n", "\n", "if sim.isPaused():\n", " print(\"Simulation is paused!\")\n", "\n", "if not sim.isRunning():\n", " print(\"Simulation is not running.\")\n", "\n", "time.sleep(5)\n", "start_time = time.time()\n", "sim.resume()\n", "\n", "if sim.isRunning():\n", " print(\"Simulation is resumed!\")\n", "\n", "while sim.isRunning():\n", " duration = time.time() - start_time\n", " mins = duration // 60\n", " secs = duration % 60\n", " print(\n", " \"\\r\"\n", " + \"Simulation is running since {} min and {} sec. Please wait.\".format(\n", " int(mins), int(secs)\n", " ),\n", " end=\"\",\n", " )\n", " time.sleep(1)\n", "\n", "if sim.isFinished():\n", " print(\"\\nSimulation has finished.\")" ] }, { "cell_type": "markdown", "id": "4c37e3c1", "metadata": {}, "source": [ "## Output Handling\n", "\n", "If final output was enabled (`simBuilder.setFinalOutput(True)`)., the simulation output, i.e. measurement and trajectory points, can be accessed using `sim.join()`." ] }, { "cell_type": "code", "execution_count": 5, "id": "26589610", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Trajectory starting point : (-30.0, -50.0, 100.0)\n", "Trajectory end point : (69.9, 50.0, 100.0)\n" ] } ], "source": [ "# Create instance of PyHeliosOutputWrapper class using sim.join().\n", "# Contains attributes 'measurements' and 'trajectories' which are Python wrappers\n", "# of classes that contain the output vectors.\n", "output = sim.join()\n", "\n", "# Create instances of vector classes by accessing 'measurements' and 'trajectories' attributes of output wrapper.\n", "measurements = output.measurements\n", "trajectories = output.trajectories\n", "\n", "# Each element of vectors contains a measurement point or point in trajectory respectively.\n", "# Access through getPosition().\n", "starting_point = trajectories[0].getPosition()\n", "end_point = trajectories[len(trajectories) - 1].getPosition()\n", "\n", "# Access individual x, y and z vals.\n", "print(\n", " f\"Trajectory starting point : ({starting_point.x}, {starting_point.y}, {starting_point.z})\"\n", ")\n", "print(\n", " f\"Trajectory end point : ({end_point.x:.1f}, {end_point.y:.1f}, {end_point.z:.1f})\"\n", ")" ] }, { "cell_type": "markdown", "id": "c725a98f", "metadata": {}, "source": [ "`pyhelios` contains additional tools for output handling (pyhelios/output_handling.py). These allow to convert the trajectory and point outputs to lists or numpy arrays." ] }, { "cell_type": "code", "execution_count": 6, "id": "cf678697", "metadata": {}, "outputs": [], "source": [ "meas_array, traj_array = pyhelios.outputToNumpy(output)" ] }, { "cell_type": "code", "execution_count": 7, "id": "41887ac9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "First three rows of measurement array:\n", "\n", "[[-29.846 -13.246 0.012 20.000 20.085 100.994 0.001 0.342 -0.940\n", " 62543.211 0.000 1.000 1.000 1.000 0.000 0.000 -2147483648.000]\n", " [-24.944 -13.595 0.012 20.003 20.085 100.994 0.047 0.339 -0.940\n", " 68765.772 0.000 1.000 1.000 33.000 0.000 0.000 -2147483648.000]\n", " [-29.693 -13.259 0.046 20.000 20.085 100.994 0.003 0.342 -0.940\n", " 74992.121 0.000 1.000 1.000 2.000 0.000 0.000 -2147483648.000]]\n", "\n", "First three rows of trajectory array:\n", "\n", "[[-30.000 -50.000 100.000 -2147483648.000 0.000 0.000 4.712]\n", " [-29.700 -50.000 100.000 -2147483648.000 0.000 0.000 4.712]\n", " [-29.400 -50.000 100.000 -2147483648.000 0.000 0.000 4.712]]\n", "\n" ] } ], "source": [ "import numpy as np\n", "\n", "np.set_printoptions(formatter={\"float\": \"{0:0.3f}\".format})\n", "print(\n", " f\"\"\"\n", "First three rows of measurement array:\n", "\n", "{meas_array[:3, :]}\n", "\n", "First three rows of trajectory array:\n", "\n", "{traj_array[:3, :]}\n", "\"\"\"\n", ")" ] }, { "cell_type": "markdown", "id": "d5a9217a", "metadata": {}, "source": [ "Columns of the measurements array:\n", "\n", "| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |\n", "|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|\n", "| pos.x | pos.y | pos.z | ori.x | ori.y | ori.z | dir.x | dir.y | dir.z | intensity | echoWidth | NumberOfReturns | ReturnNumber | FullwaveIndex | classification | gpsTime |\n", "\n", "\n", "Columns of the trajectories array:\n", "\n", "\n", "| 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n", "|:------:|:------:|:------:|:------:|:------:|:------:|:------:|\n", "| pos.x | pos.y | pos.z | gpsTime | roll | pitch | yaw |" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.15" } }, "nbformat": 4, "nbformat_minor": 5 }