private IAgCrdnCalcScalar CreateScalar(IAgStkObject stkObject, string name, IAgCrdnAngle angle) { IAgCrdnCalcScalarFactory factory = stkObject.Vgt.CalcScalars.Factory; // Check if component exists. CheckExistingVgtComponent(stkObject.Vgt.CalcScalars, name); IAgCrdnCalcScalarAngle scalar = factory.CreateCalcScalarAngle(name, "") as IAgCrdnCalcScalarAngle; scalar.InputAngle = angle; return(scalar as IAgCrdnCalcScalar); }
private void CreateAttitudeButton_Click(object sender, EventArgs e) { try { progressBar.Visible = true; UpdateProgress(0); // Check inputs CheckUserInputs(); // Get inputs string alignedVectorName = alignedVectorComboBox.SelectedItem.ToString(); string constrainedVectorName = constrainedVectorComboBox.SelectedItem.ToString(); double angleLimit = Convert.ToDouble(angleLimitTextBox.Text); string alignedBodyAxis = GetBodyAxis(VectorType.eAligned); string constrainedBodyAxis = GetBodyAxis(VectorType.eConstrained); UserInputs inputs = new UserInputs { AlignedVectorName = alignedVectorName, AlignedBodyAxis = alignedBodyAxis, ConstrainedVectorName = constrainedVectorName, ConstrainedBodyAxis = constrainedBodyAxis, AngleLimit = angleLimit }; UpdateProgress(25); // Duplicate the satellite to create a reference sat. All AWB components are created on this reference sat to avoid circular logic. m_referenceSatellite = DuplicateObject(m_selectedObject); UpdateProgress(50); // Create AWB components from user inputs IAgCrdnVector scheduledVector = CreateAlignedScheduledVector(inputs); UpdateProgress(75); // Set final attitude profile IAgCrdnVector selectedConstrainedVector = GetVectorFromObject((IAgStkObject)m_selectedObject, constrainedVectorName); SetAlignedConstrainedAttitude(m_selectedObject, scheduledVector, alignedBodyAxis, selectedConstrainedVector, constrainedBodyAxis); if (showGraphicsCheckBox.Checked == true) { // Get AWB components to display IAgCrdnAxes selectedBodyAxes = m_selectedObject.Vgt.Axes["Body"]; IAgCrdnVector selectedConstrainedBodyVector = GetVectorFromAxes((IAgStkObject)m_selectedObject, selectedBodyAxes, constrainedBodyAxis); IAgCrdnVector selectedAlignedVector = GetVectorFromObject((IAgStkObject)m_selectedObject, alignedVectorName); IAgCrdnAngle displayAngle = CreateAngle((IAgStkObject)m_selectedObject, $"Off_{constrainedVectorName}", selectedConstrainedVector, selectedConstrainedBodyVector); // Display in 3D Graphics window. ShowAttitudeGraphics(selectedAlignedVector, selectedConstrainedVector, selectedBodyAxes, displayAngle); // Add negative body axis if necessary if (constrainedBodyAxis.Contains("-")) { IAgCrdnVector bodyVector = m_selectedObject.Vgt.Vectors[$"Body.{constrainedBodyAxis}"]; DisplayElement(AgEGeometricElemType.eVectorElem, (IAgCrdn)bodyVector, Color.RoyalBlue); } } UpdateProgress(100); } catch (Exception exception) { MessageBox.Show(exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } progressBar.Visible = false; }
private void ShowAttitudeGraphics(IAgCrdnVector alignedVector, IAgCrdnVector constrainedVector, IAgCrdnAxes bodyAxes, IAgCrdnAngle offAxisAngle) { // Show aligned vector and constrained vector DisplayElement(AgEGeometricElemType.eVectorElem, (IAgCrdn)alignedVector, Color.Yellow); DisplayElement(AgEGeometricElemType.eVectorElem, (IAgCrdn)constrainedVector, Color.LawnGreen); // Show body axes DisplayElement(AgEGeometricElemType.eAxesElem, (IAgCrdn)bodyAxes, Color.RoyalBlue); // Display angle from constraint vector to Body axis on original satellite to show limited atttiude. DisplayElement(AgEGeometricElemType.eAngleElem, (IAgCrdn)offAxisAngle, Color.White); }
private IAgCrdnVector CreateAlignedScheduledVector(UserInputs inputs) { // Unpack inputs string alignedVectorName = inputs.AlignedVectorName; string alignedBodyAxis = inputs.AlignedBodyAxis; string constrainedVectorName = inputs.ConstrainedVectorName; string constrainedBodyAxis = inputs.ConstrainedBodyAxis; double angleLimit = inputs.AngleLimit; // Get vectors from user input IAgCrdnVector duplicateAlignedVector = GetVectorFromObject((IAgStkObject)m_referenceSatellite, alignedVectorName); IAgCrdnVector duplicateConstrainedVector = GetVectorFromObject((IAgStkObject)m_referenceSatellite, constrainedVectorName); // Make sure vectors are valid CheckInputVector(duplicateAlignedVector); CheckInputVector(duplicateConstrainedVector); // Create Body vector string for naming string constrainedBodyVectorName = $"Body.{constrainedBodyAxis}"; // Get body vector IAgCrdnAxes duplicateBodyAxes = m_referenceSatellite.Vgt.Axes["Body"]; IAgCrdnVector duplicateConstrainedBodyVector = GetVectorFromAxes((IAgStkObject)m_referenceSatellite, duplicateBodyAxes, constrainedBodyAxis); // Set duplicate satellite's attitude to Aligned & Constrained with user input vectors. This is the unconstrained attitude that our // final satellite's attitude is based on. SetAlignedConstrainedAttitude(m_referenceSatellite, duplicateAlignedVector, alignedBodyAxis, duplicateConstrainedVector, constrainedBodyAxis); // Create angle from constraint vector to specified body axis. Set condition to find when this angle exceeds user limit IAgCrdnAngle constraintToBodyAngle = CreateAngle((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}To{constrainedBodyVectorName}", duplicateConstrainedVector, duplicateConstrainedBodyVector); IAgCrdnCalcScalar constraintToBodyScalar = CreateScalar((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}To{constrainedBodyVectorName}Value", constraintToBodyAngle); IAgCrdnCondition constraintToBodyCondition = CreateCondition((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}To{constrainedBodyVectorName}Condition", constraintToBodyScalar, AgECrdnConditionThresholdOption.eCrdnConditionThresholdOptionBelowMax, angleLimit); // Create angle from constraint vector to aligned vector and set condition from 0 to 90 deg. This is because the attitude profile is flipped // if the angle is between 90 and 180 deg. IAgCrdnAngle constraintToAlignedAngle = CreateAngle((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}To{alignedVectorName}", duplicateConstrainedVector, duplicateAlignedVector); IAgCrdnCalcScalar constraintToAlignedScalar = CreateScalar((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}To{alignedVectorName}Value", constraintToAlignedAngle); IAgCrdnCondition constraintToAlignedCondition = CreateCondition((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}To{alignedVectorName}Condition", constraintToAlignedScalar, AgECrdnConditionThresholdOption.eCrdnConditionThresholdOptionInsideMinMax, 0, 90); // Create axes aligned with the constraint vector and constrained with the aligned vector. IAgCrdnAxes alignedConstrainedAxes = CreateAxes((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}Axes", duplicateConstrainedVector, constrainedBodyAxis, duplicateAlignedVector, alignedBodyAxis); // Rotate the new axes by both the positive and negative Angle Offset value. IAgCrdnAxes positiveRotatedAxes = CreateAxes((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}Axes_RotatedPositive", alignedConstrainedAxes, alignedBodyAxis, constrainedBodyAxis, angleLimit); IAgCrdnAxes negativeRotatedAxes = CreateAxes((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}Axes_RotatedNegative", alignedConstrainedAxes, alignedBodyAxis, constrainedBodyAxis, -angleLimit); // Create scheduled axes IAgCrdnAxes scheduledAxes; double[] alignedAxisVector = GetCartesianArray(alignedBodyAxis); double[] constrainedAxisVector = GetCartesianArray(constrainedBodyAxis); // If the cross product vector of the aligned body axis and constrained body axis is positive, the axes need to be // positively rotated when the angle between the aligned vector and constrained vector is between 0 deg and 90 deg. // If the angle is between 90 and 180, the axes need to be negatively rotated. This is flipped if the cross product // is negative. if (NormalVectorIsPositive(alignedAxisVector, constrainedAxisVector)) { scheduledAxes = CreateAxes((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}Axes_Scheduled", constraintToAlignedCondition, positiveRotatedAxes, negativeRotatedAxes); } else { scheduledAxes = CreateAxes((IAgStkObject)m_referenceSatellite, $"{constrainedVectorName}Axes_Scheduled", constraintToAlignedCondition, negativeRotatedAxes, positiveRotatedAxes); } // Create scheduled vector to point along alignment vector when constraint is not broken, and hold at constraint when violated. IAgCrdnVector alignedScheduledAxis = GetVectorFromAxes((IAgStkObject)m_referenceSatellite, scheduledAxes, alignedBodyAxis); IAgCrdnVector scheduledVector = CreateVector((IAgStkObject)m_referenceSatellite, $"{alignedVectorName}Scheduled", constraintToBodyCondition, duplicateAlignedVector, alignedScheduledAxis); return(scheduledVector); }
public static IAgCrdnCalcScalarAngle GetCreateAngleCalcScalar(IAgCrdnProvider vgtPrv, IAgCrdnAngle inputAngle, string scalarName) { IAgCrdnCalcScalarAngle calcScalarAngle; if (vgtPrv.CalcScalars.Contains(scalarName)) { calcScalarAngle = (IAgCrdnCalcScalarAngle)vgtPrv.CalcScalars[scalarName]; } else { calcScalarAngle = (IAgCrdnCalcScalarAngle)vgtPrv.CalcScalars.Factory.CreateCalcScalarAngle(scalarName, ""); } calcScalarAngle.InputAngle = inputAngle; return(calcScalarAngle); }