Skip to content

My First HSF Project Add a Constraint

Eric Mehiel edited this page Apr 18, 2024 · 25 revisions

A simple system with one Subsystem and now a constraint

Now that we have gone through the effort to create the necessary set up files for a simple system using HSF (the scenario, target, and model) files we are in a position to put a requirement on the system model in the form of a constraint.

The HSF modeling paradigm

There are obviously as many ways to model and simulate a system as there are people that model and simulate systems. Early on the Horizon team developed the HSF Modeling Paradigm. We don't claim our modeling paradigm is the only or the best way to model dynamics systems, but we think it works pretty well. The HSF Modeling Paradigm (HSF-MP) is based on dynamics systems theory. The fundamental idea is that the model of the system developed by the user is capable of describing how the states of the system change over some period of time given some initial set of state or conditions. The scheduler then supplies initial conditions to the model and asks, "Hey model, can you perform this task given this set of initial conditions? If you can, let me know and tell me everything about your states as you complete the task." Once the model figures this out, the information is passed back to the scheduler and stored in a new potential schedule. Fundamental to the HSF-MP is the idea that the model is valid regardless of the initial condition. The model has to exist outside of any one schedule and is a description of how things change.

The Horizon team also made decisions along the way to help with the basic tasks of building a model. Again, these decisions were based on our world view of how modelling should work. The guiding principles for the HSF-MP are, Modularity, Flexibility, and Utility. We will get into all of these principles as you go through the tutorials, but let's start with Modularity now.

Modularity in the HSF-MP

As we have discussed, the scheduling algorithm and the model of the simulated system are separate and only communicate through a well defined interface (the CanPerform() function). To this end, the scheduler and model have no dep knowledge of each other and are interchangeable. In fact, one project we took on was to develop a Evolutionary Algorithm as the scheduling component.

Another outcome of adopting a modularity approach, was to develop strongly typed subsystem object within the framework, and to carry that approach over to model development. One important result of this decision is to limit "Model Creep". Model Creep is the idea that one subsystem model starts to consume other models that are distinct either physically (on the built system) or from a systems engineering perspective.

This concept of modularity requires the user to define clear subsystem model boundaries and define rigorous and complete subsystem interfaces. Both of these ideas are consistent with good systems engineering practices. The HSF-MP supports this approach through Constraints and Dependencies. In this tutorial, we will show how Constraints are used within HSF.

Constraints Defined

In the HSF-MP, a Constraint is defined as:

A restriction placed on values within the state, and the list of subsystems that must execute prior to the Boolean evaluation of satisfaction of the constraint. Also the main functional system simulation block, in that in order to check if a task can be completed, the scheduler checks that each constraint is satisfied, indirectly checking the subsystems.

This is a complicated way of saying, constraints are limitations to the value of states that the system is allowed to take on. In a lot of ways, a constraint is really synonymous with a systems engineering requirement. Combining the idea of a system constraint with the role of the system model, we have another fundamental view of the HSF-MP.

The system model is a model of what the system can do (from a physics point of view) and a constraint is a limitation on what the system should do (from a requirements point of view).

So, let's get down to it and add a constraint to the simple model we developed in the previous tutorial on setting up your first simulation scenario. In this case, we are going to constrain the angle from the Nadir vector to the target vector. This angle is often referred to as the look angle. This is a good example because physically, the spacecraft can't see the target if it is over Earth's Horizon (the physical part) but we as the builders of the spacecraft may want to limit the look angle for other design considerations (the requirements part). First we need to add a state to the model and calculate the look angle.

Add a Constraint to the simulation scenario

So, let's get to it, here are the steps:

Add the look angle as a state in the xml model

First we need to add a Look_Angle(rad) state to the system model. Rename the system model file to myFirstHSFSystem_look.xml, and add the <STATE> tag for the Look_Angle(rad) as shown in the modified code below.

<SUBSYSTEM
    subsystemName = "CameraLook"
    type="scripted"
    src="..\..\..\..\samples\myFirstHSFProject\CameraLook.py"
    className="CameraLook">
    <STATE type="Matrix" name="POINTVEC_KEY" key="ECI_Pointing_Vector(XYZ)" value="[0.0; 0.0; 0.0]"/>
    <STATE type="Double" name="LookAngle" key="Look_Angle(rad)" value="0.0"/>
</SUBSYSTEM>

Notice we updated the name of the subsystem, subsystemName = "CameraLook", along with the source file for the python script src, and the className. An important update is the new <STATE> tag. Whenever an state with initial conditions is added to the model file, a new state is being defined. The new state is of type Double has a key Look_Angle(rad) and name LookAngle since the look angle is calculated and stored in radians, and an initial value of 0.0.

Update the CameraLook.py script

Go ahead and rename the code CameraLook.py just to keep things separate. In this case, we can calculate the look angle by taking the inverse cosine of the dot product between the spacecraft pointing vector and the negative of the spacecraft position vector (normalized of course).

  • Change the name of the python class

Be sure to update the CanExtend() and DependencyCollector() methods as well. We will deal with dependencies in the next tutorial.

  • Import the Math library (we need the Acos() function)
from System import Func, Delegate, Math`
  • Calculate the look angle and add the value to a state profile in the CanPerform() method.
scPos_norm = -scPositionECI / Matrix[System.Double].Norm(-scPositionECI)
pv_norm = pointingVectorECI / Matrix[System.Double].Norm(pointingVectorECI)
lookAngle = Math.Acos(Matrix[System.Double].Dot(scPos_norm, pv_norm))
event.State.AddValue(self.LookAngle, ts, lookAngle)

Add a constraint to the system model

Constraints are child tags of the Asset tag. Constraints are on the same level as Subsystems since they can be applied to any Subsystem. Add a as follows, under the CameraLook subsystem in the myFirstHSFSystemLook.xml model file.

<CONSTRAINT
    value="0.5"
    subsystemName = "CameraLook"
    type="FAIL_IF_HIGHER"
    name="look_angle_constraint">
    <STATEVAR
        type = "Double"
        key="Look_Angle(rad)"/>
</CONSTRAINT>

The tag requires the following attributes and tags:

  • value - the value at which the constraint is surpassed. In this example, 0.5 radians.
  • subsystemName - the name of the subsystem to apply the constraint. In this example, CameraLook
  • type - the type of constraint, this is an enumeration (more later), but in this example, we don't want the look angle to be greater than .5 radians, so we set the type to FAIL_IF_HIGHER
  • name - give the constraint a name. In this example, we use look_angle_constraint
  • <STATEVAR> - this is a child tag of the <CONSTRAINT> tag indicating the type and key of the state variable being constrained. In this example, we are constraining the state Look_Angle(rad) which is of type Double. Notice, the tag points to the look angle state we defined in our new camera model.

Now run Horizon from the Command Prompt by typing: Horizon -s myFirstHSFScenario.xml -t myFirstHSFTargetDeck.xml -m myFirstHSFSystem_look.xml -subpath samples\myFirstHSFProject This command will run Horizon with the scenario (-s), target deck (-t), and model (-m) files we created. You should notice a message showing up in the Command Prompt that a constraint has failed. This means the camera can physically look at a target, but the constraint (or requirement) of a maximum look angle of 0.5 radians is being enforced and those tasks that violate the constraint will not be added to a potential schedule.

Now, open up the final schedule. You will notice that the proposed schedule is different now that the constraint has been added. If you open the look angle data file, you will see that the look angle never exceeds 0.5 radians. So, we are now left with a physically valid schedule (based on the geometry of a spacecraft in orbit looking at Earth) and a verified requirement that the look angle shall not exceed 0.5 radians. Pretty cool!