Example #1
0
        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;
        }
Example #2
0
        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);
        }