Skip to content

pyhelios ๐Ÿ The util subpackage

han16nah edited this page Dec 23, 2021 · 1 revision

The util subpackage of pyhelios contains a number of utility scripts.

a) Command line tools

The XML checker

The xmlchecker is a tool to validate XML files against XML style definitions (XSDs) before executing a survey. It is only a Python wrapper around the standard command line call and does not use the Python bindings.

If no errors are found in the XML configurations, the specified survey is executed as usual. Other wise, the XML errors are reported to the user and HELIOS++ is not run.

The script takes the same arguments as the HELIOS++ command line call (Optional arguments).

The example below shows how to execute the same survey with the standard command line call, and with the python script and XML validation.

Command line:

run\helios data\surveys\toyblocks\als_toyblocks.xml --lasOutput

Python:

python pyhelios\util\xmlchecker.py data\surveys\toyblocks\als_toyblocks.xml --lasOutput

The archiver

You may want to share or publish your simulation, so that others can reproduce it. For this purpose, you can use the tool archive.py, which will write

  • the data folder with all sceneparts, scanner-XMLs, platform XMLs, scene-XMLs and survey-XMLs for the specified survey(s)
  • the assets folder
  • the run folder (from your HELIOS repository or downloaded from GitHub)
  • a file version.txt containing the version number [To do: image of folder structure]

Usage example:

python pyhelios\util\archive.py run\helios.exe data\surveys\toyblocks\als_toyblocks.xml my_archive.zip

Multiple surveys can be specified by creating an ASCII file with one survey path per line and providing this instead of the survey XML.

Such an ASCII file my_surveys.txt may look like this:

data\surveys\survey1.xml
data\surveys\survey2.xml
data\surveys\survey3.xml

To create the zip-archive, run:

python pyhelios\util\archive.py run\helios.exe my_surveys.txt archive.zip

b) Helper modules for configuring XML files for a simulation

The scene writer

The scene writer contains a number of functions which facilitate writing scene XMLs, which can then be executed either with pyhelios or by running HELIOS++ from the command line. These functions include:

  • adding transformation filters
  • adding sceneparts
  • creating the scene

Simple usage demo in Python:

Import the script

from pyhelios.util import scene_writer

Create transformation filters

filters = scene_writer.add_transformation_filters(translation=[478335.125, 5473887.89, 0.0], rotation=[0, 0, 90], on_ground=-1)

Create scene parts Here, we load a digital elevation model (DEM) from a GeoTIFF file and a 3D model of a tree from an OBJ file. To our seconds scene part, the tree, we apply the transformation that was created in the previous step.

sp = scene_writer.create_scenepart_tiff(r"data/sceneparts/tiff/dem_hd.tif",
                               matfile=r"data/sceneparts/basic/groundplane/groundplane.mtl",
                               matname="None")
sp2 = scene_writer.create_scenepart_obj("data/sceneparts/arbaro/black_tupelo_low.obj", trafofilter=filters)

Create the scene XML

Finally, we create a scene XML file with these scene parts.

scene = scene_writer.build_scene(scene_id="test", name="test_scene", sceneparts=[sp, sp2])
print(scene)

Output:

<?xml version="1.0" encoding="UTF-8"?>
<document>
    <scene id="test" name="test_scene">
        
        <part>
            <filter type="geotiffloader">
                <param type="string" key="filepath" value="data/sceneparts/tiff/dem_hd.tif" />
                <param type="string" key="matfile" value="data/sceneparts/basic/groundplane/groundplane.mtl" />
                <param type="string" key="matname" value="None" />
            </filter>
            
        </part>

        <part>
            <filter type="objloader">
                <param type="string" key="filepath" value="data/sceneparts/arbaro/black_tupelo_low.obj up="z" />
            </filter>
            
            <filter type="translate">  
                <param type="integer" key="onGround" value="-1" />
                <param type="vec3" key="offset" value="478335.125;5473887.89;0.0" /> 
            </filter>

            <filter type="rotate">
                <param key="rotation" type="rotation">  
                    <rot angle_deg="0" axis="x"/>  
                    <rot angle_deg="0" axis="y"/>  
                    <rot angle_deg="90" axis="z"/>  
                </param>
            </filter>

        </part>
    </scene>
</document>

Check out this Jupyter Notebook to see how these functions may be used in a typical workflow.

The flight planner

The flight planner facilitates the creation of survey files, specifically of the legs (or waypoints) of a survey. The flight planner functionality encompasses:

  • create the flight plan (i.e., the waypoints) for given parameters (flight pattern, strip spacing, bounding box of the scan area)
  • create waypoints from a shapefile
  • plot a flight plan
  • write the legs for the survey XML file

Simple usage demo in Python:

Import the script

from pyhelios.util import flight_planner

Define the parameters

bbox = [-200, -50, 200, 50]
strip_spacing = 45
alt = 1000
scannerSettings = "template1"
platform_speed = 5

Generate waypoints

# possible flight-patterns: parallel, criss-cross (default: parallel)
waypoints, center_point, distance = flight_planner.compute_flight_lines(bbox, spacing=strip_spacing, flight_pattern="parallel") 

# or to create a rotated flight plan, e.g. by 15 degrees:
waypoints, center_point, distance = flight_planner.compute_flight_lines(bbox, spacing=strip_spacing, rotate_deg=15)

print(f"Flight duration: {distance / platform_speed / 60:.2f} min")

Output:

Flight duration: 4.30 min

Plot the flight plan (optional)

plot = flight_planner.plot_flight_plan(waypoints)
plot.show()

Output:

Herunterladen

Write the legs for the survey XML file

print(str(flight_planner.write_legs(waypoints, altitude=alt, template_id=scannerSettings, speed=platform_speed)))

Output:

        <leg>
            <platformSettings x="181.5383082282002" y="-95.23047120351222" z="1000" movePerSec_m="5" />
            <scannerSettings template="template1" trajectoryTimeInterval_s="0.05" />
        </leg>
        
        <leg>
            <platformSettings x="-204.8320222874271" y="8.297146837496072" z="1000" movePerSec_m="5" />
            <scannerSettings template="template1" active="false" trajectoryTimeInterval_s="0.05" />
        </leg>
        
        <leg>
            <platformSettings x="-193.18516525781365" y="51.76380902050415" z="1000" movePerSec_m="5" />
            <scannerSettings template="template1" trajectoryTimeInterval_s="0.05" />
        </leg>
        
        <leg>
            <platformSettings x="193.18516525781365" y="-51.76380902050415" z="1000" movePerSec_m="5" />
            <scannerSettings template="template1" active="false" trajectoryTimeInterval_s="0.05" />
        </leg>
        
        <leg>
            <platformSettings x="204.8320222874271" y="-8.297146837496072" z="1000" movePerSec_m="5" />
            <scannerSettings template="template1" trajectoryTimeInterval_s="0.05" />
        </leg>
        
        <leg>
            <platformSettings x="-181.5383082282002" y="95.23047120351222" z="1000" movePerSec_m="5" />
            <scannerSettings template="template1" active="false" trajectoryTimeInterval_s="0.05" />
        </leg>

Check out this Jupyter Notebook to see how the flight_planner may be used in a typical workflow.