VSPAERO Control Surface Group Functions

This group of functions is available for manipulating VSPAERO control surface groups through the API. Note, VSPAERO also includes rectangle type sub-surfaces as possible control surfaces.

AutoGroupVSPAEROControlSurfaces()

Creates the initial default grouping for the control surfaces.

AddCpSlice(cut_type, location)

Add a new VSPAERO control surface group using the default naming convention.

GetNumCpSlices()

Get the number of Cp slices in the VSPAERO Cp Slicer

GetCpSliceID(slice_index)

Get the ID of the Cp slice at the specified index

DelCpSlice(slice_index)

Delete a single Cp slice from the VSPAERO Cp Slicer

DeleteAllCpSlices()

Delete all Cp slices from the VSPAERO Cp Slicer

DeleteVSPAEROControlSurfaceGroup(CSGroupIndex)

Delete one VSPAERO control surface group, by index.

CreateVSPAEROControlSurfaceGroup()

Add a VSPAERO control surface group.

AddAllToVSPAEROControlSurfaceGroup(CSGroupIndex)

Add all available control surfaces to the control surface group at the specified index

RemoveAllFromVSPAEROControlSurfaceGroup(...)

Remove all used control surfaces from the control surface group at the specified index

GetActiveCSNameVec(CSGroupIndex)

Get the names of each active (used) control surface in the control surface group at the specified index

GetCompleteCSNameVec()

Get the names of all control surfaces.

GetAvailableCSNameVec(CSGroupIndex)

Get the names of each available (not used) control surface in the control surface group at the specified index

SetVSPAEROControlGroupName(name, CSGroupIndex)

Set the name for the control surface group at the specified index

GetVSPAEROControlGroupName(CSGroupIndex)

Get the name of the control surface group at the specified index

AddSelectedToCSGroup(selected, CSGroupIndex)

Add each control surfaces in the array of control surface indexes to the control surface group at the specified index.

RemoveSelectedFromCSGroup(selected, CSGroupIndex)

Remove each control surfaces in the array of control surface indexes from the control surface group at the specified index.

GetNumControlSurfaceGroups()

Get the total number of control surface groups

FindControlSurfaceGroup(group_index)

Get the ID of a VSPAERO control surface group, so that its Parms can be reached the way any other container's are.

Details

openvsp.AutoGroupVSPAEROControlSurfaces()[source]

Creates the initial default grouping for the control surfaces. The initial grouping collects all surface copies of the sub-surface into a single group. For example if a wing is defined with an aileron and that wing is symmetrical about the xz plane there will be a surface copy of the master wing surface as well as a copy of the sub-surface. The two sub-surfaces may get deflected differently during analysis routines and can be identified uniquely by their full name.

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

#==== Add Vertical tail and set some parameters =====//
vert_id = AddGeom( "WING" )

SetGeomName( vert_id, "Vert" )

SetParmValUpdate( vert_id, "TotalArea", "WingGeom", 10.0 )
SetParmValUpdate( vert_id, "X_Rel_Location", "XForm", 8.5 )
SetParmValUpdate( vert_id, "X_Rel_Rotation", "XForm", 90 )

rudder_id = AddSubSurf( vert_id, SS_CONTROL )                      # Add Control Surface Sub-Surface

AutoGroupVSPAEROControlSurfaces()

Update()

print( "COMPLETE\n" )
control_group_settings_container_id = FindContainer( "VSPAEROSettings", 0 )   # auto grouping produces parm containers within VSPAEROSettings

#==== Set Control Surface Group Deflection Angle ====//
print( "\tSetting control surface group deflection angles..." )

# subsurfaces get added to groups with "CSGQualities_[geom_name]_[control_surf_name]"
# subsurfaces gain parm name is "Surf[surfndx]_Gain" starting from 0 to NumSymmetricCopies-1

