{"id":196775,"date":"2025-07-02T09:34:28","date_gmt":"2025-07-02T09:34:28","guid":{"rendered":"https:\/\/innovationspace.ansys.com\/knowledge\/?post_type=topic&#038;p=196775"},"modified":"2025-11-26T15:42:05","modified_gmt":"2025-11-26T15:42:05","slug":"scade-and-stk-satellite-attitude-control","status":"publish","type":"topic","link":"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/scade-and-stk-satellite-attitude-control\/","title":{"rendered":"SCADE and STK &#8211; Satellite Attitude Control"},"content":{"rendered":"<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-banner.jpeg\" style=\"max-height: 700px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<h3  id=\"INTRODUCTION\">Introduction<\/h3>\n<p>Modern space missions demand highly accurate and reliable control systems, especially when it comes to satellite attitude control. This article explores how <a href=\"https:\/\/www.ansys.com\/products\/embedded-software\/ansys-scade-suite\">Ansys SCADE<\/a> and <a href=\"https:\/\/www.ansys.com\/products\/missions\/ansys-stk\">Ansys STK<\/a> (Systems Tool Kit) can be integrated to create a powerful simulation environment for satellite embedded software development, enabling real-time testing and validation of attitude control strategies<a href=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-attitude.gif\">.<\/a><\/p>\n<p>In this blog, we integrate STK and SCADE to simulate a satellite attitude control software on a host computer.<\/p>\n<p><em>Note:<\/em> this article is written using SCADE Suite for embedded software design, but the integration would be similar with our new generation product, <a href=\"https:\/\/www.ansys.com\/products\/embedded-software\/ansys-scade-one\">Ansys Scade One<\/a>.<\/p>\n<h4  id=\"SATELLITE-ATTITUDE-CONTROL\">Satellite Attitude Control<\/h4>\n<p><strong>Attitude control<\/strong> refers to the orientation of a spacecraft relative to an inertial frame of reference. Maintaining the correct attitude is vital for satellite operations, such as ensuring that antennas point towards Earth or solar panels face the Sun.<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-stk-attitude-a.jpg\" style=\"max-height: 500px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<h4  id=\"COMBINING-THE-POWER-OF-SCADE-AND-STK\">Combining the power of SCADE and STK<\/h4>\n<table style=\"max-width: 1000px;border: none !important\">\n<tr>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-scade-logo-1.svg\" style=\"max-height: 100px !important\" \/><br \/>\n                <em><\/em>\n<\/p>\n<p><strong>SCADE<\/strong> is a model-based development environment focused on safety-critical embedded software.<\/p>\n<p>It is used to develop, simulate, and generate code for critical systems, such as the satellite attitude controller.<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-adcs-logic-1.png\" style=\"max-height: 300px !important\" \/><br \/>\n                <em><\/em>\n<\/p>\n<\/td>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-stk-logo-1.svg\" style=\"max-height: 100px !important\" \/><br \/>\n                <em><\/em>\n<\/p>\n<p><strong>STK<\/strong> is used to simulate and visualize air and space missions, satellite orbits, and dynamic systems.<\/p>\n<p>It provides realistic physics-based modeling.<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-stk-attitude-b.jpg\" style=\"max-height: 300px !important\" \/><br \/>\n                <em><\/em>\n<\/p>\n<\/td>\n<\/tr>\n<\/table>\n<p>The integration of SCADE and STK bridges model-based software design with high-fidelity mission simulation. When combined, these tools create a closed-loop simulation environment, where satellite dynamics and control logic interact in real time.<\/p>\n<h3  id=\"USE-CASE-DESCRIPTION\">Use case description<\/h3>\n<p>In our scenario, a satellite is orbiting Earth with a defined <strong>initial state<\/strong> (angular speed and orientation) and a <strong>target state <\/strong>(target angular speed and orientation). While its orbit remains unchanged, we want the satellite&#8217;s orientation to be actively managed by a software controller.<strong> <\/strong><\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-stk-attitude-c-1.png\" style=\"max-height: 400px !important\" \/><br \/>\n    <em>Simulated satellite with its initial attitude (grey) and target attitude (red)<\/em>\n<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-stk-attitude-d.jpg\" style=\"max-height: 500px !important\" \/><br \/>\n    <em>Simulated satellite trajectory and angular speeds<\/em>\n<\/p>\n<p>Our SCADE Model is responsible for the following:<\/p>\n<ul>\n<li><strong>Reading inputs<\/strong>: Current and target angular speeds and orientations, expressed as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Quaternions_and_spatial_rotation\">quaternions<\/a> and Euler angles.<\/li>\n<li><strong>Computing output<\/strong>: Torque needed to correct the satellite&#8217;s orientation, expressed as a three-dimensional vector. Note that the torque is just a vector. How it gets applied to the satellite (reaction wheels, thrusters&#8230;) is up to the STK model.<\/li>\n<\/ul>\n<h3  id=\"INTEGRATION-WORKFLOW\">Integration Workflow<\/h3>\n<p>The integration between SCADE and STK involves several components:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-architecture-2.svg\" style=\"max-height: 500px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<ul>\n<li>A <strong>SCADE model,<\/strong> compiled into a Windows DLL.<\/li>\n<li>A <strong>Python proxy<\/strong>, using the <a href=\"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/jupyter-notebook-programming-with-the-scade-python-wrapper\/\">SCADE Python Wrapper<\/a>, to exercise the model.<\/li>\n<li>A <strong>manual Python script<\/strong> that maps STK parameters to SCADE inputs\/outputs, and calls the SCADE root operator at each simulation step.<\/li>\n<li>The <strong>STK engine<\/strong> to process attitude changes and send updates.<\/li>\n<\/ul>\n<p>On the STK side, the Attitude Simulator provides an interface to connect to MATLAB, VBScript, Python, or Perl scripts. The STK to Python interface is done through COM interaction.<\/p>\n<p><em>Note: The approach described is specific to attitude control plugin. Adapting it to other simulation domains within STK may require adjustments due to differing APIs.<\/em><\/p>\n<h4  id=\"REQUIREMENTS\">Requirements<\/h4>\n<p>Running this integration requires:<\/p>\n<ul>\n<li>An STK 12 installation (the Jupyter Notebook Plugin is optional but recommended).<\/li>\n<li>A SCADE Suite Installation in version 2024 R2 or later.<\/li>\n<li>A Python Interpreter in version 3.10 or later. One comes packaged with SCADE, under <code>\/contrib\/Python310<\/code>.<\/li>\n<li>The SCADE Python Wrapper.<\/li>\n<\/ul>\n<h4  id=\"SCADE-MODEL-AND-PYTHON-WRAPPER\">SCADE Model and Python Wrapper<\/h4>\n<p>The core logic of the SCADE model is a simple Proportional \/ Derivative controller, converting the measured and target data into a torque vector:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-attitude-controller-logic-1.png\" style=\"max-height: 500px !important\" \/><br \/>\n    <em>Scade Attitude Controller logic<\/em>\n<\/p>\n<p>To generate the Python Proxy module, we&#8217;ll use the same technique described in a <a href=\"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/jupyter-notebook-programming-with-the-scade-python-wrapper\/\">previous blog<\/a>.<\/p>\n<p>Once generated, the proxy contains the following:<\/p>\n<ul>\n<li>A global variable called <code>sensors<\/code> with one read\/write property per sensor in the model.<\/li>\n<li>A class per root operator which defines:\n<ul>\n<li>One read\/write property per input<\/li>\n<li>One read-only property per output<\/li>\n<li>Two functions to exercise the generated code:\n<ul>\n<li><code>call_reset(self) -&gt; None<\/code><\/li>\n<li><code>call_cycle(self, cycles: int = 1) -&gt; None<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>In white box simulation mode, the <code>call_cycle<\/code> signature becomes:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span>call_cycle(<span style=\"color: #999999\">self<\/span>, cycles: <span style=\"color: #999999\">int<\/span> <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">1<\/span>, refresh: <span style=\"color: #999999\">bool<\/span> <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">True<\/span>, debug: <span style=\"color: #999999\">bool<\/span> <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">False<\/span>) <span style=\"font-weight: bold\">-&gt;<\/span> <span style=\"font-weight: bold\">None<\/span>\r\n<\/pre>\n<\/div>\n<h4  id=\"INTEGRATING-THE-WRAPPER-WITH-THE-ATTITUDE-CONTROLLER-PLUGIN\">Integrating the wrapper with the Attitude Controller Plugin<\/h4>\n<p>On the STK side, the attitude controller expects the registration of Python functions with a particular signature. We manually write these &#8216;glue&#8217; functions between STK and the SCADE Python Proxy into an intermediary Python file.<\/p>\n<p>For this code, we rely on two sections of the STK documentation: <a href=\"https:\/\/help.agi.com\/stkdevkit\/index.htm#..\/Subsystems\/pluginScripts\/Content\/pythonFunction.htm\">Python functions<\/a> and <a href=\"https:\/\/help.agi.com\/stkdevkit\/index.htm#..\/Subsystems\/pluginScripts\/Content\/attitudePoints.htm\">Attitude Simulator plugin points<\/a>.<\/p>\n<p>The code consists of three main parts.<\/p>\n<p>First, a <strong>main function<\/strong> serves as the entry point called by STK. It takes a list argument, the first element of which is the calling mode. This mode is set to <code>register<\/code> once to indicate the initialization phase. Then, it is set to <code>None<\/code> to run simulation steps. Some STK interfaces may also set it to <code>compute<\/code>.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"font-weight: bold\">def<\/span> <span style=\"color: #990000;font-weight: bold\">Attitude_Torque_Controller<\/span>(argList):\r\n    callMode <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #999999\">str<\/span>(argList[<span style=\"color: #009999\">0<\/span>])\r\n    <span style=\"font-weight: bold\">if<\/span> callMode <span style=\"font-weight: bold\">in<\/span> [<span style=\"color: #bb8844\">&#039;None&#039;<\/span>,<span style=\"color: #bb8844\">&#039;compute&#039;<\/span>]:\r\n        retVal <span style=\"font-weight: bold\">=<\/span> Attitude_Torque_Controller_compute(argList) <span style=\"color: #999988;font-style: italic\"># Run a SCADE cycle<\/span>\r\n    <span style=\"font-weight: bold\">elif<\/span> callMode <span style=\"font-weight: bold\">==<\/span> <span style=\"color: #bb8844\">&#039;register&#039;<\/span>:\r\n        <span style=\"font-weight: bold\">global<\/span> Attitude_Torque_Controller_init\r\n        Attitude_Torque_Controller_init <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">-<\/span><span style=\"color: #009999\">1<\/span>\r\n        retVal <span style=\"font-weight: bold\">=<\/span> Attitude_Torque_Controller_register()\r\n    <span style=\"font-weight: bold\">else<\/span>:\r\n        retVal <span style=\"font-weight: bold\">=<\/span> []  <span style=\"color: #999988;font-style: italic\"># bad call, return empty list<\/span>\r\n    <span style=\"font-weight: bold\">return<\/span> retVal\r\n<\/pre>\n<\/div>\n<p>Next, a function to <strong>register inputs and outputs<\/strong> once during initialization:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"font-weight: bold\">def<\/span> <span style=\"color: #990000;font-weight: bold\">Attitude_Torque_Controller_register<\/span>():\r\n    <span style=\"color: #999988;font-style: italic\"># Register arguments, as described in https:\/\/help.agi.com\/stkdevkit\/12.9.1\/index.htm#..\/Subsystems\/pluginScripts\/Content\/pythonFunction.htm<\/span>\r\n    arg1 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Output ; Type = Parameter ; ArgumentName = Torque ; Name = Torque ; BasicType = Vector&#039;<\/span>\r\n    arg2 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = time ; Name = Epoch&#039;<\/span>\r\n    arg3 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = att ; Type = Attitude; Derivative = Yes &#039;<\/span>\r\n    arg5 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = q1r ; Name = q1; Type = Scalar; Source = Satellite\/Reference&#039;<\/span>\r\n    arg6 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = q2r ; Name = q2; Type = Scalar; Source = Satellite\/Reference&#039;<\/span>\r\n    arg7 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = q3r ; Name = q3; Type = Scalar; Source = Satellite\/Reference&#039;<\/span>\r\n    arg8 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = q4r ; Name = q4; Type = Scalar; Source = Satellite\/Reference&#039;<\/span>\r\n    arg9 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = angxr ; Name = angx; Type = Scalar; Source = Satellite\/Reference&#039;<\/span>\r\n    arg10 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = angyr ; Name = angy; Type = Scalar; Source = Satellite\/Reference&#039;<\/span>\r\n    arg11 <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #bb8844\">&#039;ArgumentType = Input ; ArgumentName = angzr ; Name = angz; Type = Scalar; Source = Satellite\/Reference&#039;<\/span>\r\n    argList <span style=\"font-weight: bold\">=<\/span> [arg1, arg2, arg3, arg5, arg6, arg7, arg8, arg9, arg10, arg11]\r\n\r\n    <span style=\"color: #999988;font-style: italic\"># Instantiate the SCADE model proxy<\/span>\r\n    <span style=\"color: #999988;font-style: italic\"># The cosim flag would start a simulator session in SCADE<\/span>\r\n    <span style=\"font-weight: bold\">global<\/span> adcs_op\r\n    adcs_op <span style=\"font-weight: bold\">=<\/span> SCADE_ADCS(cosim<span style=\"font-weight: bold\">=False<\/span>)\r\n\r\n    <span style=\"color: #999988;font-style: italic\"># Provide initial SCADE model inputs as constants<\/span>\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>ThetaX <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">1000<\/span>\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>ThetaY <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">1000<\/span>\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>ThetaZ <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">1000<\/span>\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>SigmaQuaternion <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">0<\/span>\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>SigmaOmega <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">0.001<\/span>\r\n\r\n    <span style=\"font-weight: bold\">return<\/span> argList\r\n<\/pre>\n<\/div>\n<p>And finally, a <strong>compute function<\/strong>, running one cycle of the SCADE model and called by STK at each step of the simulation:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"font-weight: bold\">def<\/span> <span style=\"color: #990000;font-weight: bold\">Attitude_Torque_Controller_compute<\/span>(argList):\r\n    <span style=\"font-weight: bold\">global<\/span> Attitude_Torque_Controller_init\r\n    <span style=\"font-weight: bold\">global<\/span> Attitude_Torque_Controller_Inputs\r\n\r\n    <span style=\"color: #999988;font-style: italic\"># Access data based on argument names<\/span>\r\n    <span style=\"font-weight: bold\">if<\/span> Attitude_Torque_Controller_init <span style=\"font-weight: bold\">&lt;<\/span> <span style=\"color: #009999\">0<\/span>:\r\n        Attitude_Torque_Controller_init <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">1<\/span>\r\n        Attitude_Torque_Controller_Inputs <span style=\"font-weight: bold\">=<\/span> g_PluginArrayInterfaceHash[<span style=\"color: #bb8844\">&quot;Attitude_Torque_Controller_Inputs&quot;<\/span>]\r\n\r\n    <span style=\"color: #999988;font-style: italic\"># Retrieve STK inputs<\/span>\r\n    q1r <span style=\"font-weight: bold\">=<\/span> argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;q1r&#039;<\/span>]]\r\n    q2r <span style=\"font-weight: bold\">=<\/span> argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;q2r&#039;<\/span>]]\r\n    q3r <span style=\"font-weight: bold\">=<\/span> argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;q3r&#039;<\/span>]]\r\n    q4r <span style=\"font-weight: bold\">=<\/span> argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;q4r&#039;<\/span>]]\r\n    angxr <span style=\"font-weight: bold\">=<\/span> argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;angxr&#039;<\/span>]]\r\n    angyr <span style=\"font-weight: bold\">=<\/span> argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;angyr&#039;<\/span>]]\r\n    angzr <span style=\"font-weight: bold\">=<\/span> argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;angzr&#039;<\/span>]]\r\n    att <span style=\"font-weight: bold\">=<\/span> np<span style=\"font-weight: bold\">.<\/span>array(argList[Attitude_Torque_Controller_Inputs[<span style=\"color: #bb8844\">&#039;att&#039;<\/span>]])\r\n\r\n    <span style=\"color: #999988;font-style: italic\"># Pass inputs to the SCADE Model through the adcs object<\/span>\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>MeasuredQuaternion[<span style=\"color: #009999\">0<\/span>] <span style=\"font-weight: bold\">=<\/span> att[<span style=\"color: #009999\">0<\/span>]\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>MeasuredQuaternion[<span style=\"color: #009999\">1<\/span>] <span style=\"font-weight: bold\">=<\/span> att[<span style=\"color: #009999\">1<\/span>]\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>MeasuredQuaternion[<span style=\"color: #009999\">2<\/span>] <span style=\"font-weight: bold\">=<\/span> att[<span style=\"color: #009999\">2<\/span>]\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>MeasuredQuaternion[<span style=\"color: #009999\">3<\/span>] <span style=\"font-weight: bold\">=<\/span> att[<span style=\"color: #009999\">3<\/span>]\r\n\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>MeasuredAngularSpeed[<span style=\"color: #009999\">0<\/span>] <span style=\"font-weight: bold\">=<\/span> math<span style=\"font-weight: bold\">.<\/span>degrees(att[<span style=\"color: #009999\">4<\/span>])\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>MeasuredAngularSpeed[<span style=\"color: #009999\">1<\/span>] <span style=\"font-weight: bold\">=<\/span> math<span style=\"font-weight: bold\">.<\/span>degrees(att[<span style=\"color: #009999\">5<\/span>])\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>MeasuredAngularSpeed[<span style=\"color: #009999\">2<\/span>] <span style=\"font-weight: bold\">=<\/span> math<span style=\"font-weight: bold\">.<\/span>degrees(att[<span style=\"color: #009999\">6<\/span>])\r\n\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>RefQuater[<span style=\"color: #009999\">0<\/span>] <span style=\"font-weight: bold\">=<\/span> q1r\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>RefQuater[<span style=\"color: #009999\">1<\/span>] <span style=\"font-weight: bold\">=<\/span> q2r\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>RefQuater[<span style=\"color: #009999\">2<\/span>] <span style=\"font-weight: bold\">=<\/span> q3r\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>RefQuater[<span style=\"color: #009999\">3<\/span>] <span style=\"font-weight: bold\">=<\/span> q4r\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>RefAngularSpeed[<span style=\"color: #009999\">0<\/span>] <span style=\"font-weight: bold\">=<\/span> math<span style=\"font-weight: bold\">.<\/span>degrees(angxr)\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>RefAngularSpeed[<span style=\"color: #009999\">1<\/span>] <span style=\"font-weight: bold\">=<\/span> math<span style=\"font-weight: bold\">.<\/span>degrees(angyr)\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>RefAngularSpeed[<span style=\"color: #009999\">2<\/span>] <span style=\"font-weight: bold\">=<\/span> math<span style=\"font-weight: bold\">.<\/span>degrees(angzr)\r\n    \r\n    <span style=\"color: #999988;font-style: italic\"># Call the SCADE model\u2019s root operator<\/span>\r\n    <span style=\"color: #999988;font-style: italic\"># Set refresh to true to have the value refreshed in the UI<\/span>\r\n    <span style=\"color: #999988;font-style: italic\"># Set debug to true to pause the simulation after executing the cycle<\/span>\r\n    adcs_op<span style=\"font-weight: bold\">.<\/span>call_cycle(refresh<span style=\"font-weight: bold\">=True<\/span>,debug<span style=\"font-weight: bold\">=True<\/span>)\r\n\r\n    <span style=\"color: #999988;font-style: italic\"># Retrieve and return the output<\/span>\r\n    output <span style=\"font-weight: bold\">=<\/span> adcs_op<span style=\"font-weight: bold\">.<\/span>OutputTorque\r\n    retList <span style=\"font-weight: bold\">=<\/span> np<span style=\"font-weight: bold\">.<\/span>array([output[<span style=\"color: #009999\">0<\/span>], output[<span style=\"color: #009999\">1<\/span>], output[<span style=\"color: #009999\">2<\/span>]])\r\n\r\n    <span style=\"font-weight: bold\">return<\/span> np<span style=\"font-weight: bold\">.<\/span>array([retList])\r\n<\/pre>\n<\/div>\n<h4  id=\"RUNNING-AND-DEBUGGING-THE-SIMULATION\">Running and debugging the simulation<\/h4>\n<p>Once the Python part is done, we can register the script from the STK IDE.<\/p>\n<p>The Attitude Simulator plugin is accessible from right click the Satellite &gt; Satellite &gt; Attitude Simulator&#8230;<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-attitude-simulator-menu-1.png\" style=\"max-height: 305px !important\" \/><br \/>\n    <em>Accessing the Attitude Simulator<\/em>\n<\/p>\n<p>From there, we click <em>Configuration&#8230;<\/em>:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-attitude-simulator-config-1.png\" style=\"max-height: 673px !important\" \/><br \/>\n    <em>Attitude Simulator Configuration menu<\/em>\n<\/p>\n<p>In Simulation, we click <em>Add<\/em> and select the Python file located under <code>\/Scripting\/Attitude<\/code>. We see it successfully appear:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-attitude-simulator-add-script-1.png\" style=\"max-height: 253px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>Once registered, we run the simulation with the plugin dialog&#8217;s <em>Run&#8230;<\/em> button:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-attitude-simulator-run-simulation-1.png\" style=\"max-height: 104px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>If co-simulation was set to true in the Python code, a SCADE Simulator Session starts, allowing to do a step by step debugging of the scenario. Otherwise, the simulation runs by itself.<\/p>\n<p>This video showcases all steps above, up to the execution of the simulation:<\/p>\n<p><p style=\"text-align: center\"><iframe loading=\"lazy\" class=\"vidyard_iframe\" src=\"https:\/\/play.vidyard.com\/pcRGDEQXmswG5Hkp7HWfbK\" width=\"740\" height=\"460\" frameborder=\"0\" allowfullscreen referrerpolicy=\"no-referrer-when-downgrade\"><\/iframe><\/p>\n<\/p>\n<h3  id=\"WANT-TO-LEARN-MORE\">Want to learn more?<\/h3>\n<p>In this article, we have seen how to integrate SCADE and STK to simulate a satellite attitude control system.<\/p>\n<p>You may start a free trial of SCADE Suite (30 days) using this <a href=\"https:\/\/www.ansys.com\/products\/embedded-software\/ansys-scade-suite\/scade-trial\">link<\/a>, and of STK (21 days) using <a href=\"https:\/\/licensing.agi.com\/stk\/\">that link<\/a>. If you&#8217;d like to know more about how Ansys SCADE and STK can improve your engineering workflows, you may contact us from the <a href=\"https:\/\/www.ansys.com\/products\/embedded-software\">Ansys Embedded Software page<\/a> or the <a href=\"https:\/\/www.ansys.com\/products\/missions\">Ansys Digital Mission Engineering page<\/a>.<\/p>\n<p>In future blogs, we will dive into other use cases where SCADE and STK come together to solve real world engineering problems:<\/p>\n<ul>\n<li>Enhancing the Satellite Attitude Controller using the <a href=\"https:\/\/fmi-standard.org\/\">FMI standard<\/a><\/li>\n<li>Battery Monitoring for autonomous eVTOL vehicles<\/li>\n<li>Thermal and attitude control simulations<\/li>\n<li>UAV &amp; fighter formation flight<\/li>\n<\/ul>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-other-use-cases.jpg\" style=\"max-height: 300px !important\" \/><\/p>\n<h3  id=\"ABOUT-THE-AUTHOR\">About the author<\/h3>\n<table style=\"max-width: 1000px;border: none !important\">\n<tr>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2025\/07\/scade-045-author-1.png\" style=\"max-height: 150px !important\" \/><br \/>\n                <em><\/em>\n<\/p>\n<\/td>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p><strong>Romain Andrieux<\/strong> (<a href=\"https:\/\/www.linkedin.com\/in\/romain-andrieux-922a36103\">LinkedIn<\/a>) is a Product Specialist Engineer at Ansys. He has been working on SCADE Ecosystem and the SCADE Support team development for 2 years.<\/p>\n<\/td>\n<\/tr>\n<\/table>\n","protected":false},"template":"","class_list":["post-196775","topic","type-topic","status-publish","hentry","topic-tag-satellite","topic-tag-scade","topic-tag-space","topic-tag-stk","topic-tag-suite"],"aioseo_notices":[],"acf":[],"custom_fields":[{"0":{"_edit_lock":["1764171661:1769"],"_edit_last":["1769"],"_aioseo_title":[null],"_aioseo_description":[null],"_aioseo_keywords":["a:0:{}"],"_aioseo_og_title":[null],"_aioseo_og_description":[null],"_aioseo_og_article_section":[""],"_aioseo_og_article_tags":["a:0:{}"],"_aioseo_twitter_title":[null],"_aioseo_twitter_description":[null],"filter_by_optics_product":["Lumerical"],"_filter_by_optics_product":["field_64fb192ba3121"],"application_name":[""],"_application_name":["field_64a80903c8e15"],"family":[""],"_family":["field_64a809229a857"],"siebel_km_number":[""],"_siebel_km_number":["field_63ecbffce60db"],"salesforce_km_number":[""],"_salesforce_km_number":["field_63ecc018e60dc"],"km_published_date":[""],"_km_published_date":["field_64c77704499dd"],"product_version":[""],"_product_version":["field_64c776cb4fd2e"],"_bbp_forum_id":["27825"],"_bbp_topic_id":["197678"],"_bbp_author_ip":["20.82.84.9"],"_bbp_last_reply_id":["0"],"_bbp_last_active_id":["196776"],"_bbp_last_active_time":["2025-07-02 09:34:28"],"_bbp_reply_count":["0"],"_bbp_reply_count_hidden":["0"],"_bbp_voice_count":["0"],"_btv_view_count":["5756"],"_bbp_likes_count":["5"]},"test":"solution"}],"_links":{"self":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/196775","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics"}],"about":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/types\/topic"}],"version-history":[{"count":14,"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/196775\/revisions"}],"predecessor-version":[{"id":197678,"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/196775\/revisions\/197678"}],"wp:attachment":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/media?parent=196775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}