Scripting for Objects
There are a number of functions in the Ansys Orbit Determination Tool Kit (ODTK®) application to manage the scenario and objects in the scenario. See the sections below for example uses. For a complete list of functions, see Application Scope Functions.
Creating ODTK objects
You can create new objects with the CreateObj function. It takes three parameters: the parent object of the new object, the type of object to create, and the name of the new object. This function returns a handle to the new object.
Internal names used by the Automation Interface itself, such as "Name", "Class", "Count", "Item", "ItemExists", "ItemByName", and "GetProp", as well as class names of the object families such as "Satellite", "Filter", and "Smoother", are illegal names for ODTK objects and could cause issues.
Here are some sample scripts for creating objects:
COM
dim scen, sat1, trkSys, trkFac
set scen = ODTK.CreateObj(ODTK, "Scenario", "Example1")
set sat1 = ODTK.CreateObj(scen, "Satellite", "GEO_Sat1")
set trkSys = ODTK.CreateObj(scen, "TrackingSystem", "TrkSys1")
set trkFac = ODTK.CreateObj(trkSys, "Facility", "BOSS-A")
var scen, sat1, trkSys, trkFac;
scen = ODTK.CreateObj(ODTK, "Scenario", "Example1");
sat1 = ODTK.CreateObj(scen, "Satellite", "GEO_Sat1");
trkSys = ODTK.CreateObj(scen, "TrackingSystem", "TrkSys1");
trkFac = ODTK.CreateObj(trkSys, "Facility", "BOSS-A");
my ($scen, $sat1, $trkSys, $trkFac);
$scen = $ODTK->CreateObj($ODTK, "Scenario", "Example1");
$sat1 = $ODTK->CreateObj($scen, "Satellite", "GEO_Sat1");
$trkSys = $ODTK->CreateObj($scen, "TrackingSystem", "TrkSys1");
$trkFac = $ODTK->CreateObj($trkSys, "Facility", "BOSS-A");
scen = ODTK.CreateObj(ODTK, "Scenario", "Example1")
sat1 = ODTK.CreateObj(scen, "Satellite", "GEO_Sat1")
trkSys = ODTK.CreateObj(scen, "TrackingSystem", "TrkSys1")
trkFac = ODTK.CreateObj(trkSys, "Facility", "BOSS-A")
scen = odtk.invoke('CreateObj', odtk, 'Scenario', 'MyScenario');
sat = odtk.invoke('CreateObj', scen, 'Satellite', 'MySat');
trkSys = odtk.invoke('CreateObj', scen, 'TrackingSystem', 'TrkSys1');
trkFac = odtk.invoke('CreateObj', trkSys, 'Facility', 'BOSS-A');
Cross-Platform API
# ensure new scenario
if odtk_child_count > 0:
# close scenario
odtk.application.deleteObject('', odtk.scenario[0])
print('Scenario closed.')
odtk.application.createObj(odtk, 'Scenario', 'TestScenario')
print('Scenario created.')
# create satellites
zeroth_satellite_name = 'mySat'
zero_as_satellite_name = '0'
odtk.application.createObj(odtk.scenario[0], 'Satellite', zeroth_satellite_name)
my_other_sat = odtk.application.createObj(odtk.scenario[0], 'Satellite', 'myOtherSat')
odtk.application.createObj(odtk.scenario[0], 'Satellite', zero_as_satellite_name)
print('Satellites created.')
# create filter
odtk.application.createObj(odtk.scenario[0], 'Filter', 'Filter1')
% ensure new scenario
if odtkChildCount > 0
% close scenario
odtk.application.deleteObject("", odtk.scenario{0});
fprintf("Scenario closed.\n");
end
odtk.application.createObj(odtk, "Scenario", "TestScenario");
fprintf("Scenario created.\n");
% create satellites
zerothSatelliteName = "mySat";
zeroAsSatelliteName = "0";
odtk.application.createObj(odtk.scenario{0}, "Satellite", zerothSatelliteName);
myOtherSat = odtk.application.createObj(odtk.scenario{0}, "Satellite", "myOtherSat");
odtk.application.createObj(odtk.scenario{0}, "Satellite", zeroAsSatelliteName);
fprintf("Satellites created.\n");
% create filter
odtk.application.createObj(odtk.scenario{0}, "Filter", "Filter1");
// ensure new scenario
if (odtkChildCount > 0)
{
// close scenario
odtk("application")("deleteObject").Invoke("", odtk("scenario")[0]);
std::cout << "Scenario closed.\n";
}
odtk("application")("createObj").Invoke(odtk, "Scenario", "TestScenario");
std::cout << "Scenario created.\n";
// create satellites
const auto zerothSatelliteName = "mySat";
const auto zeroAsSatelliteName = "0";
const auto fourthSatName = "fourth_sat";
odtk("application")("createObj").Invoke(odtk("scenario")[0], "Satellite", zerothSatelliteName);
const auto myOtherSat = odtk("application")("createObj").InvokeAttrProxy(odtk("scenario")[0], "Satellite", "myOtherSat");
odtk("application")("createObj").Invoke(odtk("scenario")[0], "Satellite", zeroAsSatelliteName);
odtk("application")("createObj").Invoke(odtk("scenario")[0], "Satellite", fourthSatName);
std::cout << "Satellites created.\n";
// create filter
odtk("application")("createObj").Invoke(odtk("scenario")[0], "Filter", "Filter1");
// ensure new scenario
int odtkChildCout = odtk.get(“children.count”).asInt();
if (odtkChildCount > 0)
{
// close scenario
odtk.get("application.deleteObject").invoke(odtk.get("Scenario[0]”));
System.out.println("Scenario closed.");
}
odtk.get("application.createObj").invoke(odtk, "Scenario", "TestScenario");
System.out.println("Scenario created.");
// create satellites
String zerothSatelliteName = "mySat";
String zeroAsSatelliteName = "0";
String fourthSatName = "fourthSat";
odtk.get("application.createObj").invoke(new AttrRef(“ODTK.Scenario[0]”), "Satellite", zerothSatelliteName);
AttrProxy myOtherSat = odtk.get("application.createObj").invokeAttr(odtk.get("Scenario[0]”), "Satellite", "myOtherSat");
odtk.get("application.createObj").invoke(odtk.get("Scenario[0]"), "Satellite", zeroAsSatelliteName);
odtk.get("application.createObj").invoke(odtk.get("Scenario[0]"), "Satellite", fourthSatName);
System.out.println("Satellites created.");
// create filter
odtk.get("application.createObj").invoke(odtk.get("Scenario[0]"), "Filter", "Filter1");
Deleting ODTK objects
The DeleteObject function takes an object handle and returns a success status.
Here are some sample scripts for deleting objects:
COM
Cross-Platform API
const auto deleted = odtk("deleteobject").InvokeBool(myOtherSat);
std::cout << "Deleted myOtherSat: " << BoolToString(deleted) << "\n";
boolean deleted = odtk.get("deleteobject").invokeBool(myOtherSat);
System.out.println("Deleted myOtherSat: " + deleted );
Saving ODTK objects
You can save the scenario or any object to a file with the SaveObj function. It takes three parameters: the object handle, the destination file name, and the boolean SaveObjectChildren flag.
Here are some sample scripts for saving objects:
COM
set newSat = ODTK.SaveObj(scen, "C:\Temp\Example1.sco", true)
set newSat = ODTK.SaveObj(sat, "C:\Temp\GEO_Sat1.sao", false)
set newSat = ODTK.SaveObj(trkSys, "C:\Temp\TrkSys1.tso", true)
var newSat = ODTK.SaveObj(scen, "C:\\Temp\\Example1.sco", true)
newSat = ODTK.SaveObj(sat, "C:\\Temp\\GEO_Sat1.sao", false)
newSat = ODTK.SaveObj(trkSys, "C:\\Temp\\TrkSys1.tso", true)
my $newSat = $ODTK->SaveObj($scen, "C:\\Temp\\Example1.sco", true);
$newSat = $ODTK->SaveObj($sat, "C:\\Temp\\GEO_Sat1.sao", false);
$newSat = $ODTK->SaveObj($trkSys, "C:\\Temp\\TrkSys1.tso", true);
newSat = ODTK.SaveObj(scen, "C:\\Temp\\Example1.sco", True)
newSat = ODTK.SaveObj(sat, "C:\\Temp\\GEO_Sat1.sao", False)
newSat = ODTK.SaveObj(trkSys, "C:\\Temp\\TrkSys1.tso", True)
newSat = odtk.invoke('SaveObj', scen, 'C:\Temp\Example1.sco', true);
newSat = odtk.invoke('SaveObj', sat, 'C:\Temp\GEO_Sat1.sao', false);
newSat = odtk.invoke('SaveObj', trkSys, 'C:\Temp\TrkSys1.tso', true);
Cross-Platform API
# It takes three parameters: the object handle, the destination file name, and the boolean SaveObjectChildren flag.
# from pathlib import Path
this_dir_path = Path('.').resolve()
scenario_file_path = this_dir_path / 'Example1.sco'
odtk.SaveObj(odtk.scenario[0], str(scenario_file_path), True)
print(f'Scenario saved to {scenario_file_path}')
% It takes three parameters: the object handle, the destination file name,
% and the boolean SaveObjectChildren flag.
[thisFolderPath] = fileparts(mfilename('fullpath'));
scenarioFilePath = [thisFolderPath, filesep, 'Example1.sco'];
odtk.SaveObj(odtk.scenario{0}, scenarioFilePath, true);
fprintf("Scenario saved to %s.\n", scenarioFilePath);
// It takes three parameters : the object handle, the destination file name,
// and the boolean SaveObjectChildren flag.
const std::string thisFolderPath = GetThisFolderPath();
const auto scenarioFilePath = thisFolderPath + s_pathSeparator + "Example1.sco";
odtk("SaveObj").Invoke(odtk("scenario")[0], scenarioFilePath, true);
std::cout << "Scenario saved to " << scenarioFilePath << "\n";
// It takes three parameters : the object handle, the destination file name,
// and the boolean SaveObjectChildren flag.
String thisFolderPath = System.getProperty(“user.dir”);
String scenarioFilePath = thisFolderPath + Client.PATH_SEPARATOR + "Example1.sco";
odtk.get("SaveObj").invoke(odtk.get("Scenario[0]"), scenarioFilePath, true);
System.out.println("Scenario saved to " + scenarioFilePath);
Loading ODTK objects
Only one scenario at a time is allowed; unload the current scenario before loading the next one.
To load an object at a later time, use the LoadObj function. Its parameters are the path of the parent object, where the new object is to be loaded, and the source file name containing the object to be loaded. You can load Satellite and Facility objects that are produced by either the ODTK application or the Systems Tool Kit® (STK®) application.
Here are some sample scripts for loading objects:
COM
bSuccess = ODTK.LoadObj("", "C:\Temp\Scenario1.sco")
bSuccess = ODTK.LoadObj("Scenario1", "C:\Temp\STK_Sat.sa")
bSuccess = ODTK.LoadObj("Scenario1", "C:\Temp\ODTK_Sat.sao")
bSuccess = ODTK.LoadObj("Scenario1", "C:\Temp\TrkSys1.tso")
bSuccess = ODTK.LoadObj("Scenario1.TrkSys1", "C:\Temp\STK_Fac.f")
bSuccess = ODTK.LoadObj("Scenario1.TrkSys1", "C:\Temp\ODTK_Fac.fo")
bSuccess = ODTK.LoadObj("", "C:\\Temp\\Scenario1.sco");
bSuccess = ODTK.LoadObj("Scenario1", "C:\\Temp\\STK_Sat.sa");
bSuccess = ODTK.LoadObj("Scenario1", "C:\\Temp\\ODTK_Sat.sao");
bSuccess = ODTK.LoadObj("Scenario1", "C:\\Temp\\TrkSys1.tso");
bSuccess = ODTK.LoadObj("Scenario1.TrkSys1", "C:\\Temp\\STK_Fac.f");
bSuccess = ODTK.LoadObj("Scenario1.TrkSys1", "C:\\Temp\\ODTK_Fac.fo");
$bSuccess = $ODTK->LoadObj("", "C:\\Temp\\Scenario1.sco");
$bSuccess = $ODTK->LoadObj("Scenario1", "C:\\Temp\\STK_Sat.sa");
$bSuccess = $ODTK->LoadObj("Scenario1", "C:\\Temp\\ODTK_Sat.sao");
$bSuccess = $ODTK->LoadObj("Scenario1", "C:\\Temp\\TrkSys1.tso");
$bSuccess = $ODTK->LoadObj("Scenario1.TrkSys1", "C:\\Temp\\STK_Fac.f");
$bSuccess = $ODTK->LoadObj("Scenario1.TrkSys1", "C:\\Temp\\ODTK_Fac.fo");
bSuccess = ODTK.LoadObj("", "C:\\Temp\\Scenario1.sco")
bSuccess = ODTK.LoadObj("Scenario1", "C:\\Temp\\STK_Sat.sa")
bSuccess = ODTK.LoadObj("Scenario1", "C:\\Temp\\ODTK_Sat.sao")
bSuccess = ODTK.LoadObj("Scenario1", "C:\\Temp\\TrkSys1.tso")
bSuccess = ODTK.LoadObj("Scenario1.TrkSys1", "C:\\Temp\\STK_Fac.f")
bSuccess = ODTK.LoadObj("Scenario1.TrkSys1", "C:\\Temp\\ODTK_Fac.fo")
bSuccess = odtk.invoke('LoadObj', '', 'C:\Temp\Example1.sco');
bSuccess = odtk.invoke('LoadObj', 'Scenario1', 'C:\Temp\STK_Sat.sa');
bSuccess = odtk.invoke('LoadObj', 'Scenario1', 'C:\Temp\ODTK_Sat.sao');
bSuccess = odtk.invoke('LoadObj', 'Scenario1', 'C:\Temp\TrkSys1.tso');
bSuccess = odtk.invoke('LoadObj', 'Scenario1.TrkSys1', 'C:\Temp\STK_Fac.f');
bSuccess = odtk.invoke('LoadObj', 'Scenario1.TrkSys1', 'C:\Temp\ODTK_Fac.fo');
Cross-Platform API
# close the scenario
odtk.application.deleteObject('', odtk.scenario[0])
# load the scenario
scenario_loaded = odtk.LoadObj('', str(scenario_file_path))
% close the scenario
odtk.application.deleteObject("", odtk.scenario{0});
% load the scenario
scenarioLoaded = odtk.LoadObj("", scenarioFilePath);
// close the scenario
odtk("application")("deleteObject").Invoke(odtk("scenario")[0]);
// load the scenario
const auto scenarioLoaded = odtk("LoadObj").InvokeBool("", scenarioFilePath);
std::cout << "Scenario loaded from " << scenarioFilePath << ": " << BoolToString(scenarioLoaded) << "\n";
// close the scenario
odtk.get("application.deleteObject").invoke(“”,odtk.get("Scenario[0]"));
// load the scenario
boolean scenarioLoaded = odtk.get("LoadObj").invokeBool("", scenarioFilePath);
System.out.println("Scenario loaded from " + scenarioFilePath + ": " + scenarioLoaded);
Testing to see if an ODTK object exists
The scripting interface supports an ItemExists() method to test if an object exists.
Consider the below script which accesses an ODTK scenario with Facilities named "02", "03", and "AA".
Example JavaScript:
// Obtain the list of Facilities in the Tracking System in the Scenario
let facilities = ODTK.Scenario(0).TrackingSystem(0).Children.Facility;
// The Item() function looks up items by index if the parameter can be interpreted as an index.
// If the parameter cannot be interpreted as an index, it will interpret the parameter as the string name of the item.
alert(facilities.Item(0).Name.value()); // Displays '02'
alert(facilities.Item("00").Name.value()); // Displays '02'
alert(facilities.Item("01").Name.value()); // Displays '03'
alert(facilities.Item("02").Name.value()); // Displays 'AA'
alert(facilities.Item("AA").Name.value()); // Displays 'AA'
// Examples that throw 'Index Out of Range' errors.
try {
facilities.Item("03").Name.value();
} catch (error) {
alert(error); // Displays 'Error: Index Out of Range'
}
try {
facilities.Item("07").Name.value();
} catch (error) {
alert(error); // Displays 'Error: Index Out of Range'
}
// The ItemExists() function looks up items by string name only.
alert(facilities.ItemExists("01")); // Displays 'false'
alert(facilities.ItemExists("02")); // Displays 'true'
alert(facilities.ItemExists("AA")); // Displays 'true'
// The ItemByName() function follows the same policy as Item(). See comment above for information.
alert(facilities.ItemByName(0).Name.value()); // Displays '02'
alert(facilities.ItemByName("00").Name.value()); // Displays '02'
alert(facilities.ItemByName("01").Name.value()); // Displays '03'
alert(facilities.ItemByName("02").Name.value()); // Displays 'AA'
alert(facilities.ItemByName("AA").Name.value()); // Displays 'AA'
// Examples that throw 'Index Out of Range' errors.
try {
facilities.ItemByName("03").Name.value();
} catch (error) {
alert(error); // Displays 'Error: Index Out of Range'
}
try {
facilities.ItemByName("07").Name.value();
} catch (error) {
alert(error); // Displays 'Error: Index Out of Range'
}
Cross-Platform API
# Testing To See If An Object Exists
satellites = odtk.scenario[0].Children['Satellite']
# access by index
satellite_name = satellites[0].name.eval()
print(f'satellites[0] name: {satellite_name}')
# access by name
print(f'satellites[\"' + satellite_name + '\"] name: {satellites[satellite_name].name.eval()}')
# access using a name that is numeric (string)
satellite_name = satellites[zero_as_satellite_name].name.eval()
print(f'satellites[\"{zero_as_satellite_name}\"] name: {satellite_name}')
try:
# access by invalid index should throw an exception
satellite_name = satellites[7].name.eval()
raise Exception('The expected exception was not thrown.')
except ClientException as e:
if e.error_code == ClientExceptionCodes.INVALID_ATTRIBUTE_PATH and 'Index Out of Range' in str(e):
print('Non-existent satellite reference threw an exception as expected.')
else:
raise Exception('Unexpected exception was raised.')
# ItemExists returns true on existing name
exists = satellites.ItemExists(zeroth_satellite_name)
print(f'satellite \"{zeroth_satellite_name}\" exists: {exists}')
# ItemExists returns false on non-existent name
exists = satellites.ItemExists('07')
print(f'satellite \"07\" exists: {exists}')
% Testing To See If An Object Exists
% access by index
satelliteName = satellites{0}.name;
fprintf("satellites{0} name: %s\n", satelliteName);
% access by name
fprintf("satellites{""%1$s""} name: %2$s\n", satelliteName, satellites{satelliteName}.name);
% access using a name that is numeric (string)
satelliteName = satellites{zeroAsSatelliteName}.name;
fprintf("satellites{""%1$s""} name: %2$s\n", zeroAsSatelliteName, satelliteName);
try
% access by invalid index should throw an exception
satelliteName = satellites{7}.name;
throw(MException('ScriptingGuide:unexpectedError', 'The expected exception was not thrown.'));
catch ex
if ex.identifier == ClientExceptionIDs.InvalidAttributePath && contains(ex.message, "Index Out of Range")
fprintf("Non-existent satellite reference threw an exception as expected.\n");
else
throw(MException('ScriptingGuide:unexpectedError', 'An unexpected exception was thrown.'));
end
end
% ItemExists returns true on existing name
exists = satellites.ItemExists(zerothSatelliteName);
fprintf("satellite ""%1$s"" exists: %2$s\n", zerothSatelliteName, string(exists));
% ItemExists returns false on non-existent name
exists = satellites.ItemExists("07");
fprintf("satellite ""07"" exists: %s\n", string(exists));
// Testing To See If An Object Exists
// access by index
const auto satelliteName = satellites[0]("name").AsString();
std::cout << "satellites[0] name: " << satelliteName << "\n";
// access by name
std::cout << R"(satellites[")" << satelliteName << R"("] name: )" << satellites[satelliteName]("name").AsString() << "\n";
// access using a name that is numeric(string)
std::cout << R"(satellites[")" << zeroAsSatelliteName << R"("] name: )" << satellites[zeroAsSatelliteName]("name").AsString() << "\n";
try
{
// access by invalid index should throw an exception
const auto satellite7Name = satellites[7]("name").AsString();
throw std::runtime_error("The expected exception was not thrown.");
}
catch (const agi::odtk::ClientException& clientException)
{
if (clientException.ErrorCode == agi::odtk::clientExceptionCodes::InvalidAttributePath && strstr(clientException.what(), "Index Out of Range"))
{
std::cout << "Non-existent satellite reference threw an exception as expected.\n";
}
else
{
throw std::runtime_error("An unexpected exception was thrown.");
}
}
// ItemExists returns true on existing name
std::cout << "satellite \"" << zerothSatelliteName << "\" exists: " << BoolToString(satellites("ItemExists").InvokeBool(zerothSatelliteName)) << "\n";
// ItemExists returns false on non-existent name
std::cout << "satellite \"07\" exists: " << BoolToString(satellites("ItemExists").InvokeBool("07")) << "\n";
// Testing To See If An Object Exists
// access by index
// Testing To See if An Object Exists
AttrProxy satProxy = odtk.get("Scenario[0].Children['Satellite']");
satellites = satProxy.asIterProxy();
// access by index
String satelliteName = satProxy.getItem(0).get("name").asString();
System.out.println("satellites[0] name: " + satelliteName);
// access by name
System.out.println("satProxy.get(" + satelliteName + ") name: " + satProxy.get(satelliteName + ".name").asString());
// access using a name that is numeric (String);
satelliteName = satProxy.get(zeroAsSatelliteName + ".name").asString();
System.out.println("satProxy.get(" + zeroAsSatelliteName + ") name: " + satelliteName);
try {
// access by invalid index should throw an exception
satProxy.getItem(7).get("name").asString();
throw new Exception("The expected exception was not thrown.");
} catch (ClientException e) {
if (e.errorCode.equals(ClientExceptionCodes.INVALID_ATTRIBUTE_PATH)
&& e.message.contains("Index Out of Range"))
{
System.out.println("Non-existent satellite reference threw an exception as expected.");
} else {
throw new Exception("Unexpected exception was raised.");
}
}
// ItemExists returns true on existing name
boolean exists = satProxy.get("ItemExists").invokeBool(zerothSatelliteName);
System.out.println("Satellite " + zerothSatelliteName + " exists: " + exists);
// ItemExists returns false on non-existent name
exists = satProxy.get("ItemExists").invokeBool("07");
System.out.println("Satellite \"07\" exists: " + exists);