GenSAA Tips and Tricks

by Susan Valett (XTE/SWAS HUD Developer)

This document discusses some of the problems encountered during the development of the SWAS and XTE HUDs and the solutions that were developed to resolved them. While the vast majority of solutions were implemented in the two HUDs, future GenSAA developers should keep in mind as they review the SWAS and XTE HUDs that not all solutions (most notably the expert system efficiency guidelines) were followed through on these first HUDs. This is a case were you should do as I say and not as I do.


PROBLEM:
There was a need to display 1 of 3 (user selected) different time sources. GenSAA allows only one data source to be connected to any particular widget.

SOLUTION:

NOTE: Behaviors are created using the Graphics Objects Behaviors editor under the Components menu.


PROBLEM:
The users didn't want to see information on invalid stars. One mnemonic identified which stars were valid and another set of mnemonics contained the star information. GenSAA allows only one data source per widget.

SOLUTION:
This technique is similar to the previous one except I needed to determine in clips which stars were valid/invalid and put that information in inferred variables. I then used the inferred variable to hide or show the images covering the star information on the display.
NOTE: In the ST and DSS FOV display when the HUD received data that was bad for some reason, I set the X and Y values of the data to -99 so they would be plotted off the FOV.


PROBLEM:
I needed to show three time sources, but GenSAA only allows one time source per mnemonic.

SOLUTION:
I was lucky with this one because I was dealing with three (or more) mnemonics. This occurred when I was dealing with IRU X, Y, and Z mnemonics, so I needed three mnemonics to show all the possible time source combinations.

I picked mnemonics for each time format (ex. I selected the X IRU mnemonics for spacecraft time, the Y IRU mnemonic for ground receipt time, and the Z IRU mnemonic for the local GMT time.) In the Data Manager I requested the time formats along with the raw or converted data for these mnemonics. For instance for the X IRU mnemonic I requested Raw data under CVT Component and Spacecraft under Time Tag (using the Data Details panels). I specified what type of information I wanted from the mnemonic in the following way:
(X IRU mnemonic MISSION value) for the data and
(X IRU mnemonic spacecraft-GMT data) for the spacecraft time
(local-GMT would specify local time and ground-GMT would specify ground receipt time)
NOTE: time widget automatically displays the time data from widgets.


PROBLEM:
After attempting to verify a GenSAA application and receiving errors, I didn't know which widgets were causing problems because they were identified by a widget ID.

SOLUTION:
When you do a verify and you get an error and you don't know what widget it pertains to:


PROBLEM:
GenSAA will not verify widgets that are grouped together.

SOLUTION:
Ungroup the widgets.


PROBLEM:
The HUD needed patterns displayed on top of some widgets if certain conditions existed (ex. power off). The pie editor supplied with GenSAA was difficult to use.

SOLUTION:
On a HP I used the vueicon editor to create the images I needed to use, and saved them as .bit files. To get these images into the image palette I have to change the .ges file to point to the directory that contained these images. (line 5 of the .ges file, the third directory path specified.) Once I did this I needed to copy over the GenSAA.xbm to that image directory, because GenSAA wants all the images in the one directory. If the new images don't appear in the image palette in the WorkBench you will need to do a Rescan under Options.

NOTE: GenSAA 3.02 Runtime will crash if bitmaps used in the GenSAA application are missing from the image directory.


PROBLEM:
The users wanted some indication if the data displayed had exceeded specified TPOCC limits.

SOLUTION:
This problem was solved two different ways:
1) if you are displaying mission data of a CVT type then - change line 235 of the rungrt script to include /%N after etc. The line should now look like: else XUSERFILESEARCHPATH = $ROOT_GEN/etc/%N:$HOME...
2) if you are displaying inferred or non_CVT type data then - I added behavior rules to the widgets that would change the color and size of the widget borders if limits


PROBLEM:
When using TPOCC limit checks you are stuck with the red, yellow, and green values that are specified in the quality.ad file. These colors may clash with the colors chosen for your GenSAA application.