deflection_gain_id = FindParm( control_group_settings_container_id, "Surf_" + aileron_id + "_0_Gain", "ControlSurfaceGroup_0" )
deflection_gain_id = FindParm( control_group_settings_container_id, "Surf_" + aileron_id + "_1_Gain", "ControlSurfaceGroup_0" )

#  deflect aileron
deflection_angle_id = FindParm( control_group_settings_container_id, "DeflectionAngle", "ControlSurfaceGroup_0" )

# Auto grouping puts each control surface in a group of its own, so the two
# that were added make two groups, and each holds one surface.
assert GetNumControlSurfaceGroups() == 2, "AutoGroupVSPAEROControlSurfaces did not make a group per surface"

for i in range( 2 ):
    # Each wing is symmetric, so its control surface arrives as two copies
    # and both land in the group.
    assert len( GetActiveCSNameVec( i ) ) == 2, "group " + str( i ) + " does not hold its control surface copies"
    assert len( GetVSPAEROControlGroupName( i ) ) > 0, "group " + str( i ) + " was not named"

# The Parms the grouping created have to be findable.
assert len( deflection_gain_id ) > 0, "the control surface group Parms were not created"
assert len( deflection_angle_id ) > 0, "the control surface group Parms were not created"

See also: CreateVSPAEROControlSurfaceGroup

openvsp.AddCpSlice(cut_type, location)[source]

Add a new VSPAERO control surface group using the default naming convention. The control surface group will not contain any control surfaces until they are added.

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

num_group = GetNumControlSurfaceGroups()

if  num_group != 1 :
    print( "Error: CreateVSPAEROControlSurfaceGroup" )
    assert False, "Error: CreateVSPAEROControlSurfaceGroup"

See also: AddSelectedToCSGroup :rtype: string :return: int Index of the new VSPAERO control surface group

Delete a VSPAERO control surface group. The control surfaces it held go back to being available, and the groups above it slide down to fill the gap.

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

SetVSPAEROControlGroupName( "Doomed_Group", group_index )

AddAllToVSPAEROControlSurfaceGroup( group_index )

num_active = len( GetActiveCSNameVec( group_index ) )

DeleteVSPAEROControlSurfaceGroup( group_index )

assert GetNumControlSurfaceGroups() == 0, "DeleteVSPAEROControlSurfaceGroup did not remove the group"

# The surfaces it held are available again in a fresh group.
new_index = CreateVSPAEROControlSurfaceGroup()

assert len( GetAvailableCSNameVec( new_index ) ) == num_active, "the deleted group did not release its control surfaces"

# An index past the end has to be rejected.  The error queue is reached
# through the error manager singleton in Python.
err_mgr = ErrorMgrSingleton.getInstance()

DeleteVSPAEROControlSurfaceGroup( GetNumControlSurfaceGroups() )

assert err_mgr.GetNumTotalErrors() > 0, "DeleteVSPAEROControlSurfaceGroup accepted an index past the end"

# That error was raised deliberately, so take it back off the queue.
while err_mgr.GetNumTotalErrors() > 0 :
    err = err_mgr.PopLastError()

See also: CreateVSPAEROControlSurfaceGroup, GetNumControlSurfaceGroups :param [in]: CSGroupIndex int Index of the control surface group

Add a Cp slice to the VSPAERO Cp Slicer. The CpSlicer analysis has nothing to slice until at least one has been added.

# A fresh model already carries a default slice, so count from there.
num_before = GetNumCpSlices()

slice_id = AddCpSlice( X_DIR, 0.5 )

assert len( slice_id ) > 0, "AddCpSlice did not add a slice"
assert GetNumCpSlices() == num_before + 1, "AddCpSlice did not add a slice"

# The slice is its own Parm Container, so its cut can be read back.
assert abs( GetParmVal( FindParm( slice_id, "CutPosition", "CpSlice" ) ) - 0.5 ) < 1e-9, "AddCpSlice did not place the cut"
assert GetCpSliceID( num_before ) == slice_id, "GetCpSliceID does not agree with AddCpSlice"

