Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions StkAutomation/Python/StkMetaDataExtractor/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
# STK Metadata Extractor

This script will read an STK scenario with an instance of STK Engine to extract metadata from that scenario.
This script will read an STK scenario with an instance of STK Engine to extract metadata from that scenario about each of the objects. It will also export a Cesium display summary file.

As a Code Example, this script should demonstrate how users can iterate through all objects in a scenario and interrogate each object type for information related to that specific type.
As a Code Example, this script should demonstrate how users can iterate through all objects in a scenario and interrogate each object type for information related to that specific object type.

This is a work in progress but the goal will be to create a summary file (formatted in XML, JSON or other) to briefly describe the scenario contents.

# Usage

This script is intended to be used from the command line with two arguments:
1. the path to a scenario file (*.sc or *.vdf).
2. the desired path of the output file (*.xml or *.json)
2. the desired directory for the output files (*.xml and *.czml)

Example:
python StkMetadataExtractor.py "c:\Temp\sampleScenario.vdf" "c:\Temp\summary.xml"

The output summary.xml file will briefly describe the contents of the scenario.
python StkMetadataExtractor.py "c:\Temp\sampleScenario.vdf" "c:\Temp"

The output XML file and CZML file will have the same name as the scenario - in this example "c:\Temp\sampleScenario.xml" and "c:\Temp\sampleScenario.czml".



Expand Down
221 changes: 175 additions & 46 deletions StkAutomation/Python/StkMetaDataExtractor/stkMetaDataExtractor.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,181 @@
# Get reference to running STK instance using win32com
from win32com.client import GetActiveObject
uiApplication = GetActiveObject('STK12.Application')
import json
import sys
import os

def dict2xml(d, root_node=None):
wrap = False if None == root_node or isinstance(d, list) else True
root = 'objects' if None == root_node else root_node
root_singular = root[:-1] if 's' == root[-1] and None == root_node else root
xml = ''
children = []

# Get our IAgStkObjectRoot interface
root = uiApplication.Personality2
if isinstance(d, dict):
for key, value in dict.items(d):
if isinstance(value, dict):
children.append(dict2xml(value, key))
elif isinstance(value, list):
children.append(dict2xml(value, key))
else:
xml = xml + ' ' + key + '="' + str(value) + '"'
else:
for value in d:
children.append(dict2xml(value, root_singular))

end_tag = '>' if 0 < len(children) else '/>'

print(root.CurrentScenario.InstanceName)
print("Total number of objects: {0}".format(len(root.CurrentScenario.Children)))
if wrap or isinstance(d, dict):
xml = '<' + root + xml + end_tag

for stkObject in root.CurrentScenario.Children:
print(stkObject.ClassName + " " + stkObject.InstanceName)
if 0 < len(children):
for child in children:
xml = xml + child

if wrap or isinstance(d, dict):
xml = xml + '</' + root + '>'

return xml

def SummarizeStkObject(stkObject):
# Create the Properties object to hold object information, specifically Name and Class
props = {'Name': stkObject.InstanceName}

if stkObject.ClassName == "Facility":
if stkObject.ShortDescription:
props['ShortDescription'] = stkObject.ShortDescription
if stkObject.LongDescription:
props['LongDescription'] = stkObject.LongDescription

# Capture any metadata provided on an object
for key in stkObject.Metadata.Keys:
props[key] = stkObject.Metadata[key]

# For each type of object, allow for unique information to be captured
if stkObject.ClassName == "Facility" or stkObject.ClassName == "Target" or stkObject.ClassName == "Place":
positionArray = stkObject.Position.QueryPlanetocentric()
print('Position: {0:3.2f} {1:3.2f}'.format(positionArray[0], positionArray[1]))