SOLUTION:
I didn't resolve this problem in the XTE HUD. The only way I thought I could resolve it was to select colors that wouldn't clash with TPOCC warning colors. Colors like gray and slate gray would probably be more appealing.


PROBLEM:
You need to create a series of widgets that look exactly alike and you want to do it as efficiently as possible.

SOLUTION:


PROBLEM:
You need to resize or relocate a widget and using the mouse isn't giving you fine enough control.

SOLUTION: Use the Geometry selection under the Utilities Menu on the UIB. You can type in the exact x and y position, height, and width for any widget.


PROBLEM:
You have a group of widgets that you'd like the user to know belong together (e.g.. they are all Reaction Wheel parameters)

SOLUTION:


PROBLEM:
You have a XY graph widget that will need to erase points and draw new ones. (As opposed to simply adding new points to the old ones.)

SOLUTION:
For every coordinate pair you want to plot you will need a rule like the one below. The (AssertFact "DSSY Control I") will cause the previous values that occupied DSSY and DSSX to be erased.

(defrule DSSplotControl "" ?factY <- (Beta Inferred ?y) => (AssertFact "DSSY Control 1") (AssertFact "DSSX Inferred" ?x) (AssertFact "DSSY Inferred" ?y) (retract ?factY) (retract ?factX)) Then in the UIB you will need to bring up the XY-Plot Attributes Panel under the Components Menu. Fill out Plot Panel for all the pairs for the XY graph widget.

NOTE: If you are having difficulties getting the minimum and maximum values for the x and y axis to display properly, use the Graphic Object Resources panel and set the xScaleHi, xScaleLo, yScaleHi, and yScaleLo resources to the values and you want.


PROBLEM:
You want to keep your expert system as efficient as possible.

SOLUTION:

  1. Think about your use of bind, assert and AssertFact. The bind command will bind a value to a variable. It's scope is limited to the rule in which it was invoked. (Once you leave the rule the value is meaningless). Binds are sufficient for internal computations that are only needed inside one rule. The assert command will assign a value to a variable and add that fact to the fact list. A fact asserted with assert is available to all rules in the rule base. Asserts are perfect for internal computations that are needed in more than one rule, but are not needed for display. The AssertFact command does everything assert does but also sends the fact through the socket to the User Interface. The Data Manager needs to have all variables asserted with AssertFact listed in the Inferred (or UserDefined) data list. The scope of AssertFact is the entire GenSAA application. To create the most efficient expert system you will need to decide which command has the most appropriate scope for each assignment you'll make.
  2. Think about the structure of your rules. It is more efficient to have many short rules with few conditions than to have one long rule with many conditions and nested "if"'s in the actions. Smaller rules also have the additional benefit of being easier to maintain and reuse.
  3. Every condition in a rule must be evaluated to true before CLIPS will put that rule on the agenda. As soon as CLIPS encounters a condition that is false it will stop its evaluation of that rule's conditions and go on to the next rule. Therefore, it is more efficient to place conditions that are more likely to fail at the top of the list. (I tried to place user parameters at the top and mission variables at the bottom of the list.)


PROBLEM:
You need to get valid test data into your GenSAA runtime application.

SOLUTION:
Use a TSTOL script file keeping the following in mind:

  1. 0x800 Valid converted values (hex)
  2. 0X0 Valid converted value within limits (hex)
  3. 0xl Valid converted value exceeded high TPOCC warning (hex)
  4. 0x2 Valid converted value exceeded low TPOCC warning (hex)
  5. 0x3 Valid converted value exceeded high TPOCC error (hex)
  6. 0x4 Valid converted value exceeded low TPOCC error (hex)


PROBLEM:
You need to get the difference between two CVT times.

SOLUTION:
You need to first convert the string to numerical values:

(defrule Get_TimeComp_Source "This rule will take string spacecraft time and break it into day of year, hour, minute, seconds, and tenths of seconds numerical Peter Hughes 01.12.95" ?fl <- (AEAIRUAXD#XTE_DECOM spacecraft-GMT ?x) => (assert (DDD = (str-explode (sub-string 3 5 (str-cat ?x))))) (assert (HH = (str-explode (sub-string 7 8 (str-cat ?x))))) (assert (MM = (str-explode (sub-string 9 10 (str-cat ?x))))) (assert (SS = (str-explode (sub-string 11 12 (str-cat ?x))))) (assert (m = (str-explode (sub-string 13 13 (str-cat ?x))))) (retract ?f 1))

then you'll need to convert the numerical values into seconds.

(defrule ConvertTimeToSeconds "This rule will determine the number of seconds in the year given tenths of seconds, seconds, minutes, hours, and day in the year. Peter Hughes 0 1. 12.95 ?fss <- (SS ?ss) ?fmm <- (MM ?mm) ?fHH <- (HH ?hh) ?fDD <- (DDD ?ddd) ?fm <- (m ?M) => (assert (Curr_Time Inferred ;; add the current number of seconds = (+ ?ss ;;to the total seconds in the minutes (* 60 ?mm) ;;and the total seconds in the hours (* 3600 ?hh) ;;and the total seconds in the days (* 86400 ?ddd) ;;and the fraction of second (/ ?m I 0)))) (retract ?fSS ?fMM ?fHH ?fDD ?fm))

--or-- You can use this function in place of the previous two rules.

TIMETAG-TO-SECS - Function to convert time in timetag format to seconds format. Timetag format is received from GenSAA TimeTag facts - the format is YYDDD.HHMMSST. Seconds format is the integer number of seconds since January 1, 1970.

(deffunction timetag-to-secs (?t) ; arg format: YYDDD.HHMMSST ; Ed Luczak/CSC February 1995 (+ (* 31536000 (- (div ?t 1000) 70)) ;years since1970 (* 86400 (- (integer (mod ?t 1000)) 1)) ; days this year (* 86400 (div (- (div ?t 1000) 69) 4)) ; leap days (* 3600 (integer (mod (* ?t 100) 100))) ; hours (* 60 (integer (mod (* ?t 10000) 100))) ; minutes (integer (mod (* ?t 1000000) 100)) ; seconds ))

Sample call:

(timetag-to-secs ?timetag)

This deffunction can be called from the RHS of a rule that is triggered by the receipt of a GenSAA TimeTag fact. (This rule was tested with CLIPS 6.0)


PROBLEM:
There are two versions of the system variable table one with one decommutation name and one with another. (Ex, this problem occurred in the Flight Dynamics Division. There existed two copies of the system variable table, identical expect for the decommutation process names. One existed for the mission specific TPOCC (i.e., mnemonic#SWAS_DECOM) in the MOC and one for generic TPOCC (i.e., mnemonic#TPOCC_DECOM) in the FDF.)

SOLUTION:

  1. edit the clp file and make a global change from one decom process to the another.
  2. edit the mis file and make a global change from one decom process to the another.
  3. bring up the WorkBench and under the UIB use the String Substitution command to replace the data sources decommutation name of all the widgets receiving mission data from the old mnemonic#decom_name to the new mnemonic#decom_name. NOTE: this step must be performed last.


PROBLEM:
You need to set default values for the UserDefined variables so the expert system isn't waiting for a user response before processing all the data.

SOLUTION:
I created an Assign_Defaults rule that triggered off the initial-fact to assert all the default values. This rule looked something like this:

(defrule Assign_Defaults "This rule will assign default values to some of the user parameters so no action is needed by the user to allow the HUD to start running. Susan Ray Valett 10.15.94" ?x <- (initial-fact) => (retract ?x) (AssertFact "Parm_Debug UserDefined No.Debug") (AssertFact "Parm_Rot_Seq UserDefined 06=3-2-1") (AssertFact "Parm_att_opt UserDefined Commanded") ..etc.) NOTE: This rule can be used for other things that need to be done at start up; like opening files, and assigning initial values to inferred values.