See also: GetNumCpSlices, GetCpSliceID, DelCpSlice, DeleteAllCpSlices :param [in]: cut_type int Slice direction enum (X_DIR, Y_DIR or Z_DIR) :param [in]: location double Location of the cut along that axis :rtype: string :return: string Cp slice ID

openvsp.GetNumCpSlices()[source]

Get the number of Cp slices in the VSPAERO Cp Slicer

num_before = GetNumCpSlices()

AddCpSlice( X_DIR, 0.5 )
AddCpSlice( Y_DIR, 0.25 )

assert GetNumCpSlices() == num_before + 2, "GetNumCpSlices did not count both slices"

# Every slice the count claims has to be findable.
for i in range( GetNumCpSlices() ):
    assert len( GetCpSliceID( i ) ) > 0, "slice " + str( i ) + " cannot be found"

See also: AddCpSlice, GetCpSliceID, DelCpSlice, DeleteAllCpSlices :rtype: int :return: int Number of Cp slices

openvsp.GetCpSliceID(slice_index)[source]

Get the ID of the Cp slice at the specified index

num_before = GetNumCpSlices()

first = AddCpSlice( X_DIR, 0.5 )
second = AddCpSlice( Y_DIR, 0.25 )

# Slices come back in the order they were added.
assert GetCpSliceID( num_before ) == first, "GetCpSliceID did not report the slices in order"
assert GetCpSliceID( num_before + 1 ) == second, "GetCpSliceID did not report the slices in order"

# An index past the end has to be rejected.  The error queue is reached
# through the error manager singleton in Python.
err_mgr = ErrorMgrSingleton.getInstance()

GetCpSliceID( GetNumCpSlices() )

assert err_mgr.GetNumTotalErrors() > 0, "GetCpSliceID accepted an index past the end"

# That error was raised deliberately, so take it back off the queue.
while err_mgr.GetNumTotalErrors() > 0 :
    err = err_mgr.PopLastError()

See also: AddCpSlice, GetNumCpSlices :param [in]: slice_index int Cp slice index :rtype: string :return: string Cp slice ID

openvsp.DelCpSlice(slice_index)[source]

Delete a single Cp slice from the VSPAERO Cp Slicer

DeleteAllCpSlices()

first = AddCpSlice( X_DIR, 0.5 )
second = AddCpSlice( Y_DIR, 0.25 )

DelCpSlice( 0 )

# Only the indexed slice goes, and the rest slide down.
assert GetNumCpSlices() == 1, "DelCpSlice removed the wrong slice"
assert GetCpSliceID( 0 ) == second, "DelCpSlice removed the wrong slice"

# An index past the end has to be rejected.  The error queue is reached
# through the error manager singleton in Python.
err_mgr = ErrorMgrSingleton.getInstance()

DelCpSlice( GetNumCpSlices() )

assert err_mgr.GetNumTotalErrors() > 0, "DelCpSlice accepted an index past the end"

# That error was raised deliberately, so take it back off the queue.
while err_mgr.GetNumTotalErrors() > 0 :
    err = err_mgr.PopLastError()

See also: AddCpSlice, DeleteAllCpSlices :param [in]: slice_index int Cp slice index

openvsp.DeleteAllCpSlices()[source]

Delete all Cp slices from the VSPAERO Cp Slicer

AddCpSlice( X_DIR, 0.5 )
AddCpSlice( Y_DIR, 0.25 )

DeleteAllCpSlices()

assert GetNumCpSlices() == 0, "DeleteAllCpSlices left slices behind"

# Clearing an empty slicer is not an error.
err_mgr = ErrorMgrSingleton.getInstance()

DeleteAllCpSlices()

assert err_mgr.GetNumTotalErrors() == 0, "DeleteAllCpSlices complained about an empty slicer"

See also: AddCpSlice, DelCpSlice, GetNumCpSlices

openvsp.DeleteVSPAEROControlSurfaceGroup(CSGroupIndex)[source]

Delete one VSPAERO control surface group, by index.

wid = AddGeom( "WING" )

Update()

CreateVSPAEROControlSurfaceGroup()

DeleteVSPAEROControlSurfaceGroup( 0 )

assert GetNumControlSurfaceGroups() == 0, "DeleteVSPAEROControlSurfaceGroup did not delete the group"

See also: CreateVSPAEROControlSurfaceGroup :param [in]: CSGroupIndex int Index of the control surface group to delete

openvsp.CreateVSPAEROControlSurfaceGroup()[source]

Add a VSPAERO control surface group.

wid = AddGeom( "WING" )

Update()

group_index = CreateVSPAEROControlSurfaceGroup()

assert GetNumControlSurfaceGroups() == 1, "CreateVSPAEROControlSurfaceGroup did not add the group"

See also: DeleteVSPAEROControlSurfaceGroup, GetNumControlSurfaceGroups :rtype: int :return: int Index of the new control surface group

openvsp.AddAllToVSPAEROControlSurfaceGroup(CSGroupIndex)[source]

Add all available control surfaces to the control surface group at the specified index

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

# The group starts empty and the wing offers one control surface, mirrored
# by the wing's own symmetry.
assert GetNumControlSurfaceGroups() >= 1, "CreateVSPAEROControlSurfaceGroup did not add a group"

num_avail = len( GetAvailableCSNameVec( group_index ) )

assert num_avail >= 1, "no control surfaces are available to add"
assert len( GetActiveCSNameVec( group_index ) ) == 0, "a new control surface group is not empty"

AddAllToVSPAEROControlSurfaceGroup( group_index )

# Everything that was available is now active, and nothing is left over.
assert len( GetActiveCSNameVec( group_index ) ) == num_avail, "AddAllToVSPAEROControlSurfaceGroup did not add them all"
assert len( GetAvailableCSNameVec( group_index ) ) == 0, "control surfaces are still available after adding them all"
Parameters:

[in] – CSGroupIndex int Index of the control surface group

openvsp.RemoveAllFromVSPAEROControlSurfaceGroup(CSGroupIndex)[source]

Remove all used control surfaces from the control surface group at the specified index

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

AddAllToVSPAEROControlSurfaceGroup( group_index )

num_active = len( GetActiveCSNameVec( group_index ) )

assert num_active >= 1, "nothing was added to the group to remove"

RemoveAllFromVSPAEROControlSurfaceGroup( group_index ) # Empty control surface group

# Everything that was active goes back to being available.
assert len( GetActiveCSNameVec( group_index ) ) == 0, "RemoveAllFromVSPAEROControlSurfaceGroup left surfaces in the group"
assert len( GetAvailableCSNameVec( group_index ) ) == num_active, "the removed surfaces did not become available again"
Parameters:

[in] – CSGroupIndex int Index of the control surface group

openvsp.GetActiveCSNameVec(CSGroupIndex)[source]

Get the names of each active (used) control surface in the control surface group at the specified index

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

AddAllToVSPAEROControlSurfaceGroup( group_index )

cs_name_vec = GetActiveCSNameVec( group_index )
assert len( cs_name_vec ) > 0, "GetActiveCSNameVec returned nothing"

print( "Active CS in Group Index #", False )
print( group_index )

for i in range(int( len(cs_name_vec) )):

    print( cs_name_vec[i] )
Parameters:

[in] – CSGroupIndex int Index of the control surface group

Return type:

std::vector< std::string,std::allocator< std::string > >

Returns:

vector <string> Array of active control surface names

openvsp.GetCompleteCSNameVec()[source]

Get the names of all control surfaces. Some may be active (used) while others may be available.

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

cs_name_vec = GetCompleteCSNameVec()
assert len( cs_name_vec ) > 0, "GetCompleteCSNameVec returned nothing"