#if stkObject.ClassName == "AdvCAT":
#if stkObject.ClassName == "Aircraft":
#if stkObject.ClassName == "Area Target":
#if stkObject.ClassName == "Attitude Coverage":
#if stkObject.ClassName == "Chain":
#if stkObject.ClassName == "CommSystem":
#if stkObject.ClassName == "Constellation":
#if stkObject.ClassName == "Coverage Definition":
#if stkObject.ClassName == "Facility":
#if stkObject.ClassName == "Ground Vehicle":
#if stkObject.ClassName == "Launch Vehicle":
#if stkObject.ClassName == "Line Target":
#if stkObject.ClassName == "MTO (Multi-Track Object)":
#if stkObject.ClassName == "Missile":
#if stkObject.ClassName == "Missile System":
#if stkObject.ClassName == "Planet":
#if stkObject.ClassName == "Radar":
#if stkObject.ClassName == "Receiver":
#if stkObject.ClassName == "Satellite":
#if stkObject.ClassName == "Scenario":
#if stkObject.ClassName == "Sensor":
#if stkObject.ClassName == "Ship":
#if stkObject.ClassName == "Star":
#if stkObject.ClassName == "Target":
#if stkObject.ClassName == "Transmitter":
#if stkObject.ClassName == "Figure of Merit":
#if stkObject.ClassName == "Root":
#if stkObject.ClassName == "Access":
#if stkObject.ClassName == "Coverage":
#if stkObject.ClassName == "Attitude Figure of Merit":
#if stkObject.ClassName == "Submarine":
#if stkObject.ClassName == "Antenna":
#if stkObject.ClassName == "Place":
#if stkObject.ClassName == "Volumetric":
props['Latitude'] = positionArray[0]
props['Longitude'] = positionArray[1]
props['Altitude'] = positionArray[2]

elif stkObject.ClassName == "Sensor":
patternType = stkObject.PatternType
patternTypes = ['ComplexConic', 'Custom', 'PHalfPower', 'Rectangular', 'SAR', 'SimpleConic', 'EOIR']
props['PatternType'] = patternTypes[patternType]

elif stkObject.ClassName == "Antenna":
antennaType = stkObject.Model.Name
props['AntennaType'] = antennaType

elif stkObject.ClassName == "Radar":
radarType = stkObject.Model.Name
props['RadarType'] = radarType

elif stkObject.ClassName == "Receiver":
receiverType = stkObject.Model.Name
props['ReceiverType'] = receiverType

elif stkObject.ClassName == "Transmitter":
transmitterType = stkObject.Model.Name
props['TransmitterType'] = transmitterType

elif stkObject.ClassName == "Satellite":
possiblePropagator = stkObject.PropagatorSupportedTypes
for propagatorType in possiblePropagator:
if propagatorType[0] == stkObject.PropagatorType:
props['PropagatorType'] = propagatorType[1]

elif stkObject.ClassName == "AreaTarget":
centroidPosition = stkObject.Position.QueryPlanetocentricArray()
props['CentroidLatitude'] = centroidPosition[0]
props['CentroidLongitude'] = centroidPosition[1]
props['CentroidAltitude'] = centroidPosition[2]

elif stkObject.ClassName == "CoverageDefinition":
gridClasses = ['eGridClassUnknown','eGridClassAircraft','eGridClassFacility','eGridClassRadar','eGridClassReceiver','eGridClassSatellite','eGridClassSubmarine','eGridClassTarget','eGridClassTransmitter','eGridClassGroundVehicle','eGridClassShip','eGridClassPlace','eGridClassSensor']
gridClass = stkObject.PointDefinition.GridClass
props['GridClass'] = gridClass
props['GridClassName'] = gridClasses[gridClass+1]

elif stkObject.ClassName == "Missile":
possibleTrajectory = stkObject.TrajectorySupportedTypes
usedTrajectory = stkObject.TrajectoryType
for trajectory in possibleTrajectory:
if trajectory[0] == usedTrajectory:
props['TrajectoryType'] = trajectory[1]

elif stkObject.ClassName == "Planet":
centralBody = stkObject.PositionSourceData.CentralBody
props['CentralBody'] = centralBody

elif stkObject.ClassName == "Chain":
chainobjects = stkObject.Objects
props['NumberOfLinks'] = chainobjects.Count

elif stkObject.ClassName == "Constellation":
constellationobjects = stkObject.Objects
props['NumberOfItems'] = constellationobjects.Count