print( "All Control Surfaces: ", False )

for i in range(int( len(cs_name_vec) )):

    print( cs_name_vec[i] )
Return type:

std::vector< std::string,std::allocator< std::string > >

Returns:

vector <string> Array of all control surface names

openvsp.GetAvailableCSNameVec(CSGroupIndex)[source]

Get the names of each available (not used) control surface in the control surface group at the specified index

wid = AddGeom( "WING", "" ) # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL ) # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

cs_name_vec = GetAvailableCSNameVec( group_index )
assert len( cs_name_vec ) > 0, "GetAvailableCSNameVec returned nothing"

cs_ind_vec = [1]

AddSelectedToCSGroup( cs_ind_vec, group_index ) # Add the first available control surface to the group

# One surface moved from available to active.
active_vec = GetActiveCSNameVec( group_index )

assert len( active_vec ) == 1, "AddSelectedToCSGroup did not add the surface that was named"
assert active_vec[0] == cs_name_vec[0], "AddSelectedToCSGroup added the wrong surface"
assert len( GetAvailableCSNameVec( group_index ) ) == len( cs_name_vec ) - 1, "the added surface is still available"
Parameters:

[in] – CSGroupIndex int Index of the control surface group

Return type:

std::vector< std::string,std::allocator< std::string > >

Returns:

vector <string> Array of active control surface names

openvsp.SetVSPAEROControlGroupName(name, CSGroupIndex)[source]

Set the name for the control surface group at the specified index

wid = AddGeom( "WING", "" ) # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL ) # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

SetVSPAEROControlGroupName( "Example_CS_Group", group_index )

assert GetVSPAEROControlGroupName( group_index ) == "Example_CS_Group", "SetVSPAEROControlGroupName did not take"

print( "CS Group name: ", False )

print( GetVSPAEROControlGroupName( group_index ) )
Parameters:
  • [in] – name string Name to set for the control surface group

  • [in] – CSGroupIndex int Index of the control surface group

openvsp.GetVSPAEROControlGroupName(CSGroupIndex)[source]

Get the name of the control surface group at the specified index

wid = AddGeom( "WING", "" ) # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL ) # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

SetVSPAEROControlGroupName( "Example_CS_Group", group_index )

assert GetVSPAEROControlGroupName( group_index ) == "Example_CS_Group", "SetVSPAEROControlGroupName did not take"

print( "CS Group name: ", False )

print( GetVSPAEROControlGroupName( group_index ) )
Parameters:

[in] – CSGroupIndex int Index of the control surface group

openvsp.AddSelectedToCSGroup(selected, CSGroupIndex)[source]

Add each control surfaces in the array of control surface indexes to the control surface group at the specified index.

Warning: The indexes in input “selected” must be matched with available control surfaces identified by GetAvailableCSNameVec. The “selected” input uses one- based indexing to associate available control surfaces.

wid = AddGeom( "WING", "" ) # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL ) # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

cs_name_vec = GetAvailableCSNameVec( group_index )

cs_ind_vec = [0] * len(cs_name_vec)

for i in range(int( len(cs_name_vec) )):

    cs_ind_vec[i] = i + 1

AddSelectedToCSGroup( cs_ind_vec, group_index ) # Add all available control surfaces to the group

# Everything that was named moved from available to active.
assert len( GetActiveCSNameVec( group_index ) ) == len( cs_name_vec ), "AddSelectedToCSGroup did not add them all"
assert len( GetAvailableCSNameVec( group_index ) ) == 0, "control surfaces are still available after adding them all"

See also: GetAvailableCSNameVec :param [in]: selected vector <int> Array of control surface indexes to add to the group. Note, the integer values are one based. :param [in]: CSGroupIndex int Index of the control surface group

openvsp.RemoveSelectedFromCSGroup(selected, CSGroupIndex)[source]

Remove each control surfaces in the array of control surface indexes from the control surface group at the specified index.