# Determine if it is necessary to iterate through the potential child objects
if stkObject.HasChildren:
props['Children'] = {}

for stkChild in stkObject.Children:
if stkChild.ClassName not in props['Children']:
props['Children'][stkChild.ClassName] = []
# Summarize the child objects
try:
childSummary = SummarizeStkObject(stkChild)
props['Children'][stkChild.ClassName].append(childSummary)
except:
print("ERROR: An exception occurred summarizing " + stkObject.InstanceName)

# Return the summary
return props

inputScenarioPath = sys.argv[1]
outputSummaryDirectory = sys.argv[2]
print("Launching STK")
# Get reference to running STK instance using win32com
from win32com.client import Dispatch
uiApplication = Dispatch('STK12.Application')
uiApplication.Visible = False

# Get our IAgStkObjectRoot interface
root = uiApplication.Personality2

print("Loading scenario: " + inputScenarioPath)
# Determine if the scenario to be loaded is a vdf or sc file and laod as appropriate
if inputScenarioPath.endswith('.vdf'):
root.LoadVDF(inputScenarioPath, '')
elif inputScenarioPath.endswith('.sc'):
root.LoadScenario(inputScenarioPath)
else:
print('ERROR: ' + inputScenarioPath + ' is not a recognized scenario file')
exit

# Export a CZML preview from STK
outputCzmlPath = os.path.join(outputSummaryDirectory, root.CurrentScenario.InstanceName + ".czml")
cmd = 'ExportCZML * "' + outputCzmlPath + '" http://assets.agi.com/models/'
try:
print("Exporting CZML to " + outputCzmlPath)
root.ExecuteCommand(cmd)
except:
print("ERROR: An exception occurred generating CZML")

# Generating XML
# Get the summary of the scenario
try:
print("Summarizing STK scenario")
summary = SummarizeStkObject(root.CurrentScenario)

outputXmlSummaryPath = os.path.join(outputSummaryDirectory, root.CurrentScenario.InstanceName + ".xml")

print("Writing XML summary to " + outputXmlSummaryPath)
xmlSummary = dict2xml(summary)
with open(outputXmlSummaryPath, "w") as f:
f.write(xmlSummary)
except:
print("ERROR: An exception occurred generating XML")

# Generating Json
# outputJsonSummaryPath = os.path.join(outputSummaryDirectory, root.CurrentScenario.InstanceName + ".json")
# with open(outputJsonSummaryPath, 'w') as outfile:
# json.dump(summary, outfile)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//=====================================================//
// Copyright 2006-2007, Analytical Graphics, Inc. //
//=====================================================//
using System.Reflection; // For Assembly Attributes
using System.Runtime.InteropServices; // For ComVisible

// NOTE: Provide a title for your assembly that matches the namespace/package
[assembly: AssemblyTitle("Stk12.AccessConstraint.ObjectDetection")]

// NOTE: Provide a title for your assembly that matches the namespace/package
[assembly: AssemblyDescription("Stk12.AccessConstraint.ObjectDetection")]

// NOTE: Provide a title for your assembly that matches the namespace/package
[assembly: AssemblyProduct("Object Detection Access Constraint Example")]

[assembly: AssemblyCompany("Analytical Graphics, Inc.")]

[assembly: AssemblyCopyright("")]

[assembly: AssemblyVersion("1.0.0.0")]

[assembly: ComVisible(true)]
//=====================================================//
// Copyright 2006-2007, Analytical Graphics, Inc. //
//=====================================================//
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//=====================================================//
// Copyright 2020, Analytical Graphics, Inc. //
//=====================================================//

// NOTE: Indicate that your Interface for your plugin is within
// the same namespace as your plugin.
namespace Stk12.AccessConstraint.ObjectDetection
{
// By not declaring otherwise, an auto-generated COM interface
// will be created for this class (a IDispatch interface)
public interface IParameters
{
double TargetCrossSectionSqMeters { get; set; }

bool DebugMode { get; set; }
int MsgInterval { get; set; }
}
}
//=====================================================//
// Copyright 2020, Analytical Graphics, Inc //
//=====================================================//
Loading