Warning: The indexes in input “selected” must be matched with active control surfaces identified by GetActiveCSNameVec. The “selected” input uses one-based indexing to associate available control surfaces.

wid = AddGeom( "WING", "" ) # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL ) # Add Control Surface Sub-Surface

group_index = CreateVSPAEROControlSurfaceGroup() # Empty control surface group

cs_name_vec = GetAvailableCSNameVec( group_index )

cs_ind_vec = [0] * len(cs_name_vec)

for i in range(int( len(cs_name_vec) )):

    cs_ind_vec[i] = i + 1

AddSelectedToCSGroup( cs_ind_vec, group_index ) # Add the available control surfaces to the group

remove_cs_ind_vec = [1]

num_active = len( GetActiveCSNameVec( group_index ) )

assert num_active == len( cs_name_vec ), "not everything was added to the group"

RemoveSelectedFromCSGroup( remove_cs_ind_vec, group_index ) # Remove the first control surface

# One surface moved back from active to available.
assert len( GetActiveCSNameVec( group_index ) ) == num_active - 1, "RemoveSelectedFromCSGroup did not remove a surface"
assert len( GetAvailableCSNameVec( group_index ) ) == 1, "the removed surface did not become available again"

See also: GetActiveCSNameVec :param [in]: selected vector <int> Array of control surface indexes to remove from the group. Note, the integer values are one based. :param [in]: CSGroupIndex int Index of the control surface group

openvsp.GetNumControlSurfaceGroups()[source]

Get the total number of control surface groups

wid = AddGeom( "WING", "" )                             # Add Wing

aileron_id = AddSubSurf( wid, SS_CONTROL )                      # Add Control Surface Sub-Surface

#==== Add Horizontal tail and set some parameters =====//
horiz_id = AddGeom( "WING", "" )

SetGeomName( horiz_id, "Vert" )

SetParmValUpdate( horiz_id, "TotalArea", "WingGeom", 10.0 )
SetParmValUpdate( horiz_id, "X_Rel_Location", "XForm", 8.5 )

elevator_id = AddSubSurf( horiz_id, SS_CONTROL )                      # Add Control Surface Sub-Surface

AutoGroupVSPAEROControlSurfaces()

num_group = GetNumControlSurfaceGroups()

if  num_group != 2 :
    print( "Error: GetNumControlSurfaceGroups" )
    assert False, "Error: GetNumControlSurfaceGroups"
Return type:

int

Returns:

int Number of control surface groups

openvsp.FindControlSurfaceGroup(group_index)[source]

Get the ID of a VSPAERO control surface group, so that its Parms can be reached the way any other container’s are. A group carries an ActiveFlag and a DeflectionAngle, both in Parm group “ControlSurfaceGroup”. Everything else about these groups is addressed by index; this is what lets a script set a deflection without knowing the index a group happens to hold.

#==== A wing with a control surface on it ====#
wid = AddGeom( "WING", "" )
subsurf_id = AddSubSurf( wid, SS_CONTROL, 0 )

Update()

#==== Group it, the way the VSPAERO screen does ====#
AutoGroupVSPAEROControlSurfaces()

Update()

assert GetNumControlSurfaceGroups() > 0, "no control surface group was made"

group_id = FindControlSurfaceGroup( 0 )

assert len( group_id ) > 0, "FindControlSurfaceGroup found nothing"

#==== And its deflection is a Parm like any other ====#
SetParmVal( FindParm( group_id, "DeflectionAngle", "ControlSurfaceGroup" ), 7.0 )

Update()

deflected = GetParmVal( group_id, "DeflectionAngle", "ControlSurfaceGroup" )

assert abs( deflected - 7.0 ) < 1e-6, "the group did not take the deflection it was given"

See also: GetNumControlSurfaceGroups, AutoGroupVSPAEROControlSurfaces :param [in]: group_index int Control surface group index :rtype: string :return: string Control surface group ID