Compare commits
583 Commits
Author | SHA1 | Date | |
---|---|---|---|
ea6dbb6454 | |||
bfa9a3c1fe | |||
0166ebb185 | |||
2ba1d0f629 | |||
ca14429a62 | |||
00ce2fe611 | |||
64ec2ffd84 | |||
30bb5d1ac7 | |||
640e316e5e | |||
fe4ef398ed | |||
09f282cfd5 | |||
709be2cd24 | |||
54e4d27fe1 | |||
ce7d1441de | |||
6727950eac | |||
5c951f3e49 | |||
c65ad4ab4f | |||
8da305b247 | |||
1731b21953 | |||
4b99be7316 | |||
bfcd149574 | |||
90701a0723 | |||
1a9a054567 | |||
511f7275f2 | |||
80ce299d37 | |||
6782b4394b | |||
a35b28fc57 | |||
8034982067 | |||
e44f1974cd | |||
b47e8b1ddd | |||
e305d77b32 | |||
abbbb0cabb | |||
f19b129609 | |||
f2d7f32952 | |||
e267b69045 | |||
60922ccc0d | |||
3ec0509bd4 | |||
a73c36c237 | |||
5dd0c2a5cb | |||
1f8dc67922 | |||
e43a86432b | |||
585c49780f | |||
1429aa56a4 | |||
467ee0028a | |||
98a92a6b88 | |||
e1f2514596 | |||
f255feb819 | |||
6d27da4939 | |||
a3ac2505fe | |||
6350e0db0a | |||
db9e83cbc8 | |||
42ae9eafb7 | |||
0475ab872d | |||
225d037c66 | |||
aa5a148800 | |||
4720ab9a35 | |||
ba219fbe7d | |||
32271a98ff | |||
6025ea5663 | |||
5af43ca29b | |||
822df9658f | |||
765e3d6b5b | |||
0b3c928886 | |||
73279a0bf3 | |||
4559d24c62 | |||
b54f8e7738 | |||
6bb12f28a1 | |||
7e8d995b52 | |||
215f2189a6 | |||
8103b2fa0d | |||
b579cd86c1 | |||
4fdec7a74c | |||
744a94704c | |||
f7f14ff021 | |||
fe729f1df0 | |||
7734d1066a | |||
4a0acbf158 | |||
65476f4c98 | |||
aa2bfb7d0e | |||
fa01afe0fa | |||
a6ce06e3f5 | |||
75070b5e66 | |||
26341743a8 | |||
7c10f4b1cd | |||
c1b8e891c5 | |||
18cf46ea31 | |||
2d7356b9ed | |||
675dda8e9e | |||
5bb1bd8946 | |||
eff9116aec | |||
4ed516e0bc | |||
e2ee6a492c | |||
a6422f2d73 | |||
ceb2130726 | |||
fcd3b7815c | |||
1067abba9a | |||
53376fd9ed | |||
c2d05b2045 | |||
48914a2aba | |||
ef8736bd81 | |||
584a16a67c | |||
addfadddb6 | |||
df392d3319 | |||
b079ce85f2 | |||
bc9b8efdb8 | |||
51dcb56583 | |||
df0c8eefab | |||
5a7df626ab | |||
7b53275d61 | |||
709c53d533 | |||
3a70155105 | |||
7a12c1c8fe | |||
0f1c41e828 | |||
c4340c3515 | |||
eec934e1b0 | |||
b01d4f6363 | |||
d9789a48d8 | |||
c3237cae3c | |||
427c53df8c | |||
c89e81cac9 | |||
fb54d976d2 | |||
25a1e4ea25 | |||
a63eb331eb | |||
1793b325ec | |||
1c36f36b1f | |||
0f3eeb42d6 | |||
887f165484 | |||
6cc1d86018 | |||
d4eb124cdf | |||
47cedb90f9 | |||
f3d4e09487 | |||
2057ab9c10 | |||
1f0e2d99e9 | |||
35181a2693 | |||
e1b5625086 | |||
72626582f6 | |||
3e6d26669a | |||
69f378f8b6 | |||
a46f6f34d6 | |||
e6855120f3 | |||
e59235fd75 | |||
3875ddf92b | |||
4171b11928 | |||
43de097812 | |||
56512fae0d | |||
76d00ddd37 | |||
539221a458 | |||
9f03341108 | |||
4193a565a4 | |||
c1c254330b | |||
c46c6cd28b | |||
aeb8b92bc4 | |||
8011686fbe | |||
58be09bd4b | |||
ad82573a35 | |||
a1be15e939 | |||
ba7c9e1c26 | |||
46c125d9fe | |||
889dd04c6b | |||
c52746a2df | |||
f2f856e227 | |||
0cbac07f15 | |||
18d3c8fa91 | |||
3e1ef8bcaf | |||
d1fc876f03 | |||
0278aabee0 | |||
a9f5b6d2c7 | |||
80ea0b341b | |||
9740831755 | |||
c4e18432e2 | |||
f9f5ba5d46 | |||
3b521966a9 | |||
c58bae5aa5 | |||
67e6ccf4ae | |||
b795beef85 | |||
311ecd7fd2 | |||
950e86ce4b | |||
096328aadc | |||
36edd3e324 | |||
c65e813e94 | |||
1c93f51f69 | |||
7a43e1bc67 | |||
dade2d519a | |||
c4680f85bb | |||
6c9a7c3ee5 | |||
346f4ff9de | |||
ad5282ca4a | |||
3c869e5215 | |||
8374a02ae2 | |||
f2d1e16697 | |||
158927ce5c | |||
e97105820a | |||
88102b26a6 | |||
7e689c9f55 | |||
97ada32f33 | |||
244c364f60 | |||
c0c3576131 | |||
c2a4578b81 | |||
781feffc90 | |||
7efd48c695 | |||
d0765fdcce | |||
be0bae58ac | |||
616803c6a8 | |||
3501763cf0 | |||
efaf48beff | |||
e052470cf4 | |||
2364f7d5d9 | |||
c52818a5ce | |||
fb8a92ecb5 | |||
39032249b2 | |||
aa4bfa8d88 | |||
c2d8ef9fe4 | |||
440d989490 | |||
85ed8420fd | |||
2a2a173ebd | |||
cda2a9df33 | |||
6da37c0fa4 | |||
141f82d0a9 | |||
b7bf927288 | |||
8fe7307a58 | |||
7e7d8c249e | |||
ffce866ad0 | |||
236916bf67 | |||
9a8c059e05 | |||
48d37783dd | |||
d20c8258da | |||
bd46a607f0 | |||
bdb7f29b99 | |||
c6a308b308 | |||
b9d4d2f3a3 | |||
e908ee119e | |||
f6e99f171a | |||
5876ad1f56 | |||
9cc991e600 | |||
d0f8b7981f | |||
6d5f86ff77 | |||
e77e403e38 | |||
6609ac85e3 | |||
e97970ef64 | |||
af6acb035c | |||
dbb5d6d359 | |||
efd17a971f | |||
557051ba37 | |||
21ef879cae | |||
e9a665ee90 | |||
a2a360c1d7 | |||
d43d1c4f65 | |||
b8a07a3299 | |||
dc730bb6de | |||
61555aa5cf | |||
a7b05f60a7 | |||
8749e4cf6e | |||
97a54c6691 | |||
2d0f13b6e6 | |||
352053f1d2 | |||
f382bd3e61 | |||
b987b6e70c | |||
4cf34cb99a | |||
2ac9f972da | |||
69f4b6de06 | |||
c434882e37 | |||
9e89482298 | |||
9e1e286b97 | |||
9c73e89cbb | |||
386430b9f2 | |||
ab71014f67 | |||
fc40c5cc83 | |||
21ecbaaa7b | |||
4c589e0c1b | |||
f4d1dbb5df | |||
18a7705d97 | |||
3aa3810cac | |||
2965c63bf6 | |||
7066939d76 | |||
c04be384a1 | |||
64f6f92ce6 | |||
a1570e94e7 | |||
962df7e86f | |||
f11240deb4 | |||
8df720e940 | |||
3c389cb069 | |||
b2faa77ebe | |||
96acca4847 | |||
d14b83fab9 | |||
7517b33d83 | |||
3313f58905 | |||
9adb4af0e5 | |||
13aa6f50ff | |||
585b8043e6 | |||
688943cacb | |||
a8172e641f | |||
2e08f3b393 | |||
ff3bf4e291 | |||
4d5ac727a8 | |||
2f43f58792 | |||
75654277b2 | |||
58a8c5869c | |||
5e6b0f5ea2 | |||
e445f8942a | |||
1fd6db8138 | |||
2d92368240 | |||
9a1d91c261 | |||
dbb530e27b | |||
026776c1ec | |||
7d4b97d977 | |||
77527c631c | |||
43cca9ed0c | |||
2b09ec8bc0 | |||
9124cb85fa | |||
124ae6cc7e | |||
b9e4c51d82 | |||
f60fe1ed02 | |||
79a659bc39 | |||
efc0be104c | |||
7314c71062 | |||
9d6206302a | |||
d467953c18 | |||
cf7fbcef97 | |||
16255a91dc | |||
d32f7b31c3 | |||
236ca64de3 | |||
b68bbe64a3 | |||
f56d1c2b12 | |||
c064d1f625 | |||
3954d4dabe | |||
16d909bd5b | |||
1b2dd328ca | |||
2346866ba2 | |||
779bb4a277 | |||
a562a45445 | |||
b5a7db4e66 | |||
b3785628a7 | |||
36658d07f0 | |||
617b956ac9 | |||
ff76f99ad9 | |||
13c180902d | |||
4929cad198 | |||
393d50a54f | |||
3399620ba3 | |||
b7f62ac3e2 | |||
6cbd873a97 | |||
27c824eaec | |||
b4ace906bc | |||
681aebe011 | |||
484dba7eb6 | |||
5ae97d7c09 | |||
01fde7193d | |||
db9afe4a62 | |||
ecc147ca7f | |||
6ca1dda807 | |||
6f3876d204 | |||
f0e551fa54 | |||
15cddfdeb7 | |||
e7dc9cddfd | |||
84ba6262a8 | |||
8be94cf2dc | |||
cc47114891 | |||
0eebc4b00f | |||
6da0c8fe1a | |||
2c9e857060 | |||
c85bef6de4 | |||
8b9c0d3abf | |||
4d22f7f889 | |||
aa521e89f6 | |||
467ab39ad9 | |||
0d80e2a8ec | |||
3cfde3071c | |||
7dc69d3473 | |||
e3f7cda69a | |||
ef4d3066e9 | |||
07e4a6bc5a | |||
da5890f99a | |||
8b91c91a7a | |||
e301b19aba | |||
ac06947078 | |||
84401cc427 | |||
20920fe22f | |||
83fc8a633e | |||
e17ef1bcfd | |||
e3ad08d987 | |||
a4d514fbb5 | |||
8390a02690 | |||
d065f6257e | |||
96b74574b0 | |||
64d105cf87 | |||
f7c997980c | |||
0064cf13cb | |||
62c11798e5 | |||
79efca3a66 | |||
3cc6fce575 | |||
5c7f712bf2 | |||
72b937f223 | |||
c4d0203846 | |||
16fa3d1e26 | |||
5ec173f8c9 | |||
8dbbb7b9ec | |||
87a22abf24 | |||
68b0e3b20a | |||
01735d79f7 | |||
0a7454029d | |||
c7ac5904f8 | |||
bec57f98c0 | |||
3441365c65 | |||
c67f65369c | |||
ba6eac505e | |||
ec2b026103 | |||
060217fbb4 | |||
0d7f5d5dca | |||
398ddd1a3f | |||
c4297975ff | |||
772e8f1149 | |||
315365921e | |||
6cf746463b | |||
5f388d53a6 | |||
26f69d611e | |||
ec3523e5ad | |||
2f296c3c8c | |||
588612875d | |||
944dfb6f81 | |||
291c9ea99b | |||
c1e7ac7e9a | |||
7daeb9a148 | |||
10841a01b7 | |||
42b94ab581 | |||
ff5e1cd76b | |||
3892276a5c | |||
edf2f889c1 | |||
6c90777e4b | |||
a778daacfd | |||
e4f8f20d78 | |||
5df5c30e30 | |||
928dd9e2e0 | |||
05b88dd294 | |||
3c3babdd4b | |||
82dd505194 | |||
54187e47c1 | |||
39b9f770ac | |||
a71c12c9ce | |||
4fcb7fc8c6 | |||
65502c0107 | |||
392a97bb65 | |||
367e879d91 | |||
ef730022a0 | |||
d8ae45b352 | |||
4e8776ff68 | |||
883ff4f6de | |||
13f3739386 | |||
21fc431bc6 | |||
68f8759233 | |||
d3e08c36a2 | |||
d4f45a6dd8 | |||
0fe6c1397d | |||
31fc559d8e | |||
ebe4ca8084 | |||
777b61376c | |||
f4ed981003 | |||
0ae8b4e85e | |||
632b813bdb | |||
2abfb4a6b3 | |||
649949ce0a | |||
c0358d29ce | |||
1308c546fd | |||
e51dd33d82 | |||
262cc78e7e | |||
26b9343ca4 | |||
4701276523 | |||
9833a4e043 | |||
561fe5aa3c | |||
51ccbc6898 | |||
9ceaa6817c | |||
5cdb8db42a | |||
8ab6296abf | |||
d8bd52b4e3 | |||
1e58de635c | |||
be2c4379a7 | |||
f9b56d206e | |||
1dfcc238ed | |||
795b63c34f | |||
a13fbe6f54 | |||
b000f77f4b | |||
9723bf70a0 | |||
4858c1ea57 | |||
8a50746251 | |||
46ffee3e5d | |||
efc4e83857 | |||
cda88cdc56 | |||
cb6992e0f3 | |||
30fb60bd2b | |||
91a12a7b72 | |||
fe0ceac9b4 | |||
acf693636a | |||
87798f9e52 | |||
30f8c31ad0 | |||
160159ff8d | |||
b4886822eb | |||
2c9500c7aa | |||
d762a2b703 | |||
8cd773d18b | |||
42036f45f9 | |||
f05d380ad3 | |||
4cad1176d0 | |||
71193495f3 | |||
09aa7bb439 | |||
215bc8022b | |||
c6a0518515 | |||
6c6b7ff53f | |||
dab10596f6 | |||
a05fd75828 | |||
f22236b419 | |||
fec4f64a07 | |||
9f5a198c5d | |||
b0b279e313 | |||
d0588b144a | |||
5b5d891131 | |||
41c8d7e0dd | |||
4ea1e16880 | |||
064200e730 | |||
08d0619b11 | |||
aab705ca04 | |||
6d2bfbcfe6 | |||
6540d85c99 | |||
64069aa5c1 | |||
b86ee21da0 | |||
d22a2abf64 | |||
c28ff551db | |||
f9ab7962cd | |||
03b43da57f | |||
c6d0357ac9 | |||
99195565f6 | |||
3c24dfad8c | |||
cf6c86fabc | |||
7239b2e26d | |||
c475c8fd8d | |||
3969d05476 | |||
f395c71fd0 | |||
a481fc23f2 | |||
ce620243ce | |||
882c5ce598 | |||
370eff5204 | |||
3c8b0d1a71 | |||
3b4ff437c0 | |||
6ed3dc1b50 | |||
bd71446e05 | |||
e3271b6b4d | |||
14e56aa5d0 | |||
70be396b62 | |||
2f3335403b | |||
f0247a9ab3 | |||
7ef55dcab1 | |||
c7ec9726c4 | |||
647d5fda7c | |||
4a67f9ffe5 | |||
886dd17e4a | |||
0aa09bd516 | |||
a45e96b772 | |||
4a86d4ba4b | |||
9482f3cae9 | |||
5512605cd7 | |||
c465558543 | |||
74e7785c68 | |||
c155f399b1 | |||
4638415264 | |||
60a348a08f | |||
65f907448c | |||
b29c9c6e9c | |||
b8672d3453 | |||
3c383f6d01 | |||
6621b20aef | |||
d5e57501be | |||
77a555debc | |||
8d8eb6bd88 | |||
9482ceb206 | |||
823aa70954 | |||
dc0c24ce96 | |||
17c253d19b | |||
25354ee7b4 | |||
f61da1002f | |||
e7276f282a | |||
740167ce99 | |||
1d51bfba3d | |||
e40dd74f39 | |||
623427035d | |||
8e41885ca1 |
319
CHANGELOG.md
319
CHANGELOG.md
@ -16,6 +16,325 @@ will consitute of a breaking change warranting a new major release:
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v8.2.0] 2024-06-26
|
||||
|
||||
## Changed
|
||||
|
||||
- STR quaternions are now used by the `MEKF` by default
|
||||
- Changed nominal `SUS Assembly` side to `B Side`.
|
||||
- Changed source for state machine of detumbling to SUS and MGM only.
|
||||
- Changed `FusedRotRateData` dataset to always display rotation rate from SUS and MGM.
|
||||
- Solution from `QUEST` will be set to invalid if sun vector and magnetic field vector are too close
|
||||
to each other.
|
||||
- Changed collection intervals of dataset collection
|
||||
- `GPS Controller`: `GPS Set` to 60s
|
||||
- `MTQ Handler`: `HK with Torque`, `HK without Torque` to 60s
|
||||
- `RW Handler`: `Status Set` to 30s
|
||||
- `STR Handler`: `Solution Set` to 30s
|
||||
- `ACS Controller`: `MGM Sensor`, `MGM Processed`, `SUS Sensor`, `SUS Processed`, `GYR Sensor`,
|
||||
`GPS Processed` to 60s
|
||||
- `ACS Controller` at or below `IDLE`: `CTRL Values`, `ACT Commands`, `Attitude Estimation`,
|
||||
`Fused Rotation Rate` to 30s
|
||||
- `ACS Controller` above `IDLE`: `CTRL Values`, `ACT Commands`, `Attitude Estimation`,
|
||||
`Fused Rotation Rate` to 10s
|
||||
|
||||
## Fixed
|
||||
|
||||
- Added null termination for PLOC MPSoC image taking command which could possibly lead to
|
||||
default target filenames.
|
||||
|
||||
# [v8.1.1] 2024-06-05
|
||||
|
||||
## Added
|
||||
|
||||
- PLOC SUPV MPSoC update re-try logic for the `WRITE_MEMORY` command. These packets form > 98%
|
||||
of all packets required for a software update, but the update mechanism is not tolerant against
|
||||
occasional glitches on the RS485 communication to the PLOC SUPV. A simple re-try mechanism which
|
||||
tries to re-attempt packet handling up to three times for those packets is introduced.
|
||||
|
||||
# [v8.1.0] 2024-05-29
|
||||
|
||||
## Fixed
|
||||
|
||||
- Small fix for transition failure handling of the MPSoC when the `START_MPSOC` action command
|
||||
to the supervisor fails.
|
||||
- Fixed inits of arrays within the `MEKF` not being zeros.
|
||||
- Important bugfix for PLOC SUPV: The SUPV previously was able to steal packets from the special
|
||||
communication helper, for example during software updates.
|
||||
- Corrected sigma of STR for `MEKF`.
|
||||
|
||||
## Added
|
||||
|
||||
- Added new command to cancel the PLOC SUPV special communication helper.
|
||||
|
||||
# [v8.0.0] 2024-05-13
|
||||
|
||||
- `eive-tmtc` v7.0.0
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed calculation for target rotation rate during pointing modes.
|
||||
- Possible fix for MPSoC file read algorithm.
|
||||
|
||||
## Changed
|
||||
|
||||
- Reworked MPSoC handler to be compatible to new MPSoC software image and use
|
||||
new device handler base class. This should increase the reliability of the communication
|
||||
significantly.
|
||||
- MPSoC device modes IDLE, SNAPSHOT and REPLAY are now modelled using submodes.
|
||||
- Commanding a submode the device is already in will not result in a completion failure
|
||||
anymore.
|
||||
|
||||
## Added
|
||||
|
||||
- Added `VERIFY_BOOT` command for MPSoC.
|
||||
- New command for MPSoC to store camera image in chunks.
|
||||
|
||||
# [v7.8.1] 2024-04-11
|
||||
|
||||
## Fixed
|
||||
|
||||
- Reverted fix for wrong order in quaternion multiplication for computation of the error quaternion.
|
||||
|
||||
# [v7.8.0] 2024-04-10
|
||||
|
||||
## Changed
|
||||
|
||||
- Reverted lower OP limit of `PLOC` to -10°C.
|
||||
- All pointing laws are now allowed to use the `MEKF` per default.
|
||||
- Changed limits in `PWR Controller`.
|
||||
- PUS time service: Now dumps the time before and after relative timeshift or setting absolute time
|
||||
- The `GPS Controller` does not set itself to `OFF` anymore, if it has not detected a valid fix for
|
||||
some time. Instead it attempts to reset both GNSS devices once.
|
||||
- The maximum time to reach a fix is shortened from 30min to 15min.
|
||||
- The time the reset pin of the GNSS devices is pulled is prolonged from 5ms to 10s.
|
||||
- A `GPS FIX HAS CHANGED` is now only triggered if no fix change has been detected within the past
|
||||
2min. This means, this event might be thrown with a 2min delay. It is instantly thrown, if the mode
|
||||
of the controller is changed. As arguments it now displays the new fix and the numer of fix changes
|
||||
missed.
|
||||
- The number of satellites seen and used is reset to 0, in case they are set to invalid.
|
||||
- Altitude, latitude and longitude messages are not checked anymore, in case the mode message was
|
||||
already invalid.
|
||||
|
||||
## Added
|
||||
|
||||
- PUS timeservice relative timeshift.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed wrong order in quaternion multiplication for computation of the error quaternion.
|
||||
- Re-worked some FDIR logic in the FSFW. The former logic prevented events with a severity
|
||||
higher than INFO if the device was in EXTERNAL CONTROL. The new logic will allow to trigger
|
||||
events but still inhibit FDIR reactions if the device is in EXTERNAL CONTROL.
|
||||
|
||||
# [v7.7.4] 2024-03-21
|
||||
|
||||
## Changed
|
||||
|
||||
- Rotational rate limit for the GS target pointing is now seperated from controller limit. It
|
||||
is also reduced to 0.75°/s now.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed wrong sign in calculation of total current within the `PWR Controller`.
|
||||
|
||||
# [v7.7.3] 2024-03-18
|
||||
|
||||
- Bumped `eive-fsfw`
|
||||
|
||||
## Added
|
||||
|
||||
- Added parameter to disable STR input for MEKF.
|
||||
|
||||
## Changed
|
||||
|
||||
- If a primary heater is set to `EXTERNAL CONTROL` and `ON`, the `TCS Controller` will no
|
||||
try to control the temperature of that object.
|
||||
- Set lower OP limit of `PLOC` to -5°C.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Added prevention of sign jump for target quaternion of GS pointing, which would reduce the
|
||||
performance of the controller.
|
||||
- Heaters set to `EXTERNAL CONTROL` no longer can be switched off by the `TCS Controller`, if
|
||||
they violate the maximum burn duration of the controller.
|
||||
|
||||
# [v7.7.2] 2024-03-06
|
||||
|
||||
## Fixed
|
||||
|
||||
- Camera and E-band antenna now point towards the target instead of away from the target for the
|
||||
pointing target mode.
|
||||
|
||||
# [v7.7.1] 2024-03-06
|
||||
|
||||
- Bumped `eive-tmtc` to v6.1.1
|
||||
- Bumped `eive-fsfw`
|
||||
|
||||
## Added
|
||||
|
||||
- The `CoreController` now sets the leap seconds on initalization. They are stored in a persistent
|
||||
file. If the file does yet not exist, it will be created. The leap seconds can be updated using an
|
||||
action command. This will also update the file.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed wrong dimension of a matrix within the `MEKF`, which would lead to a seg fault, if the
|
||||
star tracker was available.
|
||||
- Fixed case in which control values within the `AcsController` could become NaN.
|
||||
|
||||
# [v7.7.0] 2024-02-29
|
||||
|
||||
- Bumped `eive-tmtc` to v6.1.0
|
||||
- Bumped `eive-fsfw`
|
||||
|
||||
## Fixed
|
||||
|
||||
- PLOC SUPV sets: Added missing `PoolReadGuard` instantiations when reading boot status report
|
||||
and latchup status report.
|
||||
- PLOC SUPV latchup report could not be handled previously.
|
||||
- Bugfix in PLOC SUPV latchup report parsing.
|
||||
- Bugfix in PLOC MPSoC HK set: Set and variables were not set valid.
|
||||
- The `PTG_CTRL_NO_ATTITUDE_INFORMATION` will now actually trigger a fallback into safe mode
|
||||
and is triggered by the `AcsController` now.
|
||||
- Fixed a corner case, in which an invalid speed command could be sent to the `RwHandler`.
|
||||
- Fixed calculation of desaturation torque for faulty RWs.
|
||||
- Fixed bugs within the `MEKF` and simplified the code.
|
||||
|
||||
## Changed
|
||||
|
||||
- `FusedRotationRate` now only uses rotation rate from QUEST and STR in higher modes
|
||||
- QUEST and STR rates are now allowed per default
|
||||
- Changed PTG Strat priorities to favor STR before MEKF.
|
||||
- Increased message queue depth and maximum number of handled messages per cycle for
|
||||
`PusServiceBase` based classes (especially PUS scheduler).
|
||||
- `MathOperations` functions were moved to their appropriate classes within the `eive-fsfw`
|
||||
- Changed pointing strategy for target groundstation mode to prevent blinding of the STR. This
|
||||
also limits the rotation for the reference target quaternion to prevent spikes in required
|
||||
rotation rates.
|
||||
- Updated QUEST and Sun Vector Params to new values.
|
||||
- Removed the satellites's angular momentum from desaturation calculation.
|
||||
- Bumped internal `sagittactl` library to v11.11.
|
||||
|
||||
## Added
|
||||
|
||||
- Updated STR handler to unlock and allow using the secondary firmware slot.
|
||||
- STR handling for new BlobStats TM set.
|
||||
- Added new action command to update the standard deviations within the `MEKF` from the
|
||||
`AcsParameters`.
|
||||
|
||||
# [v7.6.1] 2024-02-05
|
||||
|
||||
## Changed
|
||||
|
||||
- Guidance now uses the coordinate functions from the FSFW.
|
||||
- Idle should now point the STR away from the earth
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed bugs in `Guidance::comparePtg` and corrected overloading
|
||||
- Detumbling State Machine is now robust to commanded mode changes.
|
||||
|
||||
# [v7.6.0] 2024-01-30
|
||||
|
||||
- Bumped `eive-tmtc` to v5.13.0
|
||||
- Bumped `eive-fsfw`
|
||||
|
||||
## Added
|
||||
|
||||
- Added new parameter for MPSoC which allows to skip SUPV commanding.
|
||||
|
||||
## Changed
|
||||
|
||||
- Increased allowed mode transition time for PLOC SUPV.
|
||||
- Detumbling can now be triggered from all modes of the `AcsController`. In case the
|
||||
current mode is a higher pointing mode, the STR will be set to faulty, to trigger a
|
||||
transition to safe first. Then, in a second step, a transition to detumble is triggered.
|
||||
|
||||
## Fixed
|
||||
|
||||
- If the PCDU handler fails reading data from the IPC store, it will
|
||||
not try to do a deserialization anymore.
|
||||
- All action commands sent by the PLOC SUPV to itself will have no sender now.
|
||||
- RW speed commands get reset to 0 RPM, if the `AcsController` has changed its mode
|
||||
to Safe
|
||||
- Antistiction for RWs will set commanded speed to 0 RPM, if a wheel is detected as not
|
||||
working
|
||||
- Removed parameter to disable antistiction, as deactivating it would result in the
|
||||
`AcsController` being allowed sending invalid speed commands to the RW Handler, which
|
||||
would then trigger FDIR and turning off the functioning device
|
||||
- `RwHandler` returnvalues would use the `INTERFACE_ID` of the `DeviceHandlerBase`
|
||||
- The `AcsController` will reset its stored guidance values on mode change and lost
|
||||
orientation.
|
||||
- The nullspace controller will only be used if all RWs are available.
|
||||
- Calculation of required rotation rate in pointing modes has been fixed to actual
|
||||
calculation of rotation rate from two quaternions.
|
||||
- Fixed alignment matrix and pseudo inverses of RWs, to match the wrong definition of
|
||||
positive rotation.
|
||||
|
||||
# [v7.5.5] 2024-01-22
|
||||
|
||||
## Fixed
|
||||
|
||||
- Calculation of error quaternion was done with inverse of the required target quaternion.
|
||||
|
||||
# [v7.5.4] 2024-01-16
|
||||
|
||||
## Fixed
|
||||
|
||||
- Pointing strategy now actually uses fused rotation rate source instead of its valid flag.
|
||||
- All datasets now get updated during pointing mode, even if the strategy is a fault one.
|
||||
|
||||
# [v7.5.3] 2023-12-19
|
||||
|
||||
## Fixed
|
||||
|
||||
- Set STR quaternions to invalid in device handler if the solution is not trustworthy.
|
||||
|
||||
# [v7.5.2] 2023-12-14
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed faulty scaling within the QUEST algorithm.
|
||||
|
||||
# [v7.5.1] 2023-12-13
|
||||
|
||||
- `eive-tmtc` v5.12.1
|
||||
|
||||
## Changed
|
||||
|
||||
- Increased the maximum number of scheduled telecommands from 500 to 4000. Merry Christmas!
|
||||
|
||||
## Fixed
|
||||
|
||||
- Faulty mapping of input values for QUEST algorithm.
|
||||
- Fixed validity check for QUEST algorithm.
|
||||
|
||||
# [v7.5.0] 2023-12-06
|
||||
|
||||
- `eive-tmtc` v5.12.0
|
||||
|
||||
## Changed
|
||||
|
||||
- ACS-Board default side changed to B-Side
|
||||
- The TLE uploaded now gets stored in a file on the filesystem. It will always be stored on
|
||||
the current active SD Card. After a reboot, the TLE will be read from the filesystem.
|
||||
A filesystem change via `prefSD` on bootup, can lead to the TLE not being read, even
|
||||
though it is there.
|
||||
- Added action cmd to read the currently stored TLE.
|
||||
- Both the `AcsController` and the `PwrController` now use the monotonic clock to calculate
|
||||
the time difference.
|
||||
- `ACS Controller` now has the function `performAttitudeControl` which is called prior to passing
|
||||
on to the relevant mode functions. It handles all telemetry relevant functions, which were
|
||||
always called, regardless of the mode.
|
||||
|
||||
## Added
|
||||
|
||||
- Higher ACS modes can now be entered without a running `MEKF`. Higher modes will collect their
|
||||
quaternion and rotational rate depending on the available sources.
|
||||
- `QUEST` attitude estimation was added to the `AcsController`.
|
||||
- The fused rotational rate can now be estimated from `QUEST` and the `STR`.
|
||||
|
||||
# [v7.4.1] 2023-12-06
|
||||
|
||||
## Fixed
|
||||
|
@ -9,9 +9,9 @@
|
||||
# ##############################################################################
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(OBSW_VERSION_MAJOR 7)
|
||||
set(OBSW_VERSION_MINOR 4)
|
||||
set(OBSW_VERSION_REVISION 1)
|
||||
set(OBSW_VERSION_MAJOR 8)
|
||||
set(OBSW_VERSION_MINOR 2)
|
||||
set(OBSW_VERSION_REVISION 0)
|
||||
|
||||
# set(CMAKE_VERBOSE TRUE)
|
||||
|
||||
@ -64,7 +64,7 @@ include(EiveHelpers)
|
||||
option(EIVE_ADD_ETL_LIB "Add ETL library" ON)
|
||||
option(EIVE_ADD_JSON_LIB "Add JSON library" ON)
|
||||
|
||||
set(OBSW_MAX_SCHEDULED_TCS 500)
|
||||
set(OBSW_MAX_SCHEDULED_TCS 4000)
|
||||
|
||||
if(EIVE_Q7S_EM)
|
||||
set(OBSW_Q7S_EM
|
||||
|
@ -2,14 +2,15 @@
|
||||
#include <linux/payload/PlocMpsocHandler.h>
|
||||
#include <linux/payload/plocSupvDefs.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/parameters/HasParametersIF.h"
|
||||
|
||||
PlocMpsocHandler::PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid,
|
||||
CookieIF* comCookie, PlocMpsocSpecialComHelper* plocMPSoCHelper,
|
||||
CookieIF* comCookie,
|
||||
PlocMpsocSpecialComHelperLegacy* plocMPSoCHelper,
|
||||
Gpio uartIsolatorSwitch, object_id_t supervisorHandler)
|
||||
: DeviceHandlerBase(objectId, uartComIFid, comCookie),
|
||||
hkReport(this),
|
||||
@ -53,24 +54,26 @@ ReturnValue_t PlocMpsocHandler::initialize() {
|
||||
return result;
|
||||
}
|
||||
result = manager->subscribeToEvent(
|
||||
eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_FAILED));
|
||||
eventQueue->getId(),
|
||||
event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_WRITE_FAILED));
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
result = manager->subscribeToEvent(
|
||||
eventQueue->getId(),
|
||||
event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_SUCCESSFUL));
|
||||
event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_WRITE_SUCCESSFUL));
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
result = manager->subscribeToEvent(
|
||||
eventQueue->getId(),
|
||||
event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_SUCCESSFUL));
|
||||
event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_READ_SUCCESSFUL));
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
result = manager->subscribeToEvent(
|
||||
eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_FAILED));
|
||||
eventQueue->getId(),
|
||||
event::getEventId(PlocMpsocSpecialComHelperLegacy::MPSOC_FLASH_READ_FAILED));
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
@ -138,7 +141,7 @@ ReturnValue_t PlocMpsocHandler::executeAction(ActionId_t actionId, MessageQueueI
|
||||
}
|
||||
|
||||
if (specialComHelperExecuting) {
|
||||
return MPSoCReturnValuesIF::MPSOC_HELPER_EXECUTING;
|
||||
return mpsoc::MPSOC_HELPER_EXECUTING;
|
||||
}
|
||||
|
||||
switch (actionId) {
|
||||
@ -407,7 +410,7 @@ ReturnValue_t PlocMpsocHandler::scanForReply(const uint8_t* start, size_t remain
|
||||
sif::debug << "PlocMPSoCHandler::scanForReply: Reply has invalid APID 0x" << std::hex
|
||||
<< std::setfill('0') << std::setw(2) << apid << std::dec << std::endl;
|
||||
*foundLen = remainingSize;
|
||||
return MPSoCReturnValuesIF::INVALID_APID;
|
||||
return mpsoc::INVALID_APID;
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,7 +447,7 @@ ReturnValue_t PlocMpsocHandler::interpretDeviceReply(DeviceCommandId_t id, const
|
||||
}
|
||||
case (mpsoc::TM_FLASH_DIRECTORY_CONTENT): {
|
||||
result = verifyPacket(packet, foundPacketLen);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
if (result == mpsoc::CRC_FAILURE) {
|
||||
sif::warning << "PLOC MPSoC: Flash directory content reply invalid CRC" << std::endl;
|
||||
}
|
||||
/** Send data to commanding queue */
|
||||
@ -556,7 +559,7 @@ ReturnValue_t PlocMpsocHandler::prepareTcMemRead(const uint8_t* commandData,
|
||||
ReturnValue_t PlocMpsocHandler::prepareTcFlashDelete(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
if (commandDataLen > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) {
|
||||
return MPSoCReturnValuesIF::NAME_TOO_LONG;
|
||||
return mpsoc::NAME_TOO_LONG;
|
||||
}
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcFlashDelete tcFlashDelete(spParams, sequenceCount);
|
||||
@ -717,7 +720,7 @@ ReturnValue_t PlocMpsocHandler::finishTcPrep(mpsoc::TcBase& tcBase) {
|
||||
|
||||
ReturnValue_t PlocMpsocHandler::verifyPacket(const uint8_t* start, size_t foundLen) {
|
||||
if (CRC::crc16ccitt(start, foundLen) != 0) {
|
||||
return MPSoCReturnValuesIF::CRC_FAILURE;
|
||||
return mpsoc::CRC_FAILURE;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
@ -726,12 +729,12 @@ ReturnValue_t PlocMpsocHandler::handleAckReport(const uint8_t* data) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = verifyPacket(data, mpsoc::SIZE_ACK_REPORT);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
if (result == mpsoc::CRC_FAILURE) {
|
||||
sif::warning << "PlocMPSoCHandler::handleAckReport: CRC failure" << std::endl;
|
||||
nextReplyId = mpsoc::NONE;
|
||||
replyRawReplyIfnotWiretapped(data, mpsoc::SIZE_ACK_REPORT);
|
||||
triggerEvent(MPSOC_HANDLER_CRC_FAILURE);
|
||||
sendFailureReport(mpsoc::ACK_REPORT, MPSoCReturnValuesIF::CRC_FAILURE);
|
||||
sendFailureReport(mpsoc::ACK_REPORT, mpsoc::CRC_FAILURE);
|
||||
disableAllReplies();
|
||||
return IGNORE_REPLY_DATA;
|
||||
}
|
||||
@ -770,7 +773,7 @@ ReturnValue_t PlocMpsocHandler::handleExecutionReport(const uint8_t* data) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = verifyPacket(data, mpsoc::SIZE_EXE_REPORT);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
if (result == mpsoc::CRC_FAILURE) {
|
||||
sif::warning << "PlocMPSoCHandler::handleExecutionReport: CRC failure" << std::endl;
|
||||
nextReplyId = mpsoc::NONE;
|
||||
return result;
|
||||
@ -791,9 +794,9 @@ ReturnValue_t PlocMpsocHandler::handleExecutionReport(const uint8_t* data) {
|
||||
uint16_t status = mpsoc::getStatusFromRawData(data);
|
||||
sif::warning << "MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl;
|
||||
triggerEvent(EXE_FAILURE, commandId, status);
|
||||
sendFailureReport(mpsoc::EXE_REPORT, MPSoCReturnValuesIF::RECEIVED_EXE_FAILURE);
|
||||
sendFailureReport(mpsoc::EXE_REPORT, mpsoc::RECEIVED_EXE_FAILURE);
|
||||
result = IGNORE_REPLY_DATA;
|
||||
cmdDoneHandler(false, MPSoCReturnValuesIF::RECEIVED_EXE_FAILURE);
|
||||
cmdDoneHandler(false, mpsoc::RECEIVED_EXE_FAILURE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -809,7 +812,7 @@ ReturnValue_t PlocMpsocHandler::handleExecutionReport(const uint8_t* data) {
|
||||
ReturnValue_t PlocMpsocHandler::handleMemoryReadReport(const uint8_t* data) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = verifyPacket(data, tmMemReadReport.rememberRequestedSize);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
if (result == mpsoc::CRC_FAILURE) {
|
||||
sif::warning << "PlocMPSoCHandler::handleMemoryReadReport: Memory read report has invalid crc"
|
||||
<< std::endl;
|
||||
}
|
||||
@ -997,12 +1000,13 @@ ReturnValue_t PlocMpsocHandler::handleGetHkReport(const uint8_t* data) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
hkReport.setValidity(true, true);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocHandler::handleCamCmdRpt(const uint8_t* data) {
|
||||
ReturnValue_t result = verifyPacket(data, foundPacketLen);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
if (result == mpsoc::CRC_FAILURE) {
|
||||
sif::warning << "PlocMPSoCHandler::handleCamCmdRpt: CRC failure" << std::endl;
|
||||
}
|
||||
SpacePacketReader packetReader(data, foundPacketLen);
|
||||
@ -1395,6 +1399,9 @@ bool PlocMpsocHandler::handleHwStartup() {
|
||||
return true;
|
||||
#endif
|
||||
if (powerState == PowerState::IDLE) {
|
||||
if (skipSupvCommandingToOn) {
|
||||
powerState = PowerState::DONE;
|
||||
} else {
|
||||
if (supv::SUPV_ON) {
|
||||
commandActionHelper.commandAction(supervisorHandler, supv::START_MPSOC);
|
||||
supvTransitionCd.resetTimer();
|
||||
@ -1405,6 +1412,7 @@ bool PlocMpsocHandler::handleHwStartup() {
|
||||
setMode(MODE_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (powerState == PowerState::SUPV_FAILED) {
|
||||
setMode(MODE_OFF);
|
||||
powerState = PowerState::IDLE;
|
||||
@ -1532,3 +1540,20 @@ ReturnValue_t PlocMpsocHandler::checkModeCommand(Mode_t commandedMode, Submode_t
|
||||
}
|
||||
return DeviceHandlerBase::checkModeCommand(commandedMode, commandedSubmode, msToReachTheMode);
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocHandler::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) {
|
||||
if (uniqueId == mpsoc::ParamId::SKIP_SUPV_ON_COMMANDING) {
|
||||
uint8_t value = 0;
|
||||
newValues->getElement(&value);
|
||||
if (value > 1) {
|
||||
return HasParametersIF::INVALID_VALUE;
|
||||
}
|
||||
parameterWrapper->set(skipSupvCommandingToOn);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return DeviceHandlerBase::getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||
startAtIndex);
|
||||
}
|
@ -1,23 +1,19 @@
|
||||
#ifndef BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_
|
||||
#define BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_
|
||||
|
||||
#include <linux/payload/PlocMpsocSpecialComHelper.h>
|
||||
#include <linux/payload/mpsocRetvals.h>
|
||||
#include <linux/payload/PlocMpsocSpecialComHelperLegacy.h>
|
||||
#include <linux/payload/plocMpsocHelpers.h>
|
||||
#include <linux/payload/plocSupvDefs.h>
|
||||
#include <mission/controller/controllerdefinitions/PowerCtrlDefinitions.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "fsfw/action/CommandActionHelper.h"
|
||||
#include "fsfw/action/CommandsActionsIF.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
|
||||
#include "fsfw_hal/linux/gpio/Gpio.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
|
||||
static constexpr bool DEBUG_MPSOC_COMMUNICATION = false;
|
||||
static constexpr bool DEBUG_MPSOC_COMMUNICATION = true;
|
||||
|
||||
/**
|
||||
* @brief This is the device handler for the MPSoC of the payload computer.
|
||||
@ -48,7 +44,7 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
* @param supervisorHandler Object ID of the supervisor handler
|
||||
*/
|
||||
PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie,
|
||||
PlocMpsocSpecialComHelper* plocMPSoCHelper, Gpio uartIsolatorSwitch,
|
||||
PlocMpsocSpecialComHelperLegacy* plocMPSoCHelper, Gpio uartIsolatorSwitch,
|
||||
object_id_t supervisorHandler);
|
||||
virtual ~PlocMpsocHandler();
|
||||
virtual ReturnValue_t initialize() override;
|
||||
@ -171,7 +167,7 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
|
||||
SerialComIF* uartComIf = nullptr;
|
||||
|
||||
PlocMpsocSpecialComHelper* specialComHelper = nullptr;
|
||||
PlocMpsocSpecialComHelperLegacy* specialComHelper = nullptr;
|
||||
Gpio uartIsolatorSwitch;
|
||||
object_id_t supervisorHandler = 0;
|
||||
CommandActionHelper commandActionHelper;
|
||||
@ -186,7 +182,7 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
};
|
||||
|
||||
TmMemReadReport tmMemReadReport;
|
||||
Countdown cmdCountdown = Countdown(10000);
|
||||
Countdown cmdCountdown = Countdown(15000);
|
||||
|
||||
struct TelemetryBuffer {
|
||||
uint16_t length = 0;
|
||||
@ -201,6 +197,8 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
|
||||
PowerState powerState = PowerState::IDLE;
|
||||
|
||||
uint8_t skipSupvCommandingToOn = false;
|
||||
|
||||
/**
|
||||
* @brief Handles events received from the PLOC MPSoC helper
|
||||
*/
|
||||
@ -316,6 +314,9 @@ class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
pwrctrl::EnablePl enablePl = pwrctrl::EnablePl(objects::POWER_CONTROLLER);
|
||||
ReturnValue_t checkModeCommand(Mode_t commandedMode, Submode_t commandedSubmode,
|
||||
uint32_t* msToReachTheMode) override;
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ */
|
545
archive/PlocMpsocSpecialComHelperLegacy.cpp
Normal file
545
archive/PlocMpsocSpecialComHelperLegacy.cpp
Normal file
@ -0,0 +1,545 @@
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <linux/payload/PlocMpsocSpecialComHelperLegacy.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/FilesystemHelper.h"
|
||||
#endif
|
||||
|
||||
#include "mission/utility/Timestamp.h"
|
||||
|
||||
using namespace ploc;
|
||||
|
||||
PlocMpsocSpecialComHelperLegacy::PlocMpsocSpecialComHelperLegacy(object_id_t objectId)
|
||||
: SystemObject(objectId) {
|
||||
spParams.buf = commandBuffer;
|
||||
spParams.maxSize = sizeof(commandBuffer);
|
||||
}
|
||||
|
||||
PlocMpsocSpecialComHelperLegacy::~PlocMpsocSpecialComHelperLegacy() {}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::initialize() {
|
||||
#ifdef XIPHOS_Q7S
|
||||
sdcMan = SdCardManager::instance();
|
||||
if (sdcMan == nullptr) {
|
||||
sif::warning << "PlocMPSoCHelper::initialize: Invalid SD Card Manager" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::performOperation(uint8_t operationCode) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
semaphore.acquire();
|
||||
while (true) {
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
trace::threadTrace(opCounter, "PLOC MPSOC Helper");
|
||||
#endif
|
||||
switch (internalState) {
|
||||
case InternalState::IDLE: {
|
||||
semaphore.acquire();
|
||||
break;
|
||||
}
|
||||
case InternalState::FLASH_WRITE: {
|
||||
result = performFlashWrite();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, sequenceCount->get());
|
||||
} else {
|
||||
triggerEvent(MPSOC_FLASH_WRITE_FAILED, sequenceCount->get());
|
||||
}
|
||||
internalState = InternalState::IDLE;
|
||||
break;
|
||||
}
|
||||
case InternalState::FLASH_READ: {
|
||||
result = performFlashRead();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, sequenceCount->get());
|
||||
} else {
|
||||
triggerEvent(MPSOC_FLASH_READ_FAILED, sequenceCount->get());
|
||||
}
|
||||
internalState = InternalState::IDLE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sif::debug << "PlocMPSoCHelper::performOperation: Invalid state" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::setComIF(
|
||||
DeviceCommunicationIF* communicationInterface_) {
|
||||
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
|
||||
if (uartComIF == nullptr) {
|
||||
sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelperLegacy::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
|
||||
|
||||
void PlocMpsocSpecialComHelperLegacy::setSequenceCount(SourceSequenceCounter* sequenceCount_) {
|
||||
sequenceCount = sequenceCount_;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashWrite(std::string obcFile,
|
||||
std::string mpsocFile) {
|
||||
if (internalState != InternalState::IDLE) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile));
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
internalState = InternalState::FLASH_WRITE;
|
||||
return semaphore.release();
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashRead(std::string obcFile,
|
||||
std::string mpsocFile,
|
||||
size_t readFileSize) {
|
||||
if (internalState != InternalState::IDLE) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile));
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
flashReadAndWrite.totalReadSize = readFileSize;
|
||||
internalState = InternalState::FLASH_READ;
|
||||
return semaphore.release();
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelperLegacy::resetHelper() {
|
||||
spParams.buf = commandBuffer;
|
||||
terminate = false;
|
||||
uartComIF->flushUartRxBuffer(comCookie);
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelperLegacy::stopProcess() { terminate = true; }
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::performFlashWrite() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::ifstream file(flashReadAndWrite.obcFile, std::ifstream::binary);
|
||||
if (file.bad()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = flashfopen(mpsoc::FileAccessModes::WRITE | mpsoc::FileAccessModes::OPEN_ALWAYS);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// Set position of next character to end of file input stream
|
||||
file.seekg(0, file.end);
|
||||
// tellg returns position of character in input stream
|
||||
size_t remainingSize = file.tellg();
|
||||
size_t dataLength = 0;
|
||||
size_t bytesRead = 0;
|
||||
while (remainingSize > 0) {
|
||||
if (terminate) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
// The minus 4 is necessary for unknown reasons. Maybe some bug in the ILH software?
|
||||
if (remainingSize > mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4) {
|
||||
dataLength = mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4;
|
||||
} else {
|
||||
dataLength = remainingSize;
|
||||
}
|
||||
if (file.bad() or not file.is_open()) {
|
||||
return FILE_WRITE_ERROR;
|
||||
}
|
||||
file.seekg(bytesRead, file.beg);
|
||||
file.read(reinterpret_cast<char*>(fileBuf.data()), dataLength);
|
||||
bytesRead += dataLength;
|
||||
remainingSize -= dataLength;
|
||||
mpsoc::TcFlashWrite tc(spParams, *sequenceCount);
|
||||
result = tc.setPayload(fileBuf.data(), dataLength);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = tc.finishPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
result = handlePacketTransmissionNoReply(tc);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = flashfclose();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::performFlashRead() {
|
||||
std::error_code e;
|
||||
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::trunc | std::ios::binary);
|
||||
if (ofile.bad()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result = flashfopen(mpsoc::FileAccessModes::READ);
|
||||
if (result != returnvalue::OK) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return result;
|
||||
}
|
||||
size_t readSoFar = 0;
|
||||
size_t nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE;
|
||||
while (readSoFar < flashReadAndWrite.totalReadSize) {
|
||||
if (terminate) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE;
|
||||
if (flashReadAndWrite.totalReadSize - readSoFar < mpsoc::MAX_FLASH_READ_DATA_SIZE) {
|
||||
nextReadSize = flashReadAndWrite.totalReadSize - readSoFar;
|
||||
}
|
||||
if (ofile.bad() or not ofile.is_open()) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return FILE_READ_ERROR;
|
||||
}
|
||||
mpsoc::TcFlashRead flashReadRequest(spParams, *sequenceCount);
|
||||
result = flashReadRequest.setPayload(nextReadSize);
|
||||
if (result != returnvalue::OK) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return result;
|
||||
}
|
||||
result = flashReadRequest.finishPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize);
|
||||
if (result != returnvalue::OK) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return result;
|
||||
}
|
||||
readSoFar += nextReadSize;
|
||||
}
|
||||
result = flashfclose();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::flashfopen(uint8_t mode) {
|
||||
spParams.buf = commandBuffer;
|
||||
mpsoc::FlashFopen flashFopen(spParams, *sequenceCount);
|
||||
ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = flashFopen.finishPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
result = handlePacketTransmissionNoReply(flashFopen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::flashfclose() {
|
||||
spParams.buf = commandBuffer;
|
||||
mpsoc::FlashFclose flashFclose(spParams, *sequenceCount);
|
||||
ReturnValue_t result = flashFclose.finishPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
result = handlePacketTransmissionNoReply(flashFclose);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handlePacketTransmissionFlashRead(
|
||||
mpsoc::TcFlashRead& tc, std::ofstream& ofile, size_t expectedReadLen) {
|
||||
ReturnValue_t result = sendCommand(tc);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleAck();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleTmReception();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// We have the nominal case where the flash read report appears first, or the case where we
|
||||
// get an EXE failure immediately.
|
||||
if (spReader.getApid() == mpsoc::apid::TM_FLASH_READ_REPORT) {
|
||||
result = handleFlashReadReply(ofile, expectedReadLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return handleExe();
|
||||
} else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) {
|
||||
handleExeFailure();
|
||||
} else {
|
||||
triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast<uint32_t>(internalState));
|
||||
sif::warning << "PLOC MPSoC: Expected execution report "
|
||||
<< "but received space packet with apid " << std::hex << spReader.getApid()
|
||||
<< std::endl;
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handlePacketTransmissionNoReply(ploc::SpTcBase& tc) {
|
||||
ReturnValue_t result = sendCommand(tc);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleAck();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return handleExe();
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::sendCommand(ploc::SpTcBase& tc) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen());
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl;
|
||||
triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleAck() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = handleTmReception();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkReceivedTm();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = spReader.getApid();
|
||||
if (apid != mpsoc::apid::ACK_SUCCESS) {
|
||||
handleAckApidFailure(spReader);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelperLegacy::handleAckApidFailure(const ploc::SpTmReader& reader) {
|
||||
uint16_t apid = reader.getApid();
|
||||
if (apid == mpsoc::apid::ACK_FAILURE) {
|
||||
uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData());
|
||||
sif::warning << "PLOC MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl;
|
||||
triggerEvent(MPSOC_ACK_FAILURE_REPORT, static_cast<uint32_t>(internalState), status);
|
||||
} else {
|
||||
triggerEvent(MPSOC_ACK_INVALID_APID, apid, static_cast<uint32_t>(internalState));
|
||||
sif::warning << "PlocMPSoCHelper::handleAckApidFailure: Expected acknowledgement report "
|
||||
<< "but received space packet with apid " << std::hex << apid << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleExe() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = handleTmReception();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkReceivedTm();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = spReader.getApid();
|
||||
if (apid == mpsoc::apid::EXE_FAILURE) {
|
||||
handleExeFailure();
|
||||
return returnvalue::FAILED;
|
||||
} else if (apid != mpsoc::apid::EXE_SUCCESS) {
|
||||
triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast<uint32_t>(internalState));
|
||||
sif::warning << "PLOC MPSoC: Expected execution report "
|
||||
<< "but received space packet with apid " << std::hex << apid << std::endl;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelperLegacy::handleExeFailure() {
|
||||
uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData());
|
||||
sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl;
|
||||
triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast<uint32_t>(internalState));
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleTmReception() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
tmCountdown.resetTimer();
|
||||
size_t readBytes = 0;
|
||||
size_t currentBytes = 0;
|
||||
uint32_t usleepDelay = 5;
|
||||
size_t fullPacketLen = 0;
|
||||
while (true) {
|
||||
if (tmCountdown.hasTimedOut()) {
|
||||
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = receive(tmBuf.data() + readBytes, 6, ¤tBytes);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
spReader.setReadOnlyData(tmBuf.data(), tmBuf.size());
|
||||
fullPacketLen = spReader.getFullPacketLen();
|
||||
readBytes += currentBytes;
|
||||
if (readBytes == 6) {
|
||||
break;
|
||||
}
|
||||
usleep(usleepDelay);
|
||||
if (usleepDelay < 200000) {
|
||||
usleepDelay *= 4;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
if (tmCountdown.hasTimedOut()) {
|
||||
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = receive(tmBuf.data() + readBytes, fullPacketLen - readBytes, ¤tBytes);
|
||||
readBytes += currentBytes;
|
||||
if (fullPacketLen == readBytes) {
|
||||
break;
|
||||
}
|
||||
usleep(usleepDelay);
|
||||
if (usleepDelay < 200000) {
|
||||
usleepDelay *= 4;
|
||||
}
|
||||
}
|
||||
// arrayprinter::print(tmBuf.data(), readBytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::handleFlashReadReply(std::ofstream& ofile,
|
||||
size_t expectedReadLen) {
|
||||
ReturnValue_t result = checkReceivedTm();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = spReader.getApid();
|
||||
if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) {
|
||||
triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR);
|
||||
sif::warning << "PLOC MPSoC Flash Read: Unexpected APID" << std::endl;
|
||||
return result;
|
||||
}
|
||||
const uint8_t* packetData = spReader.getPacketData();
|
||||
size_t deserDummy = spReader.getPacketDataLen() - mpsoc::CRC_SIZE;
|
||||
uint32_t receivedReadLen = 0;
|
||||
// I think this is buggy, weird stuff in the short name field.
|
||||
// std::string receivedShortName = std::string(reinterpret_cast<const char*>(packetData), 12);
|
||||
// if (receivedShortName != flashReadAndWrite.mpsocFile.substr(0, 11)) {
|
||||
// sif::warning << "PLOC MPSoC Flash Read: Missmatch between request file name and "
|
||||
// "received file name"
|
||||
// << std::endl;
|
||||
// triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_FILENAME_ERROR);
|
||||
// return returnvalue::FAILED;
|
||||
// }
|
||||
packetData += 12;
|
||||
result = SerializeAdapter::deSerialize(&receivedReadLen, &packetData, &deserDummy,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (receivedReadLen != expectedReadLen) {
|
||||
sif::warning << "PLOC MPSoC Flash Read: Missmatch between request read length and "
|
||||
"received read length"
|
||||
<< std::endl;
|
||||
triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_READLEN_ERROR);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ofile.write(reinterpret_cast<const char*>(packetData), receivedReadLen);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::fileCheck(std::string obcFile) {
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t result = FilesystemHelper::checkPath(obcFile);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#elif defined(TE0720_1CFA)
|
||||
if (not std::filesystem::exists(obcFile)) {
|
||||
sif::warning << "PlocMPSoCHelper::startFlashWrite: File " << obcFile << "does not exist"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::startFlashReadOrWriteBase(std::string obcFile,
|
||||
std::string mpsocFile) {
|
||||
ReturnValue_t result = fileCheck(obcFile);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
flashReadAndWrite.obcFile = std::move(obcFile);
|
||||
flashReadAndWrite.mpsocFile = std::move(mpsocFile);
|
||||
resetHelper();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::checkReceivedTm() {
|
||||
ReturnValue_t result = spReader.checkSize();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl;
|
||||
triggerEvent(MPSOC_TM_SIZE_ERROR);
|
||||
return result;
|
||||
}
|
||||
result = spReader.checkCrc();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PLOC MPSoC: CRC check failed" << std::endl;
|
||||
triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount);
|
||||
return result;
|
||||
}
|
||||
uint16_t recvSeqCnt = spReader.getSequenceCount();
|
||||
if (recvSeqCnt != *sequenceCount) {
|
||||
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
|
||||
*sequenceCount = recvSeqCnt;
|
||||
}
|
||||
// This sequence count ping pong does not make any sense but it is how the MPSoC expects it.
|
||||
(*sequenceCount)++;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelperLegacy::receive(uint8_t* data, size_t requestBytes,
|
||||
size_t* readBytes) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint8_t* buffer = nullptr;
|
||||
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl;
|
||||
triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result,
|
||||
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl;
|
||||
triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (*readBytes > 0) {
|
||||
std::memcpy(data, buffer, *readBytes);
|
||||
}
|
||||
return result;
|
||||
}
|
200
archive/PlocMpsocSpecialComHelperLegacy.h
Normal file
200
archive/PlocMpsocSpecialComHelperLegacy.h
Normal file
@ -0,0 +1,200 @@
|
||||
#ifndef BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_
|
||||
#define BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_
|
||||
|
||||
#include <linux/payload/plocMpsocHelpers.h>
|
||||
#include <mission/utility/trace.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Helper class for MPSoC of PLOC intended to accelerate large data transfers between
|
||||
* MPSoC and OBC.
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PlocMpsocSpecialComHelperLegacy : public SystemObject, public ExecutableObjectIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HELPER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Flash write fails
|
||||
static const Event MPSOC_FLASH_WRITE_FAILED = MAKE_EVENT(0, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Flash write successful
|
||||
static const Event MPSOC_FLASH_WRITE_SUCCESSFUL = MAKE_EVENT(1, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command
|
||||
//! to the MPSoC
|
||||
//! P1: Return value returned by the communication interface sendMessage function
|
||||
//! P2: Internal state of MPSoC helper
|
||||
static const Event MPSOC_SENDING_COMMAND_FAILED = MAKE_EVENT(2, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Request receive message of communication interface failed
|
||||
//! P1: Return value returned by the communication interface requestReceiveMessage function
|
||||
//! P2: Internal state of MPSoC helper
|
||||
static const Event MPSOC_HELPER_REQUESTING_REPLY_FAILED = MAKE_EVENT(3, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Reading receive message of communication interface failed
|
||||
//! P1: Return value returned by the communication interface readingReceivedMessage function
|
||||
//! P2: Internal state of MPSoC helper
|
||||
static const Event MPSOC_HELPER_READING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Did not receive acknowledgment report
|
||||
//! P1: Number of bytes missing
|
||||
//! P2: Internal state of MPSoC helper
|
||||
static const Event MPSOC_MISSING_ACK = MAKE_EVENT(5, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Did not receive execution report
|
||||
//! P1: Number of bytes missing
|
||||
//! P2: Internal state of MPSoC helper
|
||||
static const Event MPSOC_MISSING_EXE = MAKE_EVENT(6, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Received acknowledgment failure report
|
||||
//! P1: Internal state of MPSoC
|
||||
static const Event MPSOC_ACK_FAILURE_REPORT = MAKE_EVENT(7, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Received execution failure report
|
||||
//! P1: Internal state of MPSoC
|
||||
static const Event MPSOC_EXE_FAILURE_REPORT = MAKE_EVENT(8, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Expected acknowledgment report but received space packet with other apid
|
||||
//! P1: Apid of received space packet
|
||||
//! P2: Internal state of MPSoC
|
||||
static const Event MPSOC_ACK_INVALID_APID = MAKE_EVENT(9, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Expected execution report but received space packet with other apid
|
||||
//! P1: Apid of received space packet
|
||||
//! P2: Internal state of MPSoC
|
||||
static const Event MPSOC_EXE_INVALID_APID = MAKE_EVENT(10, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Received sequence count does not match expected sequence count
|
||||
//! P1: Expected sequence count
|
||||
//! P2: Received sequence count
|
||||
static const Event MPSOC_HELPER_SEQ_CNT_MISMATCH = MAKE_EVENT(11, severity::LOW);
|
||||
static const Event MPSOC_TM_SIZE_ERROR = MAKE_EVENT(12, severity::LOW);
|
||||
static const Event MPSOC_TM_CRC_MISSMATCH = MAKE_EVENT(13, severity::LOW);
|
||||
static const Event MPSOC_FLASH_READ_PACKET_ERROR = MAKE_EVENT(14, severity::LOW);
|
||||
static const Event MPSOC_FLASH_READ_FAILED = MAKE_EVENT(15, severity::LOW);
|
||||
static const Event MPSOC_FLASH_READ_SUCCESSFUL = MAKE_EVENT(16, severity::INFO);
|
||||
static const Event MPSOC_READ_TIMEOUT = MAKE_EVENT(17, severity::LOW);
|
||||
|
||||
enum FlashReadErrorType : uint32_t {
|
||||
FLASH_READ_APID_ERROR = 0,
|
||||
FLASH_READ_FILENAME_ERROR = 1,
|
||||
FLASH_READ_READLEN_ERROR = 2
|
||||
};
|
||||
|
||||
PlocMpsocSpecialComHelperLegacy(object_id_t objectId);
|
||||
virtual ~PlocMpsocSpecialComHelperLegacy();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
|
||||
ReturnValue_t setComIF(DeviceCommunicationIF* communicationInterface_);
|
||||
void setComCookie(CookieIF* comCookie_);
|
||||
|
||||
/**
|
||||
* @brief Starts flash write sequence
|
||||
*
|
||||
* @param obcFile File where to read from the data
|
||||
* @param mpsocFile The file of the MPSoC where should be written to
|
||||
*
|
||||
* @return returnvalue::OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t startFlashWrite(std::string obcFile, std::string mpsocFile);
|
||||
/**
|
||||
*
|
||||
* @param obcFile Full target file name on OBC
|
||||
* @param mpsocFile The file on the MPSoC which should be copied ot the OBC
|
||||
* @param readFileSize The size of the file on the MPSoC.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t startFlashRead(std::string obcFile, std::string mpsocFile, size_t readFileSize);
|
||||
|
||||
/**
|
||||
* @brief Can be used to interrupt a running data transfer.
|
||||
*/
|
||||
void stopProcess();
|
||||
|
||||
/**
|
||||
* @brief Sets the sequence count object responsible for the sequence count handling
|
||||
*/
|
||||
void setSequenceCount(SourceSequenceCounter* sequenceCount_);
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] File error occured for file transfers from OBC to the MPSoC.
|
||||
static const ReturnValue_t FILE_WRITE_ERROR = MAKE_RETURN_CODE(0xA0);
|
||||
//! [EXPORT] : [COMMENT] File error occured for file transfers from MPSoC to OBC.
|
||||
static const ReturnValue_t FILE_READ_ERROR = MAKE_RETURN_CODE(0xA1);
|
||||
|
||||
// Maximum number of times the communication interface retries polling data from the reply
|
||||
// buffer
|
||||
static const int RETRIES = 10000;
|
||||
|
||||
struct FlashInfo {
|
||||
std::string obcFile;
|
||||
std::string mpsocFile;
|
||||
};
|
||||
|
||||
struct FlashRead : public FlashInfo {
|
||||
size_t totalReadSize = 0;
|
||||
};
|
||||
|
||||
struct FlashRead flashReadAndWrite;
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
uint32_t opCounter = 0;
|
||||
#endif
|
||||
|
||||
enum class InternalState { IDLE, FLASH_WRITE, FLASH_READ };
|
||||
|
||||
InternalState internalState = InternalState::IDLE;
|
||||
|
||||
BinarySemaphore semaphore;
|
||||
#ifdef XIPHOS_Q7S
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
#endif
|
||||
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
|
||||
SpacePacketCreator creator;
|
||||
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
|
||||
|
||||
Countdown tmCountdown = Countdown(5000);
|
||||
|
||||
std::array<uint8_t, mpsoc::SP_MAX_DATA_SIZE> fileBuf{};
|
||||
std::array<uint8_t, mpsoc::MAX_REPLY_SIZE> tmBuf{};
|
||||
|
||||
bool terminate = false;
|
||||
|
||||
/**
|
||||
* Communication interface of MPSoC responsible for low level access. Must be set by the
|
||||
* MPSoC Handler.
|
||||
*/
|
||||
SerialComIF* uartComIF = nullptr;
|
||||
// Communication cookie. Must be set by the MPSoC Handler
|
||||
CookieIF* comCookie = nullptr;
|
||||
// Sequence count, must be set by Ploc MPSoC Handler
|
||||
SourceSequenceCounter* sequenceCount = nullptr;
|
||||
ploc::SpTmReader spReader;
|
||||
|
||||
void resetHelper();
|
||||
ReturnValue_t performFlashWrite();
|
||||
ReturnValue_t performFlashRead();
|
||||
ReturnValue_t flashfopen(uint8_t accessMode);
|
||||
ReturnValue_t flashfclose();
|
||||
ReturnValue_t handlePacketTransmissionNoReply(ploc::SpTcBase& tc);
|
||||
ReturnValue_t handlePacketTransmissionFlashRead(mpsoc::TcFlashRead& tc, std::ofstream& ofile,
|
||||
size_t expectedReadLen);
|
||||
ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen);
|
||||
ReturnValue_t sendCommand(ploc::SpTcBase& tc);
|
||||
ReturnValue_t receive(uint8_t* data, size_t requestBytes, size_t* readBytes);
|
||||
ReturnValue_t handleAck();
|
||||
ReturnValue_t handleExe();
|
||||
ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile);
|
||||
ReturnValue_t fileCheck(std::string obcFile);
|
||||
void handleAckApidFailure(const ploc::SpTmReader& reader);
|
||||
void handleExeFailure();
|
||||
ReturnValue_t handleTmReception();
|
||||
ReturnValue_t checkReceivedTm();
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ */
|
@ -48,6 +48,7 @@
|
||||
#define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 1
|
||||
#define OBSW_PRINT_MISSED_DEADLINES 1
|
||||
|
||||
#define OBSW_MPSOC_JTAG_BOOT 0
|
||||
#define OBSW_SYRLINKS_SIMULATED 1
|
||||
#define OBSW_ADD_TEST_CODE 0
|
||||
#define OBSW_ADD_TEST_TASK 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 317 translations.
|
||||
* @brief Auto-generated event translation file. Contains 325 translations.
|
||||
* @details
|
||||
* Generated on: 2023-11-29 15:14:46
|
||||
* Generated on: 2024-05-06 13:47:38
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -82,8 +82,11 @@ const char *BIT_LOCK_STRING = "BIT_LOCK";
|
||||
const char *BIT_LOCK_LOST_STRING = "BIT_LOCK_LOST";
|
||||
const char *FRAME_PROCESSING_FAILED_STRING = "FRAME_PROCESSING_FAILED";
|
||||
const char *CLOCK_SET_STRING = "CLOCK_SET";
|
||||
const char *CLOCK_DUMP_STRING = "CLOCK_DUMP";
|
||||
const char *CLOCK_DUMP_LEGACY_STRING = "CLOCK_DUMP_LEGACY";
|
||||
const char *CLOCK_SET_FAILURE_STRING = "CLOCK_SET_FAILURE";
|
||||
const char *CLOCK_DUMP_STRING = "CLOCK_DUMP";
|
||||
const char *CLOCK_DUMP_BEFORE_SETTING_TIME_STRING = "CLOCK_DUMP_BEFORE_SETTING_TIME";
|
||||
const char *CLOCK_DUMP_AFTER_SETTING_TIME_STRING = "CLOCK_DUMP_AFTER_SETTING_TIME";
|
||||
const char *TC_DELETION_FAILED_STRING = "TC_DELETION_FAILED";
|
||||
const char *TEST_STRING = "TEST";
|
||||
const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
|
||||
@ -94,14 +97,17 @@ const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
|
||||
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
|
||||
const char *HANDLING_CFDP_REQUEST_FAILED_STRING = "HANDLING_CFDP_REQUEST_FAILED";
|
||||
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
||||
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||
const char *RATE_RECOVERY_STRING = "RATE_RECOVERY";
|
||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||
const char *MEKF_INVALID_INFO_STRING = "MEKF_INVALID_INFO";
|
||||
const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *PTG_CTRL_NO_ATTITUDE_INFORMATION_STRING = "PTG_CTRL_NO_ATTITUDE_INFORMATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD";
|
||||
const char *TLE_FILE_READ_FAILED_STRING = "TLE_FILE_READ_FAILED";
|
||||
const char *PTG_RATE_VIOLATION_STRING = "PTG_RATE_VIOLATION";
|
||||
const char *DETUMBLE_TRANSITION_FAILED_STRING = "DETUMBLE_TRANSITION_FAILED";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED";
|
||||
const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED";
|
||||
@ -136,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN
|
||||
const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED";
|
||||
const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON";
|
||||
const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT";
|
||||
const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE";
|
||||
const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE";
|
||||
const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE";
|
||||
const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE";
|
||||
@ -238,6 +245,7 @@ const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903_STRING = "SIDE_SWITCH_TRANS
|
||||
const char *CHILDREN_LOST_MODE_STRING = "CHILDREN_LOST_MODE";
|
||||
const char *GPS_FIX_CHANGE_STRING = "GPS_FIX_CHANGE";
|
||||
const char *CANT_GET_FIX_STRING = "CANT_GET_FIX";
|
||||
const char *RESET_FAIL_STRING = "RESET_FAIL";
|
||||
const char *P60_BOOT_COUNT_STRING = "P60_BOOT_COUNT";
|
||||
const char *BATT_MODE_STRING = "BATT_MODE";
|
||||
const char *BATT_MODE_CHANGED_STRING = "BATT_MODE_CHANGED";
|
||||
@ -480,9 +488,15 @@ const char *translateEvents(Event event) {
|
||||
case (8900):
|
||||
return CLOCK_SET_STRING;
|
||||
case (8901):
|
||||
return CLOCK_DUMP_STRING;
|
||||
return CLOCK_DUMP_LEGACY_STRING;
|
||||
case (8902):
|
||||
return CLOCK_SET_FAILURE_STRING;
|
||||
case (8903):
|
||||
return CLOCK_DUMP_STRING;
|
||||
case (8904):
|
||||
return CLOCK_DUMP_BEFORE_SETTING_TIME_STRING;
|
||||
case (8905):
|
||||
return CLOCK_DUMP_AFTER_SETTING_TIME_STRING;
|
||||
case (9100):
|
||||
return TC_DELETION_FAILED_STRING;
|
||||
case (9700):
|
||||
@ -504,7 +518,7 @@ const char *translateEvents(Event event) {
|
||||
case (11200):
|
||||
return SAFE_RATE_VIOLATION_STRING;
|
||||
case (11201):
|
||||
return SAFE_RATE_RECOVERY_STRING;
|
||||
return RATE_RECOVERY_STRING;
|
||||
case (11202):
|
||||
return MULTIPLE_RW_INVALID_STRING;
|
||||
case (11203):
|
||||
@ -514,11 +528,17 @@ const char *translateEvents(Event event) {
|
||||
case (11205):
|
||||
return MEKF_AUTOMATIC_RESET_STRING;
|
||||
case (11206):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
return PTG_CTRL_NO_ATTITUDE_INFORMATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11208):
|
||||
return TLE_TOO_OLD_STRING;
|
||||
case (11209):
|
||||
return TLE_FILE_READ_FAILED_STRING;
|
||||
case (11210):
|
||||
return PTG_RATE_VIOLATION_STRING;
|
||||
case (11211):
|
||||
return DETUMBLE_TRANSITION_FAILED_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
case (11301):
|
||||
@ -587,6 +607,8 @@ const char *translateEvents(Event event) {
|
||||
return SUPV_NOT_ON_STRING;
|
||||
case (11608):
|
||||
return SUPV_REPLY_TIMEOUT_STRING;
|
||||
case (11609):
|
||||
return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING;
|
||||
case (11701):
|
||||
return SELF_TEST_I2C_FAILURE_STRING;
|
||||
case (11702):
|
||||
@ -791,6 +813,8 @@ const char *translateEvents(Event event) {
|
||||
return GPS_FIX_CHANGE_STRING;
|
||||
case (13101):
|
||||
return CANT_GET_FIX_STRING;
|
||||
case (13102):
|
||||
return RESET_FAIL_STRING;
|
||||
case (13200):
|
||||
return P60_BOOT_COUNT_STRING;
|
||||
case (13201):
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-11-29 15:14:46
|
||||
* Contains 176 translations.
|
||||
* Generated on: 2024-05-06 13:47:38
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
@ -65,6 +65,7 @@ const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM";
|
||||
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
|
||||
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
|
||||
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
|
||||
const char *PLOC_MPSOC_COMMUNICATION_STRING = "PLOC_MPSOC_COMMUNICATION";
|
||||
const char *SCEX_STRING = "SCEX";
|
||||
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
|
||||
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
|
||||
@ -302,6 +303,8 @@ const char *translateObject(object_id_t object) {
|
||||
return PLOC_SUPERVISOR_HANDLER_STRING;
|
||||
case 0x44330017:
|
||||
return PLOC_SUPERVISOR_HELPER_STRING;
|
||||
case 0x44330018:
|
||||
return PLOC_MPSOC_COMMUNICATION_STRING;
|
||||
case 0x44330032:
|
||||
return SCEX_STRING;
|
||||
case 0x444100A2:
|
||||
|
@ -39,8 +39,6 @@
|
||||
#include "devices/gpioIds.h"
|
||||
#include "fsfw_hal/linux/gpio/Gpio.h"
|
||||
#include "linux/payload/FreshSupvHandler.h"
|
||||
#include "linux/payload/PlocMpsocHandler.h"
|
||||
#include "linux/payload/PlocMpsocSpecialComHelper.h"
|
||||
#include "linux/payload/PlocSupvUartMan.h"
|
||||
#include "test/gpio/DummyGpioIF.h"
|
||||
#endif
|
||||
@ -79,7 +77,10 @@ void ObjectFactory::produce(void* args) {
|
||||
switcherList.emplace_back(initVal);
|
||||
}
|
||||
dummySwitcher->setInitialSwitcherList(switcherList);
|
||||
|
||||
#ifdef PLATFORM_UNIX
|
||||
// Obsolete dev handler..
|
||||
/*
|
||||
new SerialComIF(objects::UART_COM_IF);
|
||||
#if OBSW_ADD_PLOC_MPSOC == 1
|
||||
std::string mpscoDev = "";
|
||||
@ -90,7 +91,8 @@ void ObjectFactory::produce(void* args) {
|
||||
new PlocMpsocHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie,
|
||||
plocMpsocHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, dummyGpioIF),
|
||||
objects::PLOC_SUPERVISOR_HANDLER);
|
||||
#endif /* OBSW_ADD_PLOC_MPSOC == 1 */
|
||||
#endif // OBSW_ADD_PLOC_MPSOC == 1
|
||||
*/
|
||||
#if OBSW_ADD_PLOC_SUPERVISOR == 1
|
||||
std::string plocSupvString = "/dev/ploc_supv";
|
||||
auto supervisorCookie =
|
||||
|
@ -480,6 +480,16 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
||||
successRecipient = commandedBy;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (UPDATE_LEAP_SECONDS): {
|
||||
if (size != sizeof(uint16_t)) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
ReturnValue_t result = actionUpdateLeapSeconds(data);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasActionsIF::EXECUTION_FINISHED;
|
||||
}
|
||||
default: {
|
||||
return HasActionsIF::INVALID_ACTION_ID;
|
||||
}
|
||||
@ -1411,6 +1421,9 @@ void CoreController::performMountedSdCardOperations() {
|
||||
if (not timeFileInitDone) {
|
||||
initClockFromTimeFile();
|
||||
}
|
||||
if (not leapSecondsInitDone) {
|
||||
initLeapSeconds();
|
||||
}
|
||||
performRebootWatchdogHandling(false);
|
||||
performRebootCountersHandling(false);
|
||||
}
|
||||
@ -2066,14 +2079,78 @@ ReturnValue_t CoreController::backupTimeFileHandler() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void CoreController::initLeapSeconds() {
|
||||
ReturnValue_t result = initLeapSecondsFromFile();
|
||||
if (result != returnvalue::OK) {
|
||||
Clock::setLeapSeconds(config::LEAP_SECONDS);
|
||||
writeLeapSecondsToFile(config::LEAP_SECONDS);
|
||||
}
|
||||
leapSecondsInitDone = true;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::initLeapSecondsFromFile() {
|
||||
std::string fileName = currMntPrefix + LEAP_SECONDS_FILE;
|
||||
std::error_code e;
|
||||
if (sdcMan->isSdCardUsable(std::nullopt) and std::filesystem::exists(fileName, e)) {
|
||||
std::ifstream leapSecondsFile(fileName);
|
||||
std::string nextWord;
|
||||
std::getline(leapSecondsFile, nextWord);
|
||||
std::istringstream iss(nextWord);
|
||||
iss >> nextWord;
|
||||
if (iss.bad() or nextWord != "LEAP") {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
iss >> nextWord;
|
||||
if (iss.bad() or nextWord != "SECONDS:") {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
iss >> nextWord;
|
||||
uint16_t leapSeconds = 0;
|
||||
leapSeconds = std::stoi(nextWord.c_str());
|
||||
if (iss.bad()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
Clock::setLeapSeconds(leapSeconds);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
sif::error
|
||||
<< "CoreController::leapSecondsFileHandler: Initalization of leap seconds from file failed"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
};
|
||||
|
||||
ReturnValue_t CoreController::writeLeapSecondsToFile(const uint16_t leapSeconds) {
|
||||
std::string fileName = currMntPrefix + LEAP_SECONDS_FILE;
|
||||
if (not sdcMan->isSdCardUsable(std::nullopt)) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
std::ofstream leapSecondsFile(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
if (not leapSecondsFile.good()) {
|
||||
sif::error << "CoreController::leapSecondsFileHandler: Error opening leap seconds file: "
|
||||
<< strerror(errno) << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
leapSecondsFile << "LEAP SECONDS: " << leapSeconds << std::endl;
|
||||
return returnvalue::OK;
|
||||
};
|
||||
|
||||
ReturnValue_t CoreController::actionUpdateLeapSeconds(const uint8_t *data) {
|
||||
uint16_t leapSeconds = data[1] | (data[0] << 8);
|
||||
ReturnValue_t result = writeLeapSecondsToFile(leapSeconds);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
Clock::setLeapSeconds(leapSeconds);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::initClockFromTimeFile() {
|
||||
using namespace GpsHyperion;
|
||||
using namespace std;
|
||||
std::string fileName = currMntPrefix + BACKUP_TIME_FILE;
|
||||
std::error_code e;
|
||||
if (sdcMan->isSdCardUsable(std::nullopt) and std::filesystem::exists(fileName, e) and
|
||||
((gpsFix == FixMode::UNKNOWN or gpsFix == FixMode::NOT_SEEN) or
|
||||
not utility::timeSanityCheck())) {
|
||||
((gpsFix == FixMode::NOT_SEEN) or not utility::timeSanityCheck())) {
|
||||
ifstream timeFile(fileName);
|
||||
string nextWord;
|
||||
getline(timeFile, nextWord);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
||||
#include <fsfw_hal/linux/uio/UioMapper.h>
|
||||
#include <libxiphos.h>
|
||||
#include <mission/acs/archive/GPSDefinitions.h>
|
||||
#include <linux/acs/GPSDefinitions.h>
|
||||
#include <mission/utility/trace.h>
|
||||
|
||||
#include <atomic>
|
||||
@ -150,6 +150,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
std::string(core::LEGACY_REBOOT_WATCHDOG_FILE_NAME);
|
||||
const std::string REBOOT_WATCHDOG_FILE =
|
||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_WATCHDOG_FILE_NAME);
|
||||
const std::string LEAP_SECONDS_FILE =
|
||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::LEAP_SECONDS_FILE_NAME);
|
||||
const std::string BACKUP_TIME_FILE =
|
||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME);
|
||||
const std::string REBOOT_COUNTERS_FILE =
|
||||
@ -209,7 +211,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
static constexpr MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
|
||||
static constexpr uint32_t MUTEX_TIMEOUT = 20;
|
||||
bool enableHkSet = false;
|
||||
GpsHyperion::FixMode gpsFix = GpsHyperion::FixMode::UNKNOWN;
|
||||
GpsHyperion::FixMode gpsFix = GpsHyperion::FixMode::NOT_SEEN;
|
||||
|
||||
// States for SD state machine, which is used in non-blocking mode
|
||||
enum class SdStates {
|
||||
@ -296,6 +298,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
|
||||
std::string currMntPrefix;
|
||||
bool timeFileInitDone = false;
|
||||
bool leapSecondsInitDone = false;
|
||||
bool performOneShotSdCardOpsSwitch = false;
|
||||
uint8_t shortSdCardCdCounter = 0;
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
@ -335,7 +338,11 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
void performMountedSdCardOperations();
|
||||
ReturnValue_t initVersionFile();
|
||||
|
||||
void initLeapSeconds();
|
||||
ReturnValue_t initLeapSecondsFromFile();
|
||||
ReturnValue_t initClockFromTimeFile();
|
||||
ReturnValue_t actionUpdateLeapSeconds(const uint8_t* data);
|
||||
ReturnValue_t writeLeapSecondsToFile(const uint16_t leapSeconds);
|
||||
ReturnValue_t performSdCardCheck();
|
||||
ReturnValue_t backupTimeFileHandler();
|
||||
ReturnValue_t initBootCopyFile();
|
||||
|
@ -175,7 +175,7 @@ void ObjectFactory::produce(void* args) {
|
||||
createScexComponents(q7s::UART_SCEX_DEV, pwrSwitcher, *SdCardManager::instance(), false,
|
||||
power::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V);
|
||||
#endif
|
||||
createAcsController(true, enableHkSets);
|
||||
createAcsController(true, enableHkSets, *SdCardManager::instance());
|
||||
HeaterHandler* heaterHandler;
|
||||
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
|
||||
createThermalController(*heaterHandler, true);
|
||||
|
@ -130,6 +130,6 @@ void ObjectFactory::produce(void* args) {
|
||||
|
||||
createMiscComponents();
|
||||
createThermalController(*heaterHandler, false);
|
||||
createAcsController(true, enableHkSets);
|
||||
createAcsController(true, enableHkSets, *SdCardManager::instance());
|
||||
satsystem::init(false);
|
||||
}
|
||||
|
@ -10,8 +10,9 @@
|
||||
#include <linux/acs/RwPollingTask.h>
|
||||
#include <linux/acs/StrComHandler.h>
|
||||
#include <linux/com/SyrlinksComHandler.h>
|
||||
#include <linux/payload/FreshMpsocHandler.h>
|
||||
#include <linux/payload/MpsocCommunication.h>
|
||||
#include <linux/payload/PlocMemoryDumper.h>
|
||||
#include <linux/payload/PlocMpsocHandler.h>
|
||||
#include <linux/payload/PlocMpsocSpecialComHelper.h>
|
||||
#include <linux/payload/ScexUartReader.h>
|
||||
#include <linux/payload/plocMpsocHelpers.h>
|
||||
@ -47,6 +48,7 @@
|
||||
#include "devices/gpioIds.h"
|
||||
#include "devices/powerSwitcherList.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "eive/objects.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "linux/ObjectFactory.h"
|
||||
#include "linux/boardtest/I2cTestClass.h"
|
||||
@ -59,7 +61,11 @@
|
||||
#include "linux/ipcore/Ptme.h"
|
||||
#include "linux/ipcore/PtmeConfig.h"
|
||||
#include "linux/payload/FreshSupvHandler.h"
|
||||
#include "linux/payload/MpsocCommunication.h"
|
||||
#include "linux/payload/PlocMpsocSpecialComHelper.h"
|
||||
#include "linux/payload/SerialConfig.h"
|
||||
#include "mission/config/configfile.h"
|
||||
#include "mission/power/defs.h"
|
||||
#include "mission/system/acs/AcsBoardFdir.h"
|
||||
#include "mission/system/acs/AcsSubsystem.h"
|
||||
#include "mission/system/acs/RwAssembly.h"
|
||||
@ -67,7 +73,7 @@
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/com/SyrlinksFdir.h"
|
||||
#include "mission/system/com/comModeTree.h"
|
||||
#include "mission/system/payloadModeTree.h"
|
||||
#include "mission/system/payload/payloadModeTree.h"
|
||||
#include "mission/system/power/GomspacePowerFdir.h"
|
||||
#include "mission/system/tcs/RtdFdir.h"
|
||||
#include "mission/system/tcs/TcsBoardAssembly.h"
|
||||
@ -510,7 +516,7 @@ void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF*
|
||||
debugGps = true;
|
||||
#endif
|
||||
RESET_ARGS_GNSS.gpioComIF = gpioComIF;
|
||||
RESET_ARGS_GNSS.waitPeriodMs = 5;
|
||||
RESET_ARGS_GNSS.waitPeriodMs = 10 * 1e3;
|
||||
auto gpsCtrl = new GpsHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT,
|
||||
enableHkSets, debugGps);
|
||||
gpsCtrl->setResetPinTriggerFunction(gps::triggerGpioResetPin, &RESET_ARGS_GNSS);
|
||||
@ -624,14 +630,15 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit
|
||||
auto mpsocGpioCookie = new GpioCookie;
|
||||
mpsocGpioCookie->addGpio(gpioIds::ENABLE_MPSOC_UART, gpioConfigMPSoC);
|
||||
gpioChecker(gpioComIF->addGpios(mpsocGpioCookie), "PLOC MPSoC");
|
||||
auto mpsocCookie =
|
||||
new SerialCookie(objects::PLOC_MPSOC_HANDLER, q7s::UART_PLOC_MPSOC_DEV,
|
||||
serial::PLOC_MPSOC_BAUD, mpsoc::MAX_REPLY_SIZE, UartModes::NON_CANONICAL);
|
||||
mpsocCookie->setNoFixedSizeReply();
|
||||
auto plocMpsocHelper = new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER);
|
||||
auto* mpsocHandler = new PlocMpsocHandler(
|
||||
objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie, plocMpsocHelper,
|
||||
Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF), objects::PLOC_SUPERVISOR_HANDLER);
|
||||
SerialConfig serialCfg(q7s::UART_PLOC_MPSOC_DEV, serial::PLOC_MPSOC_BAUD, mpsoc::MAX_REPLY_SIZE,
|
||||
UartModes::NON_CANONICAL);
|
||||
auto mpsocCommunication = new MpsocCommunication(objects::PLOC_MPSOC_COMMUNICATION, serialCfg);
|
||||
auto specialComHelper =
|
||||
new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER, *mpsocCommunication);
|
||||
DhbConfig dhbConf(objects::PLOC_MPSOC_HANDLER);
|
||||
auto* mpsocHandler = new FreshMpsocHandler(
|
||||
dhbConf, *mpsocCommunication, *specialComHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF),
|
||||
objects::PLOC_SUPERVISOR_HANDLER, pwrSwitcher, power::PDU2_CH8_PAYLOAD_CAMERA);
|
||||
mpsocHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
#endif /* OBSW_ADD_PLOC_MPSOC == 1 */
|
||||
#if OBSW_ADD_PLOC_SUPERVISOR == 1
|
||||
@ -650,7 +657,7 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit
|
||||
supv::MAX_PACKET_SIZE * 20, UartModes::NON_CANONICAL);
|
||||
supervisorCookie->setNoFixedSizeReply();
|
||||
new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER);
|
||||
DhbConfig dhbConf(objects::PLOC_SUPERVISOR_HANDLER);
|
||||
dhbConf = DhbConfig(objects::PLOC_SUPERVISOR_HANDLER);
|
||||
auto* supvHandler =
|
||||
new FreshSupvHandler(dhbConf, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF),
|
||||
pwrSwitcher, power::PDU1_CH6_PLOC_12V);
|
||||
@ -951,7 +958,7 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher, SdCardManage
|
||||
auto cfgGetter = new StrConfigPathGetter(sdcMan);
|
||||
auto starTracker =
|
||||
new StarTrackerHandler(objects::STAR_TRACKER, objects::STR_COM_IF, starTrackerCookie,
|
||||
strComIF, power::PDU1_CH2_STAR_TRACKER_5V, *cfgGetter);
|
||||
strComIF, power::PDU1_CH2_STAR_TRACKER_5V, *cfgGetter, sdcMan);
|
||||
starTracker->setPowerSwitcher(pwrSwitcher);
|
||||
starTracker->connectModeTreeParent(*strAssy);
|
||||
starTracker->setCustomFdir(strFdir);
|
||||
|
@ -20,6 +20,9 @@ static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_vers
|
||||
// ISO8601 timestamp.
|
||||
static constexpr char FILE_DATE_FORMAT[] = "%FT%H%M%SZ";
|
||||
|
||||
// Leap Seconds as of 2024-03-04
|
||||
static constexpr uint16_t LEAP_SECONDS = 37;
|
||||
|
||||
static constexpr uint16_t EIVE_PUS_APID = 0x65;
|
||||
static constexpr uint16_t EIVE_CFDP_APID = 0x66;
|
||||
static constexpr uint16_t EIVE_LOCAL_CFDP_ENTITY_ID = EIVE_CFDP_APID;
|
||||
|
@ -77,6 +77,7 @@ enum commonObjects : uint32_t {
|
||||
PLOC_MPSOC_HANDLER = 0x44330015,
|
||||
PLOC_SUPERVISOR_HANDLER = 0x44330016,
|
||||
PLOC_SUPERVISOR_HELPER = 0x44330017,
|
||||
PLOC_MPSOC_COMMUNICATION = 0x44330018,
|
||||
SCEX = 0x44330032,
|
||||
SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2,
|
||||
HEATER_HANDLER = 0x444100A4,
|
||||
|
@ -42,6 +42,7 @@ enum commonClassIds : uint8_t {
|
||||
PERSISTENT_TM_STORE, // PTM
|
||||
TM_SINK, // TMS
|
||||
VIRTUAL_CHANNEL, // VCS
|
||||
PLOC_MPSOC_COM, // PLMPCOM
|
||||
COMMON_CLASS_ID_END // [EXPORT] : [END]
|
||||
};
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define DUMMIES_GPSCTRLDUMMY_H_
|
||||
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
#include <mission/acs/archive/GPSDefinitions.h>
|
||||
#include <linux/acs/GPSDefinitions.h>
|
||||
|
||||
class GpsCtrlDummy : public ExtendedControllerBase {
|
||||
public:
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <dummies/GpsDhbDummy.h>
|
||||
#include <mission/acs/archive/GPSDefinitions.h>
|
||||
#include <linux/acs/GPSDefinitions.h>
|
||||
|
||||
GpsDhbDummy::GpsDhbDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie) {}
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "mission/genericFactory.h"
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/com/comModeTree.h"
|
||||
#include "mission/system/payloadModeTree.h"
|
||||
#include "mission/system/payload/payloadModeTree.h"
|
||||
#include "mission/system/tcs/tcsModeTree.h"
|
||||
#include "mission/tcs/defs.h"
|
||||
|
||||
|
2
fsfw
2
fsfw
@ -1 +1 @@
|
||||
Subproject commit b28174db249cb33b541f665270fd6af14c382351
|
||||
Subproject commit 42867ad0cba088ab1cb6cb672d001f991f7e4a60
|
@ -75,9 +75,12 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
7902;0x1ede;BIT_LOCK;INFO;A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0;fsfw/src/fsfw/datalinklayer/DataLinkLayer.h
|
||||
7903;0x1edf;BIT_LOCK_LOST;INFO;A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0;fsfw/src/fsfw/datalinklayer/DataLinkLayer.h
|
||||
7905;0x1ee1;FRAME_PROCESSING_FAILED;LOW;The CCSDS Board could not interpret a TC;fsfw/src/fsfw/datalinklayer/DataLinkLayer.h
|
||||
8900;0x22c4;CLOCK_SET;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8901;0x22c5;CLOCK_DUMP;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8902;0x22c6;CLOCK_SET_FAILURE;LOW;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8900;0x22c4;CLOCK_SET;INFO;Clock has been set. P1: old timeval seconds. P2: new timeval seconds.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8901;0x22c5;CLOCK_DUMP_LEGACY;INFO;Clock dump event. P1: timeval seconds P2: timeval milliseconds.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8902;0x22c6;CLOCK_SET_FAILURE;LOW;Clock could not be set. P1: Returncode.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8903;0x22c7;CLOCK_DUMP;INFO;Clock dump event. P1: timeval seconds P2: timeval microseconds.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8904;0x22c8;CLOCK_DUMP_BEFORE_SETTING_TIME;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8905;0x22c9;CLOCK_DUMP_AFTER_SETTING_TIME;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
9100;0x238c;TC_DELETION_FAILED;MEDIUM;Deletion of a TC from the map failed. P1: First 32 bit of request ID, P2. Last 32 bit of Request ID;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
9700;0x25e4;TEST;INFO;No description;fsfw/src/fsfw/pus/Service17Test.h
|
||||
10600;0x2968;CHANGE_OF_SETUP_PARAMETER;LOW;No description;fsfw/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h
|
||||
@ -88,14 +91,17 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
10805;0x2a35;HANDLING_CFDP_REQUEST_FAILED;LOW;CFDP request handling failed. P2: Returncode.;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;The limits for the rotation in safe mode were violated.;mission/acs/defs.h
|
||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;The system has recovered from a safe rate rotation violation.;mission/acs/defs.h
|
||||
11201;0x2bc1;RATE_RECOVERY;MEDIUM;The system has recovered from a rate rotation violation.;mission/acs/defs.h
|
||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;Multiple RWs are invalid, uncommandable and therefore higher ACS modes cannot be maintained.;mission/acs/defs.h
|
||||
11203;0x2bc3;MEKF_INVALID_INFO;INFO;MEKF was not able to compute a solution. P1: MEKF state on exit;mission/acs/defs.h
|
||||
11204;0x2bc4;MEKF_RECOVERY;INFO;MEKF is able to compute a solution again.;mission/acs/defs.h
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11206;0x2bc6;PTG_CTRL_NO_ATTITUDE_INFORMATION;HIGH;For a prolonged time, no attitude information was available for the Pointing Controller. Falling back to Safe Mode.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h
|
||||
11209;0x2bc9;TLE_FILE_READ_FAILED;LOW;The TLE could not be read from the filesystem.;mission/acs/defs.h
|
||||
11210;0x2bca;PTG_RATE_VIOLATION;MEDIUM;The limits for the rotation in pointing mode were violated.;mission/acs/defs.h
|
||||
11211;0x2bcb;DETUMBLE_TRANSITION_FAILED;HIGH;The detumble transition has failed. //! P1: Last detumble state before failure.;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
@ -122,14 +128,15 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11506;0x2cf2;DEPL_SA1_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h
|
||||
11507;0x2cf3;DEPL_SA2_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h
|
||||
11508;0x2cf4;AUTONOMOUS_DEPLOYMENT_COMPLETED;INFO;No description;mission/SolarArrayDeploymentHandler.h
|
||||
11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/PlocMpsocHandler.h
|
||||
11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h
|
||||
11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h
|
||||
11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/PlocMpsocHandler.h
|
||||
11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocHandler.h
|
||||
11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/PlocMpsocHandler.h
|
||||
11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/PlocMpsocHandler.h
|
||||
11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/PlocMpsocHandler.h
|
||||
11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/plocMpsocHelpers.h
|
||||
11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h
|
||||
11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h
|
||||
11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/plocMpsocHelpers.h
|
||||
11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h
|
||||
11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h
|
||||
11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h
|
||||
11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;SUPV reply timeout.;linux/payload/plocMpsocHelpers.h
|
||||
11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h
|
||||
11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
@ -230,8 +237,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12902;0x3266;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/SusAssembly.h
|
||||
12903;0x3267;SIDE_SWITCH_TRANSITION_NOT_ALLOWED;LOW;Not implemented, would increase already high complexity. Operator should instead command the assembly off first and then command the assembly on into the desired mode/submode combination;mission/system/acs/SusAssembly.h
|
||||
13000;0x32c8;CHILDREN_LOST_MODE;MEDIUM;No description;mission/system/tcs/TcsBoardAssembly.h
|
||||
13100;0x332c;GPS_FIX_CHANGE;INFO;Fix has changed. P1: Old fix. P2: New fix 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix;mission/acs/archive/GPSDefinitions.h
|
||||
13101;0x332d;CANT_GET_FIX;LOW;Could not get fix in maximum allowed time. P1: Maximum allowed time to get a fix after the GPS was switched on.;mission/acs/archive/GPSDefinitions.h
|
||||
13100;0x332c;GPS_FIX_CHANGE;INFO;Fix has changed. P1: New fix. P2: Missed fix changes 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix;linux/acs/GPSDefinitions.h
|
||||
13101;0x332d;CANT_GET_FIX;MEDIUM;Could not get fix in maximum allowed time. Trying to reset both GNSS devices. P1: Maximum allowed time to get a fix after the GPS was switched on.;linux/acs/GPSDefinitions.h
|
||||
13102;0x332e;RESET_FAIL;HIGH;Failed to reset an GNNS Device. P1: Board-Side.;linux/acs/GPSDefinitions.h
|
||||
13200;0x3390;P60_BOOT_COUNT;INFO;P60 boot count is broadcasted once at SW startup. P1: Boot count;mission/power/P60DockHandler.h
|
||||
13201;0x3391;BATT_MODE;INFO;Battery mode is broadcasted at startup. P1: Mode;mission/power/P60DockHandler.h
|
||||
13202;0x3392;BATT_MODE_CHANGED;MEDIUM;Battery mode has changed. P1: Old mode. P2: New mode;mission/power/P60DockHandler.h
|
||||
|
|
@ -57,6 +57,7 @@
|
||||
0x44330015;PLOC_MPSOC_HANDLER
|
||||
0x44330016;PLOC_SUPERVISOR_HANDLER
|
||||
0x44330017;PLOC_SUPERVISOR_HELPER
|
||||
0x44330018;PLOC_MPSOC_COMMUNICATION
|
||||
0x44330032;SCEX
|
||||
0x444100A2;SOLAR_ARRAY_DEPL_HANDLER
|
||||
0x444100A4;HEATER_HANDLER
|
||||
|
|
@ -387,6 +387,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x4304;PUS11_InvalidRelativeTime;No description;4;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4305;PUS11_ContainedTcTooSmall;No description;5;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4306;PUS11_ContainedTcCrcMissmatch;No description;6;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4307;PUS11_MapIsFull;No description;7;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4400;FILS_GenericFileError;No description;0;FILE_SYSTEM;fsfw/src/fsfw/filesystem/HasFileSystemIF.h
|
||||
0x4401;FILS_GenericDirError;No description;1;FILE_SYSTEM;fsfw/src/fsfw/filesystem/HasFileSystemIF.h
|
||||
0x4402;FILS_FilesystemInactive;No description;2;FILE_SYSTEM;fsfw/src/fsfw/filesystem/HasFileSystemIF.h
|
||||
@ -453,6 +454,12 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x5208;IMTQ_CmdErrUnknown;No description;8;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5209;IMTQ_StartupCfgError;No description;9;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x520a;IMTQ_UnexpectedSelfTestReply;The status reply to a self test command was received but no self test command has been sent. This should normally never happen.;10;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x53a0;RWHA_InvalidSpeed;Action Message with invalid speed was received. Valid speeds must be in the range of [-65000, 1000] or [1000, 65000];160;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a1;RWHA_InvalidRampTime;Action Message with invalid ramp time was received.;161;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a2;RWHA_SetSpeedCommandInvalidLength;Received set speed command has invalid length. Should be 6.;162;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a3;RWHA_ExecutionFailed;Command execution failed;163;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a4;RWHA_CrcError;Reaction wheel reply has invalid crc;164;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a5;RWHA_ValueNotRead;No description;165;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53b0;RWHA_SpiWriteFailure;No description;176;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x53b1;RWHA_SpiReadFailure;Used by the spi send function to tell a failing read call;177;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x53b2;RWHA_MissingStartSign;Can be used by the HDLC decoding mechanism to inform about a missing start sign 0x7E;178;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
@ -486,12 +493,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x54b6;STRH_StartrackerAlreadyBooted;Star tracker is already in firmware mode;182;STR_HANDLER;mission/acs/str/StarTrackerHandler.h
|
||||
0x54b7;STRH_StartrackerNotRunningFirmware;Star tracker must be in firmware mode to run this command;183;STR_HANDLER;mission/acs/str/StarTrackerHandler.h
|
||||
0x54b8;STRH_StartrackerNotRunningBootloader;Star tracker must be in bootloader mode to run this command;184;STR_HANDLER;mission/acs/str/StarTrackerHandler.h
|
||||
0x59a0;SUSS_InvalidSpeed;Action Message with invalid speed was received. Valid speeds must be in the range of [-65000, 1000] or [1000, 65000];160;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a1;SUSS_InvalidRampTime;Action Message with invalid ramp time was received.;161;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a2;SUSS_SetSpeedCommandInvalidLength;Received set speed command has invalid length. Should be 6.;162;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a3;SUSS_ExecutionFailed;Command execution failed;163;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a4;SUSS_CrcError;Reaction wheel reply has invalid crc;164;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a5;SUSS_ValueNotRead;No description;165;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a0;SUSS_ErrorUnlockMutex;No description;160;SUS_HANDLER;mission/acs/archive/LegacySusHandler.h
|
||||
0x59a1;SUSS_ErrorLockMutex;No description;161;SUS_HANDLER;mission/acs/archive/LegacySusHandler.h
|
||||
0x5e00;GOMS_PacketTooLong;No description;0;GOM_SPACE_HANDLER;mission/power/GomspaceDeviceHandler.h
|
||||
0x5e01;GOMS_InvalidTableId;No description;1;GOM_SPACE_HANDLER;mission/power/GomspaceDeviceHandler.h
|
||||
0x5e02;GOMS_InvalidAddress;No description;2;GOM_SPACE_HANDLER;mission/power/GomspaceDeviceHandler.h
|
||||
@ -508,7 +511,11 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x67a2;SADPL_MainSwitchTimeoutFailure;No description;162;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x67a3;SADPL_SwitchingDeplSa1Failed;No description;163;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x67a4;SADPL_SwitchingDeplSa2Failed;No description;164;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x6a00;ACSCTRL_FileDeletionFailed;File deletion failed and at least one file is still existent.;0;ACS_CTRL;mission/controller/AcsController.h
|
||||
0x6aa0;ACSCTRL_FileDeletionFailed;File deletion failed and at least one file is still existent.;160;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa1;ACSCTRL_WriteFileFailed;Writing the TLE to the file has failed.;161;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa2;ACSCTRL_ReadFileFailed;Reading the TLE to the file has failed.;162;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa3;ACSCTRL_SingleRwUnavailable;A single RW has failed.;163;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa4;ACSCTRL_MultipleRwUnavailable;Multiple RWs have failed.;164;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6b02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6b03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6b04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
|
|
@ -75,9 +75,12 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
7902;0x1ede;BIT_LOCK;INFO;A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0;fsfw/src/fsfw/datalinklayer/DataLinkLayer.h
|
||||
7903;0x1edf;BIT_LOCK_LOST;INFO;A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0;fsfw/src/fsfw/datalinklayer/DataLinkLayer.h
|
||||
7905;0x1ee1;FRAME_PROCESSING_FAILED;LOW;The CCSDS Board could not interpret a TC;fsfw/src/fsfw/datalinklayer/DataLinkLayer.h
|
||||
8900;0x22c4;CLOCK_SET;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8901;0x22c5;CLOCK_DUMP;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8902;0x22c6;CLOCK_SET_FAILURE;LOW;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8900;0x22c4;CLOCK_SET;INFO;Clock has been set. P1: old timeval seconds. P2: new timeval seconds.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8901;0x22c5;CLOCK_DUMP_LEGACY;INFO;Clock dump event. P1: timeval seconds P2: timeval milliseconds.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8902;0x22c6;CLOCK_SET_FAILURE;LOW;Clock could not be set. P1: Returncode.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8903;0x22c7;CLOCK_DUMP;INFO;Clock dump event. P1: timeval seconds P2: timeval microseconds.;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8904;0x22c8;CLOCK_DUMP_BEFORE_SETTING_TIME;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
8905;0x22c9;CLOCK_DUMP_AFTER_SETTING_TIME;INFO;No description;fsfw/src/fsfw/pus/Service9TimeManagement.h
|
||||
9100;0x238c;TC_DELETION_FAILED;MEDIUM;Deletion of a TC from the map failed. P1: First 32 bit of request ID, P2. Last 32 bit of Request ID;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
9700;0x25e4;TEST;INFO;No description;fsfw/src/fsfw/pus/Service17Test.h
|
||||
10600;0x2968;CHANGE_OF_SETUP_PARAMETER;LOW;No description;fsfw/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h
|
||||
@ -88,14 +91,17 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
10805;0x2a35;HANDLING_CFDP_REQUEST_FAILED;LOW;CFDP request handling failed. P2: Returncode.;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;The limits for the rotation in safe mode were violated.;mission/acs/defs.h
|
||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;The system has recovered from a safe rate rotation violation.;mission/acs/defs.h
|
||||
11201;0x2bc1;RATE_RECOVERY;MEDIUM;The system has recovered from a rate rotation violation.;mission/acs/defs.h
|
||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;Multiple RWs are invalid, uncommandable and therefore higher ACS modes cannot be maintained.;mission/acs/defs.h
|
||||
11203;0x2bc3;MEKF_INVALID_INFO;INFO;MEKF was not able to compute a solution. P1: MEKF state on exit;mission/acs/defs.h
|
||||
11204;0x2bc4;MEKF_RECOVERY;INFO;MEKF is able to compute a solution again.;mission/acs/defs.h
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11206;0x2bc6;PTG_CTRL_NO_ATTITUDE_INFORMATION;HIGH;For a prolonged time, no attitude information was available for the Pointing Controller. Falling back to Safe Mode.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h
|
||||
11209;0x2bc9;TLE_FILE_READ_FAILED;LOW;The TLE could not be read from the filesystem.;mission/acs/defs.h
|
||||
11210;0x2bca;PTG_RATE_VIOLATION;MEDIUM;The limits for the rotation in pointing mode were violated.;mission/acs/defs.h
|
||||
11211;0x2bcb;DETUMBLE_TRANSITION_FAILED;HIGH;The detumble transition has failed. //! P1: Last detumble state before failure.;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
@ -122,14 +128,15 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11506;0x2cf2;DEPL_SA1_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h
|
||||
11507;0x2cf3;DEPL_SA2_GPIO_SWTICH_OFF_FAILED;HIGH;No description;mission/SolarArrayDeploymentHandler.h
|
||||
11508;0x2cf4;AUTONOMOUS_DEPLOYMENT_COMPLETED;INFO;No description;mission/SolarArrayDeploymentHandler.h
|
||||
11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/PlocMpsocHandler.h
|
||||
11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h
|
||||
11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/PlocMpsocHandler.h
|
||||
11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/PlocMpsocHandler.h
|
||||
11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocHandler.h
|
||||
11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/PlocMpsocHandler.h
|
||||
11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/PlocMpsocHandler.h
|
||||
11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/PlocMpsocHandler.h
|
||||
11601;0x2d51;MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC crc failure in telemetry packet;linux/payload/plocMpsocHelpers.h
|
||||
11602;0x2d52;ACK_FAILURE;LOW;PLOC receive acknowledgment failure report P1: Command Id which leads the acknowledgment failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h
|
||||
11603;0x2d53;EXE_FAILURE;LOW;PLOC receive execution failure report P1: Command Id which leads the execution failure report P2: The status field inserted by the MPSoC into the data field;linux/payload/plocMpsocHelpers.h
|
||||
11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/plocMpsocHelpers.h
|
||||
11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h
|
||||
11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h
|
||||
11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h
|
||||
11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;SUPV reply timeout.;linux/payload/plocMpsocHelpers.h
|
||||
11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h
|
||||
11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
@ -230,8 +237,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12902;0x3266;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/SusAssembly.h
|
||||
12903;0x3267;SIDE_SWITCH_TRANSITION_NOT_ALLOWED;LOW;Not implemented, would increase already high complexity. Operator should instead command the assembly off first and then command the assembly on into the desired mode/submode combination;mission/system/acs/SusAssembly.h
|
||||
13000;0x32c8;CHILDREN_LOST_MODE;MEDIUM;No description;mission/system/tcs/TcsBoardAssembly.h
|
||||
13100;0x332c;GPS_FIX_CHANGE;INFO;Fix has changed. P1: Old fix. P2: New fix 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix;mission/acs/archive/GPSDefinitions.h
|
||||
13101;0x332d;CANT_GET_FIX;LOW;Could not get fix in maximum allowed time. P1: Maximum allowed time to get a fix after the GPS was switched on.;mission/acs/archive/GPSDefinitions.h
|
||||
13100;0x332c;GPS_FIX_CHANGE;INFO;Fix has changed. P1: New fix. P2: Missed fix changes 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix;linux/acs/GPSDefinitions.h
|
||||
13101;0x332d;CANT_GET_FIX;MEDIUM;Could not get fix in maximum allowed time. Trying to reset both GNSS devices. P1: Maximum allowed time to get a fix after the GPS was switched on.;linux/acs/GPSDefinitions.h
|
||||
13102;0x332e;RESET_FAIL;HIGH;Failed to reset an GNNS Device. P1: Board-Side.;linux/acs/GPSDefinitions.h
|
||||
13200;0x3390;P60_BOOT_COUNT;INFO;P60 boot count is broadcasted once at SW startup. P1: Boot count;mission/power/P60DockHandler.h
|
||||
13201;0x3391;BATT_MODE;INFO;Battery mode is broadcasted at startup. P1: Mode;mission/power/P60DockHandler.h
|
||||
13202;0x3392;BATT_MODE_CHANGED;MEDIUM;Battery mode has changed. P1: Old mode. P2: New mode;mission/power/P60DockHandler.h
|
||||
|
|
@ -56,6 +56,7 @@
|
||||
0x44330015;PLOC_MPSOC_HANDLER
|
||||
0x44330016;PLOC_SUPERVISOR_HANDLER
|
||||
0x44330017;PLOC_SUPERVISOR_HELPER
|
||||
0x44330018;PLOC_MPSOC_COMMUNICATION
|
||||
0x44330032;SCEX
|
||||
0x444100A2;SOLAR_ARRAY_DEPL_HANDLER
|
||||
0x444100A4;HEATER_HANDLER
|
||||
|
|
@ -387,6 +387,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x4304;PUS11_InvalidRelativeTime;No description;4;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4305;PUS11_ContainedTcTooSmall;No description;5;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4306;PUS11_ContainedTcCrcMissmatch;No description;6;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4307;PUS11_MapIsFull;No description;7;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
|
||||
0x4400;FILS_GenericFileError;No description;0;FILE_SYSTEM;fsfw/src/fsfw/filesystem/HasFileSystemIF.h
|
||||
0x4401;FILS_GenericDirError;No description;1;FILE_SYSTEM;fsfw/src/fsfw/filesystem/HasFileSystemIF.h
|
||||
0x4402;FILS_FilesystemInactive;No description;2;FILE_SYSTEM;fsfw/src/fsfw/filesystem/HasFileSystemIF.h
|
||||
@ -453,6 +454,12 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x5208;IMTQ_CmdErrUnknown;No description;8;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5209;IMTQ_StartupCfgError;No description;9;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x520a;IMTQ_UnexpectedSelfTestReply;The status reply to a self test command was received but no self test command has been sent. This should normally never happen.;10;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x53a0;RWHA_InvalidSpeed;Action Message with invalid speed was received. Valid speeds must be in the range of [-65000, 1000] or [1000, 65000];160;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a1;RWHA_InvalidRampTime;Action Message with invalid ramp time was received.;161;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a2;RWHA_SetSpeedCommandInvalidLength;Received set speed command has invalid length. Should be 6.;162;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a3;RWHA_ExecutionFailed;Command execution failed;163;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a4;RWHA_CrcError;Reaction wheel reply has invalid crc;164;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53a5;RWHA_ValueNotRead;No description;165;RW_HANDLER;mission/acs/RwHandler.h
|
||||
0x53b0;RWHA_SpiWriteFailure;No description;176;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x53b1;RWHA_SpiReadFailure;Used by the spi send function to tell a failing read call;177;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x53b2;RWHA_MissingStartSign;Can be used by the HDLC decoding mechanism to inform about a missing start sign 0x7E;178;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
@ -498,12 +505,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x58a1;PLSPVhLP_ProcessTerminated;Process has been terminated by command;161;PLOC_SUPV_HELPER;linux/payload/PlocSupvUartMan.h
|
||||
0x58a2;PLSPVhLP_PathNotExists;Received command with invalid pathname;162;PLOC_SUPV_HELPER;linux/payload/PlocSupvUartMan.h
|
||||
0x58a3;PLSPVhLP_EventBufferReplyInvalidApid;Expected event buffer TM but received space packet with other APID;163;PLOC_SUPV_HELPER;linux/payload/PlocSupvUartMan.h
|
||||
0x59a0;SUSS_InvalidSpeed;Action Message with invalid speed was received. Valid speeds must be in the range of [-65000, 1000] or [1000, 65000];160;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a1;SUSS_InvalidRampTime;Action Message with invalid ramp time was received.;161;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a2;SUSS_SetSpeedCommandInvalidLength;Received set speed command has invalid length. Should be 6.;162;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a3;SUSS_ExecutionFailed;Command execution failed;163;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a4;SUSS_CrcError;Reaction wheel reply has invalid crc;164;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a5;SUSS_ValueNotRead;No description;165;SUS_HANDLER;mission/acs/RwHandler.h
|
||||
0x59a0;SUSS_ErrorUnlockMutex;No description;160;SUS_HANDLER;mission/acs/archive/LegacySusHandler.h
|
||||
0x59a1;SUSS_ErrorLockMutex;No description;161;SUS_HANDLER;mission/acs/archive/LegacySusHandler.h
|
||||
0x5aa0;IPCI_PapbBusy;No description;160;CCSDS_IP_CORE_BRIDGE;linux/ipcore/PapbVcInterface.h
|
||||
0x5ba0;PTME_UnknownVcId;No description;160;PTME;linux/ipcore/Ptme.h
|
||||
0x5d01;STRHLP_SdNotMounted;SD card specified in path string not mounted;1;STR_HELPER;linux/acs/StrComHandler.h
|
||||
@ -558,16 +561,17 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x67a2;SADPL_MainSwitchTimeoutFailure;No description;162;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x67a3;SADPL_SwitchingDeplSa1Failed;No description;163;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x67a4;SADPL_SwitchingDeplSa2Failed;No description;164;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x68a0;MPSOCRTVIF_CrcFailure;Space Packet received from PLOC has invalid CRC;160;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a1;MPSOCRTVIF_ReceivedAckFailure;Received ACK failure reply from PLOC;161;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a2;MPSOCRTVIF_ReceivedExeFailure;Received execution failure reply from PLOC;162;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a3;MPSOCRTVIF_InvalidApid;Received space packet with invalid APID from PLOC;163;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a4;MPSOCRTVIF_InvalidLength;Received command with invalid length;164;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a5;MPSOCRTVIF_FilenameTooLong;Filename of file in OBC filesystem is too long;165;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a6;MPSOCRTVIF_MpsocHelperExecuting;MPSoC helper is currently executing a command;166;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a7;MPSOCRTVIF_MpsocFilenameTooLong;Filename of MPSoC file is to long (max. 256 bytes);167;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a8;MPSOCRTVIF_InvalidParameter;Command has invalid parameter;168;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x68a9;MPSOCRTVIF_NameTooLong;Received command has file string with invalid length;169;MPSOC_RETURN_VALUES_IF;linux/payload/mpsocRetvals.h
|
||||
0x6810;MPSOCRTVIF_CommandTimeout;Command has timed out.;16;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a0;MPSOCRTVIF_CrcFailure;Space Packet received from PLOC has invalid CRC;160;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a1;MPSOCRTVIF_ReceivedAckFailure;Received ACK failure reply from PLOC;161;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a2;MPSOCRTVIF_ReceivedExeFailure;Received execution failure reply from PLOC;162;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a3;MPSOCRTVIF_InvalidApid;Received space packet with invalid APID from PLOC;163;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a4;MPSOCRTVIF_InvalidLength;Received command with invalid length;164;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a5;MPSOCRTVIF_FilenameTooLong;Filename of file in OBC filesystem is too long;165;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a6;MPSOCRTVIF_MpsocHelperExecuting;MPSoC helper is currently executing a command;166;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a7;MPSOCRTVIF_MpsocFilenameTooLong;Filename of MPSoC file is to long (max. 256 bytes);167;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a8;MPSOCRTVIF_InvalidParameter;Command has invalid parameter;168;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x68a9;MPSOCRTVIF_NameTooLong;Received command has file string with invalid length;169;MPSOC_RETURN_VALUES_IF;linux/payload/plocMpsocHelpers.h
|
||||
0x69a0;SPVRTVIF_CrcFailure;Space Packet received from PLOC supervisor has invalid CRC;160;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x69a1;SPVRTVIF_InvalidServiceId;No description;161;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x69a2;SPVRTVIF_ReceivedAckFailure;Received ACK failure reply from PLOC supervisor;162;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
@ -592,7 +596,11 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x69b5;SPVRTVIF_SupvHelperExecuting;Supervisor helper task ist currently executing a command (wait until helper tas has finished or interrupt by sending the terminate command);181;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x69c0;SPVRTVIF_BufTooSmall;No description;192;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x69c1;SPVRTVIF_NoReplyTimeout;No description;193;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x6a00;ACSCTRL_FileDeletionFailed;File deletion failed and at least one file is still existent.;0;ACS_CTRL;mission/controller/AcsController.h
|
||||
0x6aa0;ACSCTRL_FileDeletionFailed;File deletion failed and at least one file is still existent.;160;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa1;ACSCTRL_WriteFileFailed;Writing the TLE to the file has failed.;161;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa2;ACSCTRL_ReadFileFailed;Reading the TLE to the file has failed.;162;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa3;ACSCTRL_SingleRwUnavailable;A single RW has failed.;163;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6aa4;ACSCTRL_MultipleRwUnavailable;Multiple RWs have failed.;164;ACS_CTRL;mission/controller/controllerdefinitions/AcsCtrlDefinitions.h
|
||||
0x6b02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6b03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6b04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
@ -619,4 +627,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x6f02;TMS_NoWriteActive;No description;2;TM_SINK;mission/tmtc/DirectTmSinkIF.h
|
||||
0x6f03;TMS_Timeout;No description;3;TM_SINK;mission/tmtc/DirectTmSinkIF.h
|
||||
0x7000;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h
|
||||
0x7200;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h
|
||||
0x7100;PLMPCOM_PacketReceived;No description;0;PLOC_MPSOC_COM;linux/payload/MpsocCommunication.h
|
||||
0x7101;PLMPCOM_FaultyPacketSize;No description;1;PLOC_MPSOC_COM;linux/payload/MpsocCommunication.h
|
||||
0x7102;PLMPCOM_CrcCheckFailed;No description;2;PLOC_MPSOC_COM;linux/payload/MpsocCommunication.h
|
||||
0x7300;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h
|
||||
|
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 317 translations.
|
||||
* @brief Auto-generated event translation file. Contains 325 translations.
|
||||
* @details
|
||||
* Generated on: 2023-11-29 15:14:46
|
||||
* Generated on: 2024-05-06 13:47:38
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -82,8 +82,11 @@ const char *BIT_LOCK_STRING = "BIT_LOCK";
|
||||
const char *BIT_LOCK_LOST_STRING = "BIT_LOCK_LOST";
|
||||
const char *FRAME_PROCESSING_FAILED_STRING = "FRAME_PROCESSING_FAILED";
|
||||
const char *CLOCK_SET_STRING = "CLOCK_SET";
|
||||
const char *CLOCK_DUMP_STRING = "CLOCK_DUMP";
|
||||
const char *CLOCK_DUMP_LEGACY_STRING = "CLOCK_DUMP_LEGACY";
|
||||
const char *CLOCK_SET_FAILURE_STRING = "CLOCK_SET_FAILURE";
|
||||
const char *CLOCK_DUMP_STRING = "CLOCK_DUMP";
|
||||
const char *CLOCK_DUMP_BEFORE_SETTING_TIME_STRING = "CLOCK_DUMP_BEFORE_SETTING_TIME";
|
||||
const char *CLOCK_DUMP_AFTER_SETTING_TIME_STRING = "CLOCK_DUMP_AFTER_SETTING_TIME";
|
||||
const char *TC_DELETION_FAILED_STRING = "TC_DELETION_FAILED";
|
||||
const char *TEST_STRING = "TEST";
|
||||
const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
|
||||
@ -94,14 +97,17 @@ const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
|
||||
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
|
||||
const char *HANDLING_CFDP_REQUEST_FAILED_STRING = "HANDLING_CFDP_REQUEST_FAILED";
|
||||
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
||||
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||
const char *RATE_RECOVERY_STRING = "RATE_RECOVERY";
|
||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||
const char *MEKF_INVALID_INFO_STRING = "MEKF_INVALID_INFO";
|
||||
const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *PTG_CTRL_NO_ATTITUDE_INFORMATION_STRING = "PTG_CTRL_NO_ATTITUDE_INFORMATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD";
|
||||
const char *TLE_FILE_READ_FAILED_STRING = "TLE_FILE_READ_FAILED";
|
||||
const char *PTG_RATE_VIOLATION_STRING = "PTG_RATE_VIOLATION";
|
||||
const char *DETUMBLE_TRANSITION_FAILED_STRING = "DETUMBLE_TRANSITION_FAILED";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED";
|
||||
const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED";
|
||||
@ -136,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN
|
||||
const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED";
|
||||
const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON";
|
||||
const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT";
|
||||
const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE";
|
||||
const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE";
|
||||
const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE";
|
||||
const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE";
|
||||
@ -238,6 +245,7 @@ const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903_STRING = "SIDE_SWITCH_TRANS
|
||||
const char *CHILDREN_LOST_MODE_STRING = "CHILDREN_LOST_MODE";
|
||||
const char *GPS_FIX_CHANGE_STRING = "GPS_FIX_CHANGE";
|
||||
const char *CANT_GET_FIX_STRING = "CANT_GET_FIX";
|
||||
const char *RESET_FAIL_STRING = "RESET_FAIL";
|
||||
const char *P60_BOOT_COUNT_STRING = "P60_BOOT_COUNT";
|
||||
const char *BATT_MODE_STRING = "BATT_MODE";
|
||||
const char *BATT_MODE_CHANGED_STRING = "BATT_MODE_CHANGED";
|
||||
@ -480,9 +488,15 @@ const char *translateEvents(Event event) {
|
||||
case (8900):
|
||||
return CLOCK_SET_STRING;
|
||||
case (8901):
|
||||
return CLOCK_DUMP_STRING;
|
||||
return CLOCK_DUMP_LEGACY_STRING;
|
||||
case (8902):
|
||||
return CLOCK_SET_FAILURE_STRING;
|
||||
case (8903):
|
||||
return CLOCK_DUMP_STRING;
|
||||
case (8904):
|
||||
return CLOCK_DUMP_BEFORE_SETTING_TIME_STRING;
|
||||
case (8905):
|
||||
return CLOCK_DUMP_AFTER_SETTING_TIME_STRING;
|
||||
case (9100):
|
||||
return TC_DELETION_FAILED_STRING;
|
||||
case (9700):
|
||||
@ -504,7 +518,7 @@ const char *translateEvents(Event event) {
|
||||
case (11200):
|
||||
return SAFE_RATE_VIOLATION_STRING;
|
||||
case (11201):
|
||||
return SAFE_RATE_RECOVERY_STRING;
|
||||
return RATE_RECOVERY_STRING;
|
||||
case (11202):
|
||||
return MULTIPLE_RW_INVALID_STRING;
|
||||
case (11203):
|
||||
@ -514,11 +528,17 @@ const char *translateEvents(Event event) {
|
||||
case (11205):
|
||||
return MEKF_AUTOMATIC_RESET_STRING;
|
||||
case (11206):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
return PTG_CTRL_NO_ATTITUDE_INFORMATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11208):
|
||||
return TLE_TOO_OLD_STRING;
|
||||
case (11209):
|
||||
return TLE_FILE_READ_FAILED_STRING;
|
||||
case (11210):
|
||||
return PTG_RATE_VIOLATION_STRING;
|
||||
case (11211):
|
||||
return DETUMBLE_TRANSITION_FAILED_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
case (11301):
|
||||
@ -587,6 +607,8 @@ const char *translateEvents(Event event) {
|
||||
return SUPV_NOT_ON_STRING;
|
||||
case (11608):
|
||||
return SUPV_REPLY_TIMEOUT_STRING;
|
||||
case (11609):
|
||||
return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING;
|
||||
case (11701):
|
||||
return SELF_TEST_I2C_FAILURE_STRING;
|
||||
case (11702):
|
||||
@ -791,6 +813,8 @@ const char *translateEvents(Event event) {
|
||||
return GPS_FIX_CHANGE_STRING;
|
||||
case (13101):
|
||||
return CANT_GET_FIX_STRING;
|
||||
case (13102):
|
||||
return RESET_FAIL_STRING;
|
||||
case (13200):
|
||||
return P60_BOOT_COUNT_STRING;
|
||||
case (13201):
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 179 translations.
|
||||
* Generated on: 2023-11-29 15:14:46
|
||||
* Contains 180 translations.
|
||||
* Generated on: 2024-05-06 13:47:38
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
@ -64,6 +64,7 @@ const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM";
|
||||
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
|
||||
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
|
||||
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
|
||||
const char *PLOC_MPSOC_COMMUNICATION_STRING = "PLOC_MPSOC_COMMUNICATION";
|
||||
const char *SCEX_STRING = "SCEX";
|
||||
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
|
||||
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
|
||||
@ -304,6 +305,8 @@ const char *translateObject(object_id_t object) {
|
||||
return PLOC_SUPERVISOR_HANDLER_STRING;
|
||||
case 0x44330017:
|
||||
return PLOC_SUPERVISOR_HELPER_STRING;
|
||||
case 0x44330018:
|
||||
return PLOC_MPSOC_COMMUNICATION_STRING;
|
||||
case 0x44330032:
|
||||
return SCEX_STRING;
|
||||
case 0x444100A2:
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "devConf.h"
|
||||
#include "devices/gpioIds.h"
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/payloadModeTree.h"
|
||||
#include "mission/system/payload/payloadModeTree.h"
|
||||
#include "mission/system/power/epsModeTree.h"
|
||||
|
||||
void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF,
|
||||
@ -331,8 +331,9 @@ void ObjectFactory::createScexComponents(std::string uartDev, PowerSwitchIF* pwr
|
||||
scexHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
|
||||
AcsController* ObjectFactory::createAcsController(bool connectSubsystem, bool enableHkSets) {
|
||||
auto acsCtrl = new AcsController(objects::ACS_CONTROLLER, enableHkSets);
|
||||
AcsController* ObjectFactory::createAcsController(bool connectSubsystem, bool enableHkSets,
|
||||
SdCardMountedIF& mountedIF) {
|
||||
auto acsCtrl = new AcsController(objects::ACS_CONTROLLER, enableHkSets, mountedIF);
|
||||
if (connectSubsystem) {
|
||||
acsCtrl->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ void createScexComponents(std::string uartDev, PowerSwitchIF* pwrSwitcher,
|
||||
|
||||
void gpioChecker(ReturnValue_t result, std::string output);
|
||||
|
||||
AcsController* createAcsController(bool connectSubsystem, bool enableHkSets);
|
||||
AcsController* createAcsController(bool connectSubsystem, bool enableHkSets,
|
||||
SdCardMountedIF& mountedIF);
|
||||
PowerController* createPowerController(bool connectSubsystem, bool enableHkSets);
|
||||
|
||||
} // namespace ObjectFactory
|
||||
|
@ -7,15 +7,19 @@
|
||||
|
||||
namespace GpsHyperion {
|
||||
|
||||
enum class FixMode : uint8_t { NOT_SEEN = 0, NO_FIX = 1, FIX_2D = 2, FIX_3D = 3, UNKNOWN = 4 };
|
||||
enum FixMode : uint8_t { NOT_SEEN = 0, NO_FIX = 1, FIX_2D = 2, FIX_3D = 3 };
|
||||
|
||||
enum GnssChip : uint8_t { A_SIDE = 0, B_SIDE = 1 };
|
||||
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::GPS_HANDLER;
|
||||
//! [EXPORT] : [COMMENT] Fix has changed. P1: Old fix. P2: New fix
|
||||
//! [EXPORT] : [COMMENT] Fix has changed. P1: New fix. P2: Missed fix changes
|
||||
//! 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix
|
||||
static constexpr Event GPS_FIX_CHANGE = event::makeEvent(SUBSYSTEM_ID, 0, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Could not get fix in maximum allowed time. P1: Maximum allowed time
|
||||
//! to get a fix after the GPS was switched on.
|
||||
static constexpr Event CANT_GET_FIX = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Could not get fix in maximum allowed time. Trying to reset both GNSS
|
||||
//! devices. P1: Maximum allowed time to get a fix after the GPS was switched on.
|
||||
static constexpr Event CANT_GET_FIX = event::makeEvent(SUBSYSTEM_ID, 1, severity::MEDIUM);
|
||||
//! [EXPORT] : [COMMENT] Failed to reset an GNNS Device. P1: Board-Side.
|
||||
static constexpr Event RESET_FAIL = event::makeEvent(SUBSYSTEM_ID, 2, severity::HIGH);
|
||||
|
||||
static constexpr DeviceCommandId_t GPS_REPLY = 0;
|
||||
static constexpr DeviceCommandId_t TRIGGER_RESET_PIN_GNSS = 5;
|
||||
@ -53,8 +57,6 @@ static constexpr uint8_t SKYVIEW_ENTRIES = 6;
|
||||
|
||||
static constexpr uint8_t MAX_SATELLITES = 30;
|
||||
|
||||
enum GpsFixModes : uint8_t { INVALID = 0, NO_FIX = 1, FIX_2D = 2, FIX_3D = 3 };
|
||||
|
||||
} // namespace GpsHyperion
|
||||
|
||||
class GpsPrimaryDataset : public StaticLocalDataSet<GpsHyperion::CORE_DATASET_ENTRIES> {
|
@ -44,24 +44,21 @@ LocalPoolDataSetBase *GpsHyperionLinuxController::getDataSetHandle(sid_t sid) {
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) {
|
||||
if (not modeCommanded) {
|
||||
if (mode == MODE_ON or mode == MODE_OFF) {
|
||||
// 5h time to reach fix
|
||||
*msToReachTheMode = MAX_SECONDS_TO_REACH_FIX;
|
||||
if (mode == MODE_ON) {
|
||||
maxTimeToReachFix.resetTimer();
|
||||
modeCommanded = true;
|
||||
gainedNewFix.timeOut();
|
||||
} else if (mode == MODE_NORMAL) {
|
||||
return HasModesIF::INVALID_MODE;
|
||||
}
|
||||
}
|
||||
if (mode == MODE_OFF) {
|
||||
maxTimeToReachFix.timeOut();
|
||||
gainedNewFix.timeOut();
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
gpsSet.setValidity(false, true);
|
||||
// There can't be a fix with a device that is off.
|
||||
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, 0);
|
||||
gpsSet.fixMode.value = 0;
|
||||
// The ctrl is off, so it cannot detect the data from the devices.
|
||||
handleFixChangedEvent(GpsHyperion::FixMode::NOT_SEEN);
|
||||
gpsSet.fixMode.value = GpsHyperion::FixMode::NOT_SEEN;
|
||||
oneShotSwitches.reset();
|
||||
modeCommanded = false;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
@ -75,13 +72,16 @@ ReturnValue_t GpsHyperionLinuxController::executeAction(ActionId_t actionId,
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
// Set HK entries invalid
|
||||
gpsSet.setValidity(false, true);
|
||||
resetCallback(data, size, resetCallbackArgs);
|
||||
ReturnValue_t result = resetCallback(data, size, resetCallbackArgs);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasActionsIF::EXECUTION_FINISHED;
|
||||
}
|
||||
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
return HasActionsIF::INVALID_ACTION_ID;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::initializeLocalDataPool(
|
||||
@ -100,7 +100,7 @@ ReturnValue_t GpsHyperionLinuxController::initializeLocalDataPool(
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsSet.getSid(), enableHkSets, 30.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsSet.getSid(), enableHkSets, 60.0});
|
||||
localDataPoolMap.emplace(GpsHyperion::SKYVIEW_UNIX_SECONDS, new PoolEntry<double>());
|
||||
localDataPoolMap.emplace(GpsHyperion::PRN_ID, new PoolEntry<int16_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::AZIMUTH, new PoolEntry<int16_t>());
|
||||
@ -216,15 +216,9 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
||||
bool modeIsSet = true;
|
||||
if (MODE_SET != (MODE_SET & gps.set)) {
|
||||
if (mode != MODE_OFF) {
|
||||
if (maxTimeToReachFix.hasTimedOut() and oneShotSwitches.cantGetFixSwitch) {
|
||||
sif::warning << "GpsHyperionLinuxController: No mode could be set in allowed "
|
||||
<< maxTimeToReachFix.getTimeoutMs() / 1000 << " seconds" << std::endl;
|
||||
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.getTimeoutMs());
|
||||
oneShotSwitches.cantGetFixSwitch = false;
|
||||
}
|
||||
modeIsSet = false;
|
||||
} else {
|
||||
// GPS device is off anyway, so do other handling
|
||||
// GPS ctrl is off anyway, so do other handling
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
@ -249,27 +243,44 @@ ReturnValue_t GpsHyperionLinuxController::handleCoreTelemetry(bool modeIsSet) {
|
||||
uint8_t newFix = 0;
|
||||
if (modeIsSet) {
|
||||
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
|
||||
if (gps.fix.mode == 2 or gps.fix.mode == 3) {
|
||||
if (gps.fix.mode == GpsHyperion::FixMode::FIX_2D or
|
||||
gps.fix.mode == GpsHyperion::FixMode::FIX_3D) {
|
||||
validFix = true;
|
||||
maxTimeToReachFix.resetTimer();
|
||||
}
|
||||
newFix = gps.fix.mode;
|
||||
if (newFix == 0 or newFix == 1) {
|
||||
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
|
||||
// We are supposed to be on and functioning, but no fix was found
|
||||
if (mode == MODE_ON or mode == MODE_NORMAL) {
|
||||
mode = MODE_OFF;
|
||||
}
|
||||
modeCommanded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gpsSet.fixMode.value != newFix) {
|
||||
#if OBSW_Q7S_EM != 1
|
||||
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFix);
|
||||
#endif
|
||||
handleFixChangedEvent(newFix);
|
||||
}
|
||||
gpsSet.fixMode = newFix;
|
||||
gpsSet.fixMode.setValid(modeIsSet);
|
||||
// We are supposed to be on and functioning, but no fix was found
|
||||
if (not validFix) {
|
||||
if (maxTimeToReachFix.hasTimedOut()) {
|
||||
// Set HK entries invalid
|
||||
gpsSet.setValidity(false, true);
|
||||
if (oneShotSwitches.cantGetFixSwitch) {
|
||||
sif::warning << "GpsHyperionLinuxController: No fix detected in allowed "
|
||||
<< maxTimeToReachFix.getTimeoutMs() / 1000 << " seconds" << std::endl;
|
||||
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.getTimeoutMs());
|
||||
oneShotSwitches.cantGetFixSwitch = false;
|
||||
// Try resetting the devices
|
||||
if (resetCallback != nullptr) {
|
||||
uint8_t chip = GpsHyperion::GnssChip::A_SIDE;
|
||||
ReturnValue_t result = resetCallback(&chip, 1, resetCallbackArgs);
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(GpsHyperion::RESET_FAIL, chip);
|
||||
}
|
||||
chip = GpsHyperion::GnssChip::B_SIDE;
|
||||
result = resetCallback(&chip, 1, resetCallbackArgs);
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(GpsHyperion::RESET_FAIL, chip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only set on specific messages, so only set a valid flag to invalid
|
||||
// if not set for more than a full message set (10 messages here)
|
||||
@ -282,9 +293,12 @@ ReturnValue_t GpsHyperionLinuxController::handleCoreTelemetry(bool modeIsSet) {
|
||||
}
|
||||
satNotSetCounter = 0;
|
||||
} else {
|
||||
if (satNotSetCounter < 10) {
|
||||
satNotSetCounter++;
|
||||
if (gpsSet.satInUse.isValid() and satNotSetCounter >= 10) {
|
||||
} else {
|
||||
gpsSet.satInUse.value = 0;
|
||||
gpsSet.satInUse.setValid(false);
|
||||
gpsSet.satInView.value = 0;
|
||||
gpsSet.satInView.setValid(false);
|
||||
}
|
||||
}
|
||||
@ -292,12 +306,13 @@ ReturnValue_t GpsHyperionLinuxController::handleCoreTelemetry(bool modeIsSet) {
|
||||
// LATLON is set for every message, no need for a counter
|
||||
bool latValid = false;
|
||||
bool longValid = false;
|
||||
if (modeIsSet) {
|
||||
if (LATLON_SET == (LATLON_SET & gps.set)) {
|
||||
if (std::isfinite(gps.fix.latitude)) {
|
||||
// Negative latitude -> South direction
|
||||
gpsSet.latitude.value = gps.fix.latitude;
|
||||
// As specified in gps.h: Only valid if mode >= 2
|
||||
if (gps.fix.mode >= 2) {
|
||||
if (gps.fix.mode >= GpsHyperion::FixMode::FIX_2D) {
|
||||
latValid = true;
|
||||
}
|
||||
}
|
||||
@ -306,31 +321,36 @@ ReturnValue_t GpsHyperionLinuxController::handleCoreTelemetry(bool modeIsSet) {
|
||||
// Negative longitude -> West direction
|
||||
gpsSet.longitude.value = gps.fix.longitude;
|
||||
// As specified in gps.h: Only valid if mode >= 2
|
||||
if (gps.fix.mode >= 2) {
|
||||
if (gps.fix.mode >= GpsHyperion::FixMode::FIX_2D) {
|
||||
longValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gpsSet.latitude.setValid(latValid);
|
||||
gpsSet.longitude.setValid(longValid);
|
||||
|
||||
// ALTITUDE is set for every message, no need for a counter
|
||||
bool altitudeValid = false;
|
||||
if (modeIsSet) {
|
||||
if (ALTITUDE_SET == (ALTITUDE_SET & gps.set) && std::isfinite(gps.fix.altitude)) {
|
||||
gpsSet.altitude.value = gps.fix.altitude;
|
||||
// As specified in gps.h: Only valid if mode == 3
|
||||
if (gps.fix.mode == 3) {
|
||||
if (gps.fix.mode == GpsHyperion::FixMode::FIX_3D) {
|
||||
altitudeValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
gpsSet.altitude.setValid(altitudeValid);
|
||||
|
||||
// SPEED is set for every message, no need for a counter
|
||||
bool speedValid = false;
|
||||
if (modeIsSet) {
|
||||
if (SPEED_SET == (SPEED_SET & gps.set) && std::isfinite(gps.fix.speed)) {
|
||||
gpsSet.speed.value = gps.fix.speed;
|
||||
speedValid = true;
|
||||
}
|
||||
}
|
||||
gpsSet.speed.setValid(speedValid);
|
||||
|
||||
// TIME is set for every message, no need for a counter
|
||||
@ -430,3 +450,14 @@ void GpsHyperionLinuxController::overwriteTimeIfNotSane(timeval time, bool valid
|
||||
timeInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GpsHyperionLinuxController::handleFixChangedEvent(uint8_t newFix) {
|
||||
if (gainedNewFix.hasTimedOut()) {
|
||||
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, newFix, fixChangeCounter);
|
||||
fixChangeCounter = 0;
|
||||
gainedNewFix.resetTimer();
|
||||
return;
|
||||
}
|
||||
fixChangeCounter++;
|
||||
gainedNewFix.resetTimer();
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
#ifndef MISSION_DEVICES_GPSHYPERIONHANDLER_H_
|
||||
#define MISSION_DEVICES_GPSHYPERIONHANDLER_H_
|
||||
|
||||
#include <mission/acs/archive/GPSDefinitions.h>
|
||||
#include <common/config/eive/eventSubsystemIds.h>
|
||||
#include <fsfw/FSFW.h>
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <linux/acs/GPSDefinitions.h>
|
||||
#include <mission/utility/trace.h>
|
||||
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/controller/ExtendedControllerBase.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
|
||||
#ifdef FSFW_OSAL_LINUX
|
||||
#include <gps.h>
|
||||
#include <libgpsmm.h>
|
||||
@ -24,8 +23,8 @@
|
||||
*/
|
||||
class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
public:
|
||||
// 30 minutes
|
||||
static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 30;
|
||||
// 15 minutes
|
||||
static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 15;
|
||||
|
||||
enum ReadModes { SHM = 0, SOCKET = 1 };
|
||||
|
||||
@ -65,7 +64,8 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
const char* currentClientBuf = nullptr;
|
||||
ReadModes readMode = ReadModes::SOCKET;
|
||||
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
|
||||
bool modeCommanded = false;
|
||||
Countdown gainedNewFix = Countdown(60 * 2 * 1000);
|
||||
uint32_t fixChangeCounter = 0;
|
||||
bool timeInit = false;
|
||||
uint8_t satNotSetCounter = 0;
|
||||
|
||||
@ -92,6 +92,8 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
// we set it with the roughly valid time from the GPS. For some reason, NTP might only work
|
||||
// if the time difference between sys time and current time is not too large
|
||||
void overwriteTimeIfNotSane(timeval time, bool validFix);
|
||||
|
||||
void handleFixChangedEvent(uint8_t newFix);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_GPSHYPERIONHANDLER_H_ */
|
||||
|
@ -175,7 +175,8 @@ void StrComHandler::setDownloadImageName(std::string filename) {
|
||||
|
||||
void StrComHandler::setFlashReadFilename(std::string filename) { flashRead.filename = filename; }
|
||||
|
||||
ReturnValue_t StrComHandler::startFirmwareUpdate(std::string fullname) {
|
||||
ReturnValue_t StrComHandler::startFirmwareUpdate(std::string fullname,
|
||||
startracker::FirmwareTarget target) {
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
if (state != InternalState::SLEEPING) {
|
||||
@ -192,8 +193,13 @@ ReturnValue_t StrComHandler::startFirmwareUpdate(std::string fullname) {
|
||||
if (not std::filesystem::exists(flashWrite.fullname)) {
|
||||
return FILE_NOT_EXISTS;
|
||||
}
|
||||
flashWrite.firstRegion = static_cast<uint8_t>(startracker::FirmwareRegions::FIRST);
|
||||
flashWrite.lastRegion = static_cast<uint8_t>(startracker::FirmwareRegions::LAST);
|
||||
if (target == startracker::FirmwareTarget::MAIN) {
|
||||
flashWrite.firstRegion = static_cast<uint8_t>(startracker::FirmwareRegions::FIRST_MAIN);
|
||||
flashWrite.lastRegion = static_cast<uint8_t>(startracker::FirmwareRegions::LAST_MAIN);
|
||||
} else if (target == startracker::FirmwareTarget::BACKUP) {
|
||||
flashWrite.firstRegion = static_cast<uint8_t>(startracker::FirmwareRegions::FIRST_BACKUP);
|
||||
flashWrite.lastRegion = static_cast<uint8_t>(startracker::FirmwareRegions::LAST_BACKUP);
|
||||
}
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
replyWasReceived = false;
|
||||
@ -264,7 +270,7 @@ ReturnValue_t StrComHandler::performImageDownload() {
|
||||
file.close();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
arc_pack_download_action_req(&downloadReq, cmdBuf.data(), &size);
|
||||
prv_arc_pack_download_action_req(&downloadReq, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, downloadReq.position);
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
@ -275,7 +281,7 @@ ReturnValue_t StrComHandler::performImageDownload() {
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply(replySize);
|
||||
result = checkActionReply(replySize, "downloading image");
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
serial::flushRxBuf(serialPort);
|
||||
@ -343,12 +349,12 @@ ReturnValue_t StrComHandler::performImageUpload() {
|
||||
}
|
||||
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
|
||||
file.read(reinterpret_cast<char*>(uploadReq.data), SIZE_IMAGE_PART);
|
||||
arc_pack_upload_action_req(&uploadReq, cmdBuf.data(), &size);
|
||||
prv_arc_pack_upload_action_req(&uploadReq, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, uploadReq.position);
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
result = checkActionReply(replyLen, "sky image upload");
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -369,12 +375,12 @@ ReturnValue_t StrComHandler::performImageUpload() {
|
||||
file.seekg(fullChunks * SIZE_IMAGE_PART, file.beg);
|
||||
file.read(reinterpret_cast<char*>(uploadReq.data), remainder);
|
||||
file.close();
|
||||
arc_pack_upload_action_req(&uploadReq, cmdBuf.data(), &size);
|
||||
prv_arc_pack_upload_action_req(&uploadReq, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, uploadReq.position);
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
result = checkActionReply(replyLen, "sky image upload");
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -388,8 +394,7 @@ ReturnValue_t StrComHandler::performImageUpload() {
|
||||
ReturnValue_t StrComHandler::performFirmwareUpdate() {
|
||||
using namespace startracker;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = unlockAndEraseRegions(static_cast<uint32_t>(startracker::FirmwareRegions::FIRST),
|
||||
static_cast<uint32_t>(startracker::FirmwareRegions::LAST));
|
||||
result = unlockAndEraseRegions(flashWrite.firstRegion, flashWrite.lastRegion);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -440,12 +445,12 @@ ReturnValue_t StrComHandler::performFlashWrite() {
|
||||
bytesWrittenInRegion = 0;
|
||||
}
|
||||
req.address = bytesWrittenInRegion;
|
||||
arc_pack_write_action_req(&req, cmdBuf.data(), &size);
|
||||
prv_arc_pack_write_action_req(&req, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
result = checkActionReply(replyLen, "firmware image upload");
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -483,12 +488,12 @@ ReturnValue_t StrComHandler::performFlashWrite() {
|
||||
req.length = remainingBytes;
|
||||
totalBytesWritten += CHUNK_SIZE;
|
||||
bytesWrittenInRegion += remainingBytes;
|
||||
arc_pack_write_action_req(&req, cmdBuf.data(), &size);
|
||||
prv_arc_pack_write_action_req(&req, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
result = checkActionReply(replyLen, "flash write");
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -531,7 +536,7 @@ ReturnValue_t StrComHandler::performFlashRead() {
|
||||
} else {
|
||||
req.length = CHUNK_SIZE;
|
||||
}
|
||||
arc_pack_read_action_req(&req, cmdBuf.data(), &size);
|
||||
prv_arc_pack_read_action_req(&req, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
@ -542,7 +547,7 @@ ReturnValue_t StrComHandler::performFlashRead() {
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
result = checkActionReply(replyLen, "flash read");
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
serial::flushRxBuf(serialPort);
|
||||
@ -584,7 +589,7 @@ ReturnValue_t StrComHandler::sendAndRead(size_t size, uint32_t failParameter) {
|
||||
return readOneReply(failParameter);
|
||||
}
|
||||
|
||||
ReturnValue_t StrComHandler::checkActionReply(size_t replySize) {
|
||||
ReturnValue_t StrComHandler::checkActionReply(size_t replySize, const char* context) {
|
||||
uint8_t type = startracker::getReplyFrameType(replyPtr);
|
||||
if (type != TMTC_ACTIONREPLY) {
|
||||
sif::warning << "StrHelper::checkActionReply: Received reply with invalid type ID" << std::endl;
|
||||
@ -592,7 +597,7 @@ ReturnValue_t StrComHandler::checkActionReply(size_t replySize) {
|
||||
}
|
||||
uint8_t status = startracker::getStatusField(replyPtr);
|
||||
if (status != ArcsecDatalinkLayer::STATUS_OK) {
|
||||
sif::warning << "StrHelper::checkActionReply: Status failure: "
|
||||
sif::warning << "StrHelper::checkActionReply: Status failure for " << context << ": "
|
||||
<< static_cast<unsigned int>(status) << std::endl;
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
@ -744,23 +749,26 @@ ReturnValue_t StrComHandler::unlockAndEraseRegions(uint32_t from, uint32_t to) {
|
||||
struct UnlockActionRequest unlockReq;
|
||||
struct EraseActionRequest eraseReq;
|
||||
uint32_t size = 0;
|
||||
for (uint32_t idx = from; idx <= to; idx++) {
|
||||
for (uint32_t idx = from; idx < to; idx++) {
|
||||
unlockReq.region = idx;
|
||||
unlockReq.code = startracker::region_secrets::secret[idx];
|
||||
arc_pack_unlock_action_req(&unlockReq, cmdBuf.data(), &size);
|
||||
unlockReq.code = startracker::region_secrets::SECRETS[idx];
|
||||
prv_arc_pack_unlock_action_req(&unlockReq, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, unlockReq.region);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
result = checkActionReply(replyLen, "unlocking region");
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to unlock region with id "
|
||||
<< static_cast<unsigned int>(unlockReq.region) << std::endl;
|
||||
return result;
|
||||
}
|
||||
eraseReq.region = idx;
|
||||
arc_pack_erase_action_req(&eraseReq, cmdBuf.data(), &size);
|
||||
prv_arc_pack_erase_action_req(&eraseReq, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, eraseReq.region);
|
||||
if (result != returnvalue::OK) {
|
||||
}
|
||||
result = checkActionReply(replyLen, "erasing region");
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to erase region with id "
|
||||
<< static_cast<unsigned int>(eraseReq.region) << std::endl;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "mission/acs/str/strHelpers.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
@ -127,7 +128,7 @@ class StrComHandler : public SystemObject, public DeviceCommunicationIF, public
|
||||
* @param fullname Full name including absolute path of file containing firmware
|
||||
* update.
|
||||
*/
|
||||
ReturnValue_t startFirmwareUpdate(std::string fullname);
|
||||
ReturnValue_t startFirmwareUpdate(std::string fullname, startracker::FirmwareTarget target);
|
||||
|
||||
/**
|
||||
* @brief Starts the flash read procedure
|
||||
@ -334,7 +335,7 @@ class StrComHandler : public SystemObject, public DeviceCommunicationIF, public
|
||||
*
|
||||
* @return returnvalue::OK if reply confirms success of packet transfer, otherwise REUTRN_FAILED
|
||||
*/
|
||||
ReturnValue_t checkActionReply(size_t replySize);
|
||||
ReturnValue_t checkActionReply(size_t replySize, const char *context);
|
||||
|
||||
/**
|
||||
* @brief Checks the position field in a star tracker upload/download reply.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 317 translations.
|
||||
* @brief Auto-generated event translation file. Contains 325 translations.
|
||||
* @details
|
||||
* Generated on: 2023-11-29 15:14:46
|
||||
* Generated on: 2024-05-06 13:47:38
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -82,8 +82,11 @@ const char *BIT_LOCK_STRING = "BIT_LOCK";
|
||||
const char *BIT_LOCK_LOST_STRING = "BIT_LOCK_LOST";
|
||||
const char *FRAME_PROCESSING_FAILED_STRING = "FRAME_PROCESSING_FAILED";
|
||||
const char *CLOCK_SET_STRING = "CLOCK_SET";
|
||||
const char *CLOCK_DUMP_STRING = "CLOCK_DUMP";
|
||||
const char *CLOCK_DUMP_LEGACY_STRING = "CLOCK_DUMP_LEGACY";
|
||||
const char *CLOCK_SET_FAILURE_STRING = "CLOCK_SET_FAILURE";
|
||||
const char *CLOCK_DUMP_STRING = "CLOCK_DUMP";
|
||||
const char *CLOCK_DUMP_BEFORE_SETTING_TIME_STRING = "CLOCK_DUMP_BEFORE_SETTING_TIME";
|
||||
const char *CLOCK_DUMP_AFTER_SETTING_TIME_STRING = "CLOCK_DUMP_AFTER_SETTING_TIME";
|
||||
const char *TC_DELETION_FAILED_STRING = "TC_DELETION_FAILED";
|
||||
const char *TEST_STRING = "TEST";
|
||||
const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
|
||||
@ -94,14 +97,17 @@ const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
|
||||
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
|
||||
const char *HANDLING_CFDP_REQUEST_FAILED_STRING = "HANDLING_CFDP_REQUEST_FAILED";
|
||||
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
||||
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||
const char *RATE_RECOVERY_STRING = "RATE_RECOVERY";
|
||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||
const char *MEKF_INVALID_INFO_STRING = "MEKF_INVALID_INFO";
|
||||
const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *PTG_CTRL_NO_ATTITUDE_INFORMATION_STRING = "PTG_CTRL_NO_ATTITUDE_INFORMATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD";
|
||||
const char *TLE_FILE_READ_FAILED_STRING = "TLE_FILE_READ_FAILED";
|
||||
const char *PTG_RATE_VIOLATION_STRING = "PTG_RATE_VIOLATION";
|
||||
const char *DETUMBLE_TRANSITION_FAILED_STRING = "DETUMBLE_TRANSITION_FAILED";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED";
|
||||
const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED";
|
||||
@ -136,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN
|
||||
const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED";
|
||||
const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON";
|
||||
const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT";
|
||||
const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE";
|
||||
const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE";
|
||||
const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE";
|
||||
const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE";
|
||||
@ -238,6 +245,7 @@ const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903_STRING = "SIDE_SWITCH_TRANS
|
||||
const char *CHILDREN_LOST_MODE_STRING = "CHILDREN_LOST_MODE";
|
||||
const char *GPS_FIX_CHANGE_STRING = "GPS_FIX_CHANGE";
|
||||
const char *CANT_GET_FIX_STRING = "CANT_GET_FIX";
|
||||
const char *RESET_FAIL_STRING = "RESET_FAIL";
|
||||
const char *P60_BOOT_COUNT_STRING = "P60_BOOT_COUNT";
|
||||
const char *BATT_MODE_STRING = "BATT_MODE";
|
||||
const char *BATT_MODE_CHANGED_STRING = "BATT_MODE_CHANGED";
|
||||
@ -480,9 +488,15 @@ const char *translateEvents(Event event) {
|
||||
case (8900):
|
||||
return CLOCK_SET_STRING;
|
||||
case (8901):
|
||||
return CLOCK_DUMP_STRING;
|
||||
return CLOCK_DUMP_LEGACY_STRING;
|
||||
case (8902):
|
||||
return CLOCK_SET_FAILURE_STRING;
|
||||
case (8903):
|
||||
return CLOCK_DUMP_STRING;
|
||||
case (8904):
|
||||
return CLOCK_DUMP_BEFORE_SETTING_TIME_STRING;
|
||||
case (8905):
|
||||
return CLOCK_DUMP_AFTER_SETTING_TIME_STRING;
|
||||
case (9100):
|
||||
return TC_DELETION_FAILED_STRING;
|
||||
case (9700):
|
||||
@ -504,7 +518,7 @@ const char *translateEvents(Event event) {
|
||||
case (11200):
|
||||
return SAFE_RATE_VIOLATION_STRING;
|
||||
case (11201):
|
||||
return SAFE_RATE_RECOVERY_STRING;
|
||||
return RATE_RECOVERY_STRING;
|
||||
case (11202):
|
||||
return MULTIPLE_RW_INVALID_STRING;
|
||||
case (11203):
|
||||
@ -514,11 +528,17 @@ const char *translateEvents(Event event) {
|
||||
case (11205):
|
||||
return MEKF_AUTOMATIC_RESET_STRING;
|
||||
case (11206):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
return PTG_CTRL_NO_ATTITUDE_INFORMATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11208):
|
||||
return TLE_TOO_OLD_STRING;
|
||||
case (11209):
|
||||
return TLE_FILE_READ_FAILED_STRING;
|
||||
case (11210):
|
||||
return PTG_RATE_VIOLATION_STRING;
|
||||
case (11211):
|
||||
return DETUMBLE_TRANSITION_FAILED_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
case (11301):
|
||||
@ -587,6 +607,8 @@ const char *translateEvents(Event event) {
|
||||
return SUPV_NOT_ON_STRING;
|
||||
case (11608):
|
||||
return SUPV_REPLY_TIMEOUT_STRING;
|
||||
case (11609):
|
||||
return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING;
|
||||
case (11701):
|
||||
return SELF_TEST_I2C_FAILURE_STRING;
|
||||
case (11702):
|
||||
@ -791,6 +813,8 @@ const char *translateEvents(Event event) {
|
||||
return GPS_FIX_CHANGE_STRING;
|
||||
case (13101):
|
||||
return CANT_GET_FIX_STRING;
|
||||
case (13102):
|
||||
return RESET_FAIL_STRING;
|
||||
case (13200):
|
||||
return P60_BOOT_COUNT_STRING;
|
||||
case (13201):
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 179 translations.
|
||||
* Generated on: 2023-11-29 15:14:46
|
||||
* Contains 180 translations.
|
||||
* Generated on: 2024-05-06 13:47:38
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
@ -64,6 +64,7 @@ const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM";
|
||||
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
|
||||
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
|
||||
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
|
||||
const char *PLOC_MPSOC_COMMUNICATION_STRING = "PLOC_MPSOC_COMMUNICATION";
|
||||
const char *SCEX_STRING = "SCEX";
|
||||
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
|
||||
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
|
||||
@ -304,6 +305,8 @@ const char *translateObject(object_id_t object) {
|
||||
return PLOC_SUPERVISOR_HANDLER_STRING;
|
||||
case 0x44330017:
|
||||
return PLOC_SUPERVISOR_HELPER_STRING;
|
||||
case 0x44330018:
|
||||
return PLOC_MPSOC_COMMUNICATION_STRING;
|
||||
case 0x44330032:
|
||||
return SCEX_STRING;
|
||||
case 0x444100A2:
|
||||
|
@ -1,7 +1,9 @@
|
||||
target_sources(
|
||||
${OBSW_NAME}
|
||||
PUBLIC PlocMemoryDumper.cpp
|
||||
PlocMpsocHandler.cpp
|
||||
MpsocCommunication.cpp
|
||||
SerialCommunicationHelper.cpp
|
||||
FreshMpsocHandler.cpp
|
||||
FreshSupvHandler.cpp
|
||||
PlocMpsocSpecialComHelper.cpp
|
||||
plocMpsocHelpers.cpp
|
||||
|
1288
linux/payload/FreshMpsocHandler.cpp
Normal file
1288
linux/payload/FreshMpsocHandler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
212
linux/payload/FreshMpsocHandler.h
Normal file
212
linux/payload/FreshMpsocHandler.h
Normal file
@ -0,0 +1,212 @@
|
||||
#include "fsfw/action/ActionMessage.h"
|
||||
#include "fsfw/action/CommandsActionsIF.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
|
||||
#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/ipc/messageQueueDefinitions.h"
|
||||
#include "fsfw/modes/ModeMessage.h"
|
||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||
#include "fsfw/power/PowerSwitchIF.h"
|
||||
#include "fsfw/power/definitions.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw_hal/linux/gpio/Gpio.h"
|
||||
#include "linux/payload/MpsocCommunication.h"
|
||||
#include "linux/payload/PlocMpsocSpecialComHelper.h"
|
||||
#include "linux/payload/plocMpsocHelpers.h"
|
||||
|
||||
class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsIF {
|
||||
public:
|
||||
enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 };
|
||||
static constexpr uint32_t MPSOC_MODE_CMD_TIMEOUT_MS = 120000;
|
||||
|
||||
FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface,
|
||||
PlocMpsocSpecialComHelper& specialComHelper, Gpio uartIsolatorSwitch,
|
||||
object_id_t supervisorHandler, PowerSwitchIF& powerSwitcher,
|
||||
power::Switch_t camSwitchId);
|
||||
|
||||
/**
|
||||
* Periodic helper executed function, implemented by child class.
|
||||
*/
|
||||
void performDeviceOperation(uint8_t opCode) override;
|
||||
|
||||
void performDefaultDeviceOperation();
|
||||
|
||||
/**
|
||||
* Implemented by child class. Handle all command messages which are
|
||||
* not health, mode, action or housekeeping messages.
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
enum class StartupState { IDLE, HW_INIT, DONE } startupState = StartupState::IDLE;
|
||||
enum class PowerState { IDLE, PENDING_STARTUP, PENDING_SHUTDOWN, SUPV_FAILED, DONE };
|
||||
|
||||
enum TransitionState { NONE, TO_ON, TO_OFF, SUBMODE } transitionState = TransitionState::NONE;
|
||||
MpsocCommunication& comInterface;
|
||||
PlocMpsocSpecialComHelper& specialComHelper;
|
||||
MessageQueueIF* eventQueue = nullptr;
|
||||
SourceSequenceCounter commandSequenceCount = SourceSequenceCounter(0);
|
||||
MessageQueueIF* commandActionHelperQueue = nullptr;
|
||||
CommandActionHelper commandActionHelper;
|
||||
Gpio uartIsolatorSwitch;
|
||||
mpsoc::HkReport hkReport;
|
||||
object_id_t supervisorHandler;
|
||||
|
||||
Countdown mpsocBootTransitionCd = Countdown(6500);
|
||||
Countdown supvTransitionCd = Countdown(3000);
|
||||
|
||||
PoolEntry<uint32_t> peStatus = PoolEntry<uint32_t>();
|
||||
PoolEntry<uint8_t> peMode = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkPwrOn = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkReplyActive = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkJesdSyncStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peDownlinkDacStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peCameraStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peCameraSdiStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<float> peCameraFpgaTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peCameraSocTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonTemp = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccInt = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccAux = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccBram = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPaux = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPint = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVccPdro = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb12V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb3V3 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonMb1V8 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc12V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc5V = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc3V3 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc3V3VA = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc2V5DDR = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc1V2DDR = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc0V9 = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonVcc0V6VTT = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonSafeCotsCur = PoolEntry<float>();
|
||||
PoolEntry<float> peSysmonNvm4XoCur = PoolEntry<float>();
|
||||
PoolEntry<uint16_t> peSemUncorrectableErrs = PoolEntry<uint16_t>();
|
||||
PoolEntry<uint16_t> peSemCorrectableErrs = PoolEntry<uint16_t>();
|
||||
PoolEntry<uint8_t> peSemStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<uint8_t> peRebootMpsocRequired = PoolEntry<uint8_t>();
|
||||
|
||||
PowerState powerState;
|
||||
bool specialComHelperExecuting = false;
|
||||
|
||||
struct ActionCommandInfo {
|
||||
Countdown cmdCountdown = Countdown(mpsoc::DEFAULT_CMD_TIMEOUT_MS);
|
||||
bool pending = false;
|
||||
MessageQueueId_t commandedBy = MessageQueueIF::NO_QUEUE;
|
||||
DeviceCommandId_t pendingCmd = DeviceHandlerIF::NO_COMMAND_ID;
|
||||
uint16_t pendingCmdMpsocApid = 0;
|
||||
|
||||
void reset() {
|
||||
pending = false;
|
||||
commandedBy = MessageQueueIF::NO_QUEUE;
|
||||
pendingCmd = DeviceHandlerIF::NO_COMMAND_ID;
|
||||
}
|
||||
|
||||
void start(DeviceCommandId_t commandId, MessageQueueId_t commandedBy) {
|
||||
pending = true;
|
||||
cmdCountdown.resetTimer();
|
||||
pendingCmd = commandId;
|
||||
this->commandedBy = commandedBy;
|
||||
}
|
||||
} activeCmdInfo;
|
||||
|
||||
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
|
||||
SpacePacketCreator creator;
|
||||
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
|
||||
Mode_t targetMode = HasModesIF::MODE_UNDEFINED;
|
||||
Submode_t targetSubmode = 0;
|
||||
|
||||
struct TmMemReadReport {
|
||||
static const uint8_t FIX_SIZE = 14;
|
||||
size_t rememberRequestedSize = 0;
|
||||
};
|
||||
|
||||
TmMemReadReport tmMemReadReport;
|
||||
uint32_t lastReplySequenceCount = 0;
|
||||
uint8_t skipSupvCommandingToOn = false;
|
||||
PowerSwitchIF& powerSwitcher;
|
||||
power::Switch_t camSwitchId;
|
||||
|
||||
// HK manager abstract functions.
|
||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
|
||||
// Mode abstract functions
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) override;
|
||||
// Action override. Forward to user.
|
||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) override;
|
||||
|
||||
/**
|
||||
* @overload
|
||||
* @param submode
|
||||
*/
|
||||
void startTransition(Mode_t newMode, Submode_t submode) override;
|
||||
|
||||
ReturnValue_t performDeviceOperationPreQueueHandling(uint8_t opCode) override;
|
||||
|
||||
// CommandsActionsIF overrides.
|
||||
MessageQueueIF* getCommandQueuePtr() override;
|
||||
|
||||
void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) override;
|
||||
void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) override;
|
||||
void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) override;
|
||||
void completionSuccessfulReceived(ActionId_t actionId) override;
|
||||
void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) override;
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
|
||||
|
||||
void handleActionCommandFailure(ActionId_t actionId, ReturnValue_t returnCode);
|
||||
ReturnValue_t executeRegularCmd(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t dataLen);
|
||||
void handleTransitionToOn();
|
||||
void handleTransitionToOff();
|
||||
|
||||
ReturnValue_t commandTcModeReplay();
|
||||
ReturnValue_t commandTcMemWrite(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcMemRead(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcFlashDelete(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcReplayStart(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcReplayStop();
|
||||
ReturnValue_t commandTcDownlinkPwrOn(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcDownlinkPwrOff();
|
||||
ReturnValue_t commandTcGetHkReport();
|
||||
ReturnValue_t commandTcGetDirContent(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcModeIdle();
|
||||
ReturnValue_t commandTcCamTakePic(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcSimplexStreamFile(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcSplitFile(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t commandTcModeSnapshot();
|
||||
|
||||
ReturnValue_t finishAndSendTc(DeviceCommandId_t cmdId, mpsoc::TcBase& tcBase,
|
||||
uint32_t cmdCountdown = mpsoc::DEFAULT_CMD_TIMEOUT_MS);
|
||||
void handleEvent(EventMessage* eventMessage);
|
||||
void cmdDoneHandler(bool success, ReturnValue_t result);
|
||||
ReturnValue_t handleDeviceReply();
|
||||
ReturnValue_t handleAckReport();
|
||||
ReturnValue_t handleExecutionReport();
|
||||
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
|
||||
ReturnValue_t reportReplyData(DeviceCommandId_t tmId);
|
||||
ReturnValue_t handleGetHkReport();
|
||||
bool handleHwStartup();
|
||||
bool handleHwShutdown();
|
||||
|
||||
void stopSpecialComHelper();
|
||||
void commandSubmodeTransition();
|
||||
void commonSpecialComInit();
|
||||
void commonSpecialComStop();
|
||||
void commandInitHandling(ActionId_t actionId, MessageQueueId_t commandedBy);
|
||||
};
|
@ -241,6 +241,10 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI
|
||||
uartManager->initiateUpdateContinuation();
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case ABORT_LONGER_REQUEST: {
|
||||
uartManager->stop();
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case MEMORY_CHECK_WITH_FILE: {
|
||||
UpdateParams params;
|
||||
result = extractBaseParams(&data, size, params);
|
||||
@ -849,6 +853,10 @@ ReturnValue_t FreshSupvHandler::prepareWipeMramCmd(const uint8_t* commandData, s
|
||||
ReturnValue_t FreshSupvHandler::parseTmPackets() {
|
||||
uint8_t* receivedData = nullptr;
|
||||
size_t receivedSize = 0;
|
||||
// We do not want to steal packets from the long request handler.
|
||||
if (uartManager->longerRequestActive()) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
while (true) {
|
||||
ReturnValue_t result =
|
||||
uartManager->readReceivedMessage(comCookie, &receivedData, &receivedSize);
|
||||
@ -900,6 +908,14 @@ ReturnValue_t FreshSupvHandler::parseTmPackets() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (Apid::LATCHUP_MON): {
|
||||
if (tmReader.getServiceId() ==
|
||||
static_cast<uint8_t>(supv::tm::LatchupMonId::LATCHUP_STATUS_REPORT)) {
|
||||
handleLatchupStatusReport(receivedData);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (Apid::ADC_MON): {
|
||||
if (tmReader.getServiceId() == static_cast<uint8_t>(supv::tm::AdcMonId::ADC_REPORT)) {
|
||||
genericHandleTm("ADC", receivedData, adcReport, supv::Apid::ADC_MON,
|
||||
@ -1115,7 +1131,8 @@ void FreshSupvHandler::handleEvent(EventMessage* eventMessage) {
|
||||
if (not isCommandAlreadyActive(supv::SHUTDOWN_MPSOC)) {
|
||||
CommandMessage actionMsg;
|
||||
ActionMessage::setCommand(&actionMsg, supv::SHUTDOWN_MPSOC, store_address_t::invalid());
|
||||
result = messageQueue->sendMessage(getCommandQueue(), &actionMsg);
|
||||
result = messageQueue->sendMessageFrom(getCommandQueue(), &actionMsg,
|
||||
MessageQueueIF::NO_QUEUE);
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(supv::SUPV_MPSOC_SHUTDOWN_BUILD_FAILED);
|
||||
sif::warning << "PlocSupervisorHandler::handleEvent: Failed to build MPSoC shutdown "
|
||||
@ -1290,7 +1307,7 @@ void FreshSupvHandler::handleExecutionFailureReport(ActiveCmdInfo& info, Executi
|
||||
triggerEvent(SUPV_EXE_FAILURE, info.commandId, static_cast<uint32_t>(report.getStatusCode()));
|
||||
}
|
||||
if (info.commandedBy) {
|
||||
actionHelper.finish(false, info.commandedBy, info.commandId, report.getStatusCode());
|
||||
actionHelper.finish(false, info.commandedBy, info.commandId, result::RECEIVED_EXE_FAILURE);
|
||||
}
|
||||
info.isPending = false;
|
||||
}
|
||||
@ -1390,15 +1407,17 @@ ReturnValue_t FreshSupvHandler::verifyPacket(const uint8_t* start, size_t foundL
|
||||
|
||||
ReturnValue_t FreshSupvHandler::handleBootStatusReport(const uint8_t* data) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = verifyPacket(data, tmReader.getFullPacketLen());
|
||||
|
||||
if (result == result::CRC_FAILURE) {
|
||||
sif::error << "PlocSupervisorHandler::handleBootStatusReport: Boot status report has invalid"
|
||||
" crc"
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
PoolReadGuard pg(&bootStatusReport);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return pg.getReadResult();
|
||||
}
|
||||
|
||||
const uint8_t* payloadStart = tmReader.getPayloadStart();
|
||||
uint16_t offset = 0;
|
||||
@ -1462,13 +1481,17 @@ ReturnValue_t FreshSupvHandler::handleLatchupStatusReport(const uint8_t* data) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = verifyPacket(data, tmReader.getFullPacketLen());
|
||||
|
||||
if (result == result::CRC_FAILURE) {
|
||||
sif::error << "PlocSupervisorHandler::handleLatchupStatusReport: Latchup status report has "
|
||||
<< "invalid crc" << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
PoolReadGuard pg(&latchupStatusReport);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return pg.getReadResult();
|
||||
}
|
||||
|
||||
const uint8_t* payloadData = tmReader.getPayloadStart();
|
||||
uint16_t offset = 0;
|
||||
latchupStatusReport.id = *(payloadData + offset);
|
||||
@ -1485,10 +1508,10 @@ ReturnValue_t FreshSupvHandler::handleLatchupStatusReport(const uint8_t* data) {
|
||||
offset += 2;
|
||||
latchupStatusReport.cnt5 = *(payloadData + offset) << 8 | *(payloadData + offset + 1);
|
||||
offset += 2;
|
||||
latchupStatusReport.cnt6 = *(payloadData + offset) << 8 | *(data + offset + 1);
|
||||
latchupStatusReport.cnt6 = *(payloadData + offset) << 8 | *(payloadData + offset + 1);
|
||||
offset += 2;
|
||||
uint16_t msec = *(payloadData + offset) << 8 | *(payloadData + offset + 1);
|
||||
latchupStatusReport.isSet = msec >> supv::LatchupStatusReport::IS_SET_BIT_POS;
|
||||
latchupStatusReport.isSynced = msec >> supv::LatchupStatusReport::IS_SET_BIT_POS;
|
||||
latchupStatusReport.timeMsec = msec & (~(1 << latchupStatusReport.IS_SET_BIT_POS));
|
||||
offset += 2;
|
||||
latchupStatusReport.timeSec = *(payloadData + offset);
|
||||
|
75
linux/payload/MpsocCommunication.cpp
Normal file
75
linux/payload/MpsocCommunication.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "MpsocCommunication.h"
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
|
||||
#include "fsfw/tmtcpacket/ccsds/header.h"
|
||||
#include "linux/payload/plocMpsocHelpers.h"
|
||||
#include "unistd.h"
|
||||
|
||||
MpsocCommunication::MpsocCommunication(object_id_t objectId, SerialConfig cfg)
|
||||
: SystemObject(objectId), readRingBuf(4096, true), helper(cfg) {}
|
||||
|
||||
ReturnValue_t MpsocCommunication::initialize() { return helper.initialize(); }
|
||||
|
||||
ReturnValue_t MpsocCommunication::send(const uint8_t* data, size_t dataLen) {
|
||||
if (MPSOC_LOW_LEVEL_TX_WIRETAPPING) {
|
||||
sif::debug << "SEND MPSOC packet with size " << dataLen << std::endl;
|
||||
}
|
||||
return helper.send(data, dataLen);
|
||||
}
|
||||
|
||||
ReturnValue_t MpsocCommunication::parseAndRetrieveNextPacket() {
|
||||
// We do not have a data link layer, so this whole thing is a mess in any case..
|
||||
// But basically, we try to parse space packets from the internal ring buffer and trasnfer
|
||||
// them to the higher level device handler. The CRC check is performed here as well, with
|
||||
// few other ways to detect if we even have a valid packet.
|
||||
size_t availableReadData = readRingBuf.getAvailableReadData();
|
||||
// Minimum valid size for a space packet header.
|
||||
if (availableReadData < ccsds::HEADER_LEN + 1) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
readRingBuf.readData(readBuf, availableReadData);
|
||||
spReader.setReadOnlyData(readBuf, sizeof(readBuf));
|
||||
auto res = spReader.checkSize();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
// The packet might be garbage, with no way to recover without a data link layer.
|
||||
if (spReader.getFullPacketLen() > 4096) {
|
||||
readRingBuf.clear();
|
||||
// TODO: Maybe we should also clear the serial input buffer in Linux?
|
||||
return FAULTY_PACKET_SIZE;
|
||||
}
|
||||
if (availableReadData < spReader.getFullPacketLen()) {
|
||||
// Might be split packet where the rest still has to be read.
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (CRC::crc16ccitt(readBuf, spReader.getFullPacketLen()) != 0) {
|
||||
// Possibly invalid packet. We can not even trust the detected packet length.
|
||||
// Just clear the whole read buffer as well.
|
||||
readRingBuf.clear();
|
||||
triggerEvent(mpsoc::CRC_FAILURE);
|
||||
return CRC_CHECK_FAILED;
|
||||
}
|
||||
readRingBuf.deleteData(spReader.getFullPacketLen());
|
||||
return PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
ReturnValue_t MpsocCommunication::readSerialInterface() {
|
||||
int bytesRead = read(helper.rawFd(), readBuf, sizeof(readBuf));
|
||||
if (bytesRead < 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (bytesRead > 0) {
|
||||
if (MPSOC_LOW_LEVEL_RX_WIRETAPPING) {
|
||||
sif::debug << "Read " << bytesRead << " bytes on the MPSoC interface" << std::endl;
|
||||
}
|
||||
return readRingBuf.writeData(readBuf, bytesRead);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
const SpacePacketReader& MpsocCommunication::getSpReader() const { return spReader; }
|
||||
|
||||
SerialCommunicationHelper& MpsocCommunication::getComHelper() { return helper; }
|
44
linux/payload/MpsocCommunication.h
Normal file
44
linux/payload/MpsocCommunication.h
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/container/SimpleRingBuffer.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
|
||||
#include "linux/payload/SerialCommunicationHelper.h"
|
||||
|
||||
static constexpr bool MPSOC_LOW_LEVEL_TX_WIRETAPPING = false;
|
||||
static constexpr bool MPSOC_LOW_LEVEL_RX_WIRETAPPING = false;
|
||||
|
||||
class MpsocCommunication : public SystemObject {
|
||||
public:
|
||||
static const uint8_t CLASS_ID = CLASS_ID::PLOC_MPSOC_COM;
|
||||
static constexpr ReturnValue_t PACKET_RECEIVED = returnvalue::makeCode(CLASS_ID, 0);
|
||||
static constexpr ReturnValue_t FAULTY_PACKET_SIZE = returnvalue::makeCode(CLASS_ID, 1);
|
||||
static constexpr ReturnValue_t CRC_CHECK_FAILED = returnvalue::makeCode(CLASS_ID, 2);
|
||||
|
||||
MpsocCommunication(object_id_t objectId, SerialConfig cfg);
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
ReturnValue_t send(const uint8_t* data, size_t dataLen);
|
||||
|
||||
// Should be called periodically to transfer the received data from the MPSoC from the Linux
|
||||
// buffer to the internal ring buffer for further processing.
|
||||
ReturnValue_t readSerialInterface();
|
||||
|
||||
// Parses the internal ring buffer for packets and checks whether a packet was received.
|
||||
ReturnValue_t parseAndRetrieveNextPacket();
|
||||
|
||||
// Can be used to read the parse packet, if one was received.
|
||||
const SpacePacketReader& getSpReader() const;
|
||||
|
||||
SerialCommunicationHelper& getComHelper();
|
||||
|
||||
private:
|
||||
SpacePacketReader spReader;
|
||||
uint8_t readBuf[4096];
|
||||
SimpleRingBuffer readRingBuf;
|
||||
SerialCommunicationHelper helper;
|
||||
};
|
@ -6,16 +6,21 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterfacePrinter.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
|
||||
#include "linux/payload/MpsocCommunication.h"
|
||||
#include "linux/payload/plocMpsocHelpers.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/FilesystemHelper.h"
|
||||
#endif
|
||||
|
||||
#include "mission/utility/Timestamp.h"
|
||||
|
||||
using namespace ploc;
|
||||
|
||||
PlocMpsocSpecialComHelper::PlocMpsocSpecialComHelper(object_id_t objectId)
|
||||
: SystemObject(objectId) {
|
||||
PlocMpsocSpecialComHelper::PlocMpsocSpecialComHelper(object_id_t objectId,
|
||||
MpsocCommunication& comInterface)
|
||||
: SystemObject(objectId), comInterface(comInterface) {
|
||||
spParams.buf = commandBuffer;
|
||||
spParams.maxSize = sizeof(commandBuffer);
|
||||
}
|
||||
@ -48,9 +53,9 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode)
|
||||
case InternalState::FLASH_WRITE: {
|
||||
result = performFlashWrite();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, sequenceCount->get());
|
||||
triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, txSequenceCount.get());
|
||||
} else {
|
||||
triggerEvent(MPSOC_FLASH_WRITE_FAILED, sequenceCount->get());
|
||||
triggerEvent(MPSOC_FLASH_WRITE_FAILED, txSequenceCount.get());
|
||||
}
|
||||
internalState = InternalState::IDLE;
|
||||
break;
|
||||
@ -58,9 +63,10 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode)
|
||||
case InternalState::FLASH_READ: {
|
||||
result = performFlashRead();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, sequenceCount->get());
|
||||
triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, txSequenceCount.get());
|
||||
} else {
|
||||
triggerEvent(MPSOC_FLASH_READ_FAILED, sequenceCount->get());
|
||||
sif::printWarning("PLOC MPSoC Helper: Flash read failed with code %04x\n", result);
|
||||
triggerEvent(MPSOC_FLASH_READ_FAILED, txSequenceCount.get(), result);
|
||||
}
|
||||
internalState = InternalState::IDLE;
|
||||
break;
|
||||
@ -72,19 +78,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode)
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::setComIF(DeviceCommunicationIF* communicationInterface_) {
|
||||
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
|
||||
if (uartComIF == nullptr) {
|
||||
sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
void PlocMpsocSpecialComHelper::setCommandSequenceCount(uint16_t sequenceCount_) {
|
||||
txSequenceCount.set(sequenceCount_);
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
|
||||
|
||||
void PlocMpsocSpecialComHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) {
|
||||
sequenceCount = sequenceCount_;
|
||||
uint16_t PlocMpsocSpecialComHelper::getCommandSequenceCount() const {
|
||||
return txSequenceCount.get();
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::startFlashWrite(std::string obcFile,
|
||||
@ -117,7 +116,8 @@ ReturnValue_t PlocMpsocSpecialComHelper::startFlashRead(std::string obcFile, std
|
||||
void PlocMpsocSpecialComHelper::resetHelper() {
|
||||
spParams.buf = commandBuffer;
|
||||
terminate = false;
|
||||
uartComIF->flushUartRxBuffer(comCookie);
|
||||
auto& helper = comInterface.getComHelper();
|
||||
helper.flushUartRxBuffer();
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelper::stopProcess() { terminate = true; }
|
||||
@ -155,7 +155,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() {
|
||||
file.read(reinterpret_cast<char*>(fileBuf.data()), dataLength);
|
||||
bytesRead += dataLength;
|
||||
remainingSize -= dataLength;
|
||||
mpsoc::TcFlashWrite tc(spParams, *sequenceCount);
|
||||
mpsoc::TcFlashWrite tc(spParams, txSequenceCount);
|
||||
result = tc.setPayload(fileBuf.data(), dataLength);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@ -164,7 +164,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
txSequenceCount.increment();
|
||||
result = handlePacketTransmissionNoReply(tc);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@ -179,8 +179,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() {
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
|
||||
std::error_code e;
|
||||
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::trunc | std::ios::binary);
|
||||
if (ofile.bad()) {
|
||||
if (std::filesystem::exists(flashReadAndWrite.obcFile)) {
|
||||
// Truncate the file first.
|
||||
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::binary | std::ios::trunc);
|
||||
}
|
||||
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::binary | std::ios::app);
|
||||
if (ofile.bad() or not ofile.is_open()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result = flashfopen(mpsoc::FileAccessModes::READ);
|
||||
@ -203,7 +207,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return FILE_READ_ERROR;
|
||||
}
|
||||
mpsoc::TcFlashRead flashReadRequest(spParams, *sequenceCount);
|
||||
mpsoc::TcFlashRead flashReadRequest(spParams, txSequenceCount);
|
||||
result = flashReadRequest.setPayload(nextReadSize);
|
||||
if (result != returnvalue::OK) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
@ -214,7 +218,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
txSequenceCount.increment();
|
||||
result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize);
|
||||
if (result != returnvalue::OK) {
|
||||
std::filesystem::remove(flashReadAndWrite.obcFile, e);
|
||||
@ -231,7 +235,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) {
|
||||
spParams.buf = commandBuffer;
|
||||
mpsoc::FlashFopen flashFopen(spParams, *sequenceCount);
|
||||
mpsoc::TcFlashFopen flashFopen(spParams, txSequenceCount);
|
||||
ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@ -240,7 +244,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
txSequenceCount.increment();
|
||||
result = handlePacketTransmissionNoReply(flashFopen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@ -250,12 +254,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) {
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::flashfclose() {
|
||||
spParams.buf = commandBuffer;
|
||||
mpsoc::FlashFclose flashFclose(spParams, *sequenceCount);
|
||||
mpsoc::TcFlashFclose flashFclose(spParams, txSequenceCount);
|
||||
ReturnValue_t result = flashFclose.finishPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
txSequenceCount.increment();
|
||||
result = handlePacketTransmissionNoReply(flashFclose);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@ -278,6 +282,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionFlashRead(mpsoc
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
auto& spReader = comInterface.getSpReader();
|
||||
|
||||
// We have the nominal case where the flash read report appears first, or the case where we
|
||||
// get an EXE failure immediately.
|
||||
@ -288,7 +293,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionFlashRead(mpsoc
|
||||
}
|
||||
return handleExe();
|
||||
} else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) {
|
||||
handleExeFailure();
|
||||
handleExeFailure(spReader);
|
||||
} else {
|
||||
triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast<uint32_t>(internalState));
|
||||
sif::warning << "PLOC MPSoC: Expected execution report "
|
||||
@ -311,8 +316,8 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionNoReply(ploc::S
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::sendCommand(ploc::SpTcBase& tc) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen());
|
||||
ReturnValue_t result = comInterface.send(tc.getFullPacket(), tc.getFullPacketLen());
|
||||
mpsoc::printTxPacket(tc);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl;
|
||||
triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
@ -331,6 +336,8 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleAck() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
const auto& spReader = comInterface.getSpReader();
|
||||
|
||||
uint16_t apid = spReader.getApid();
|
||||
if (apid != mpsoc::apid::ACK_SUCCESS) {
|
||||
handleAckApidFailure(spReader);
|
||||
@ -339,7 +346,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleAck() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelper::handleAckApidFailure(const ploc::SpTmReader& reader) {
|
||||
void PlocMpsocSpecialComHelper::handleAckApidFailure(const SpacePacketReader& reader) {
|
||||
uint16_t apid = reader.getApid();
|
||||
if (apid == mpsoc::apid::ACK_FAILURE) {
|
||||
uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData());
|
||||
@ -363,9 +370,10 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleExe() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
const auto& spReader = comInterface.getSpReader();
|
||||
uint16_t apid = spReader.getApid();
|
||||
if (apid == mpsoc::apid::EXE_FAILURE) {
|
||||
handleExeFailure();
|
||||
handleExeFailure(spReader);
|
||||
return returnvalue::FAILED;
|
||||
} else if (apid != mpsoc::apid::EXE_SUCCESS) {
|
||||
triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast<uint32_t>(internalState));
|
||||
@ -375,7 +383,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleExe() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMpsocSpecialComHelper::handleExeFailure() {
|
||||
void PlocMpsocSpecialComHelper::handleExeFailure(const SpacePacketReader& spReader) {
|
||||
uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData());
|
||||
sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl;
|
||||
triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast<uint32_t>(internalState));
|
||||
@ -384,46 +392,32 @@ void PlocMpsocSpecialComHelper::handleExeFailure() {
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::handleTmReception() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
tmCountdown.resetTimer();
|
||||
size_t readBytes = 0;
|
||||
size_t currentBytes = 0;
|
||||
uint32_t usleepDelay = 5;
|
||||
size_t fullPacketLen = 0;
|
||||
while (true) {
|
||||
if (tmCountdown.hasTimedOut()) {
|
||||
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = receive(tmBuf.data() + readBytes, 6, ¤tBytes);
|
||||
result = tryReceiveNextReply();
|
||||
if (result == MpsocCommunication::PACKET_RECEIVED) {
|
||||
// Need to convert this, we are faking a synchronous API here.
|
||||
result = returnvalue::OK;
|
||||
break;
|
||||
}
|
||||
if (result != returnvalue::OK) {
|
||||
if (result == MpsocCommunication::FAULTY_PACKET_SIZE) {
|
||||
sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed: faulty packet size\n");
|
||||
} else if (result == MpsocCommunication::CRC_CHECK_FAILED) {
|
||||
sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed: CRC check failed\n");
|
||||
}
|
||||
sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed with code %d\n", result);
|
||||
return result;
|
||||
}
|
||||
spReader.setReadOnlyData(tmBuf.data(), tmBuf.size());
|
||||
fullPacketLen = spReader.getFullPacketLen();
|
||||
readBytes += currentBytes;
|
||||
if (readBytes == 6) {
|
||||
break;
|
||||
}
|
||||
usleep(usleepDelay);
|
||||
if (usleepDelay < 200000) {
|
||||
usleepDelay *= 4;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
if (tmCountdown.hasTimedOut()) {
|
||||
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = receive(tmBuf.data() + readBytes, fullPacketLen - readBytes, ¤tBytes);
|
||||
readBytes += currentBytes;
|
||||
if (fullPacketLen == readBytes) {
|
||||
break;
|
||||
}
|
||||
usleep(usleepDelay);
|
||||
if (usleepDelay < 200000) {
|
||||
usleepDelay *= 4;
|
||||
}
|
||||
}
|
||||
// arrayprinter::print(tmBuf.data(), readBytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -433,6 +427,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleFlashReadReply(std::ofstream& ofi
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
auto& spReader = comInterface.getSpReader();
|
||||
uint16_t apid = spReader.getApid();
|
||||
if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) {
|
||||
triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR);
|
||||
@ -498,47 +493,25 @@ ReturnValue_t PlocMpsocSpecialComHelper::startFlashReadOrWriteBase(std::string o
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() {
|
||||
const auto& spReader = comInterface.getSpReader();
|
||||
ReturnValue_t result = spReader.checkSize();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl;
|
||||
triggerEvent(MPSOC_TM_SIZE_ERROR);
|
||||
return result;
|
||||
}
|
||||
result = spReader.checkCrc();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PLOC MPSoC: CRC check failed" << std::endl;
|
||||
triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount);
|
||||
return result;
|
||||
}
|
||||
uint16_t recvSeqCnt = spReader.getSequenceCount();
|
||||
if (recvSeqCnt != *sequenceCount) {
|
||||
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
|
||||
*sequenceCount = recvSeqCnt;
|
||||
}
|
||||
// This sequence count ping pong does not make any sense but it is how the MPSoC expects it.
|
||||
(*sequenceCount)++;
|
||||
rxSequenceCount = spReader.getSequenceCount();
|
||||
mpsoc::printRxPacket(spReader);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::receive(uint8_t* data, size_t requestBytes,
|
||||
size_t* readBytes) {
|
||||
ReturnValue_t PlocMpsocSpecialComHelper::tryReceiveNextReply() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint8_t* buffer = nullptr;
|
||||
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
|
||||
result = comInterface.readSerialInterface();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl;
|
||||
triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result,
|
||||
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl;
|
||||
triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (*readBytes > 0) {
|
||||
std::memcpy(data, buffer, *readBytes);
|
||||
}
|
||||
return result;
|
||||
return comInterface.parseAndRetrieveNextPacket();
|
||||
}
|
||||
|
@ -6,14 +6,13 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
|
||||
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
#include "linux/payload/MpsocCommunication.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
@ -83,15 +82,12 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF
|
||||
FLASH_READ_READLEN_ERROR = 2
|
||||
};
|
||||
|
||||
PlocMpsocSpecialComHelper(object_id_t objectId);
|
||||
PlocMpsocSpecialComHelper(object_id_t objectId, MpsocCommunication& comInterface);
|
||||
virtual ~PlocMpsocSpecialComHelper();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
|
||||
ReturnValue_t setComIF(DeviceCommunicationIF* communicationInterface_);
|
||||
void setComCookie(CookieIF* comCookie_);
|
||||
|
||||
/**
|
||||
* @brief Starts flash write sequence
|
||||
*
|
||||
@ -118,7 +114,8 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF
|
||||
/**
|
||||
* @brief Sets the sequence count object responsible for the sequence count handling
|
||||
*/
|
||||
void setSequenceCount(SourceSequenceCounter* sequenceCount_);
|
||||
void setCommandSequenceCount(uint16_t sequenceCount_);
|
||||
uint16_t getCommandSequenceCount() const;
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER;
|
||||
@ -169,12 +166,14 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF
|
||||
* Communication interface of MPSoC responsible for low level access. Must be set by the
|
||||
* MPSoC Handler.
|
||||
*/
|
||||
SerialComIF* uartComIF = nullptr;
|
||||
// SerialComIF* uartComIF = nullptr;
|
||||
// Communication cookie. Must be set by the MPSoC Handler
|
||||
CookieIF* comCookie = nullptr;
|
||||
// CookieIF* comCookie = nullptr;
|
||||
MpsocCommunication& comInterface;
|
||||
// Sequence count, must be set by Ploc MPSoC Handler
|
||||
SourceSequenceCounter* sequenceCount = nullptr;
|
||||
ploc::SpTmReader spReader;
|
||||
// ploc::SpTmReader spReader;
|
||||
uint16_t rxSequenceCount = 0;
|
||||
SourceSequenceCounter txSequenceCount = 0;
|
||||
|
||||
void resetHelper();
|
||||
ReturnValue_t performFlashWrite();
|
||||
@ -186,13 +185,13 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF
|
||||
size_t expectedReadLen);
|
||||
ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen);
|
||||
ReturnValue_t sendCommand(ploc::SpTcBase& tc);
|
||||
ReturnValue_t receive(uint8_t* data, size_t requestBytes, size_t* readBytes);
|
||||
ReturnValue_t tryReceiveNextReply();
|
||||
ReturnValue_t handleAck();
|
||||
ReturnValue_t handleExe();
|
||||
ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile);
|
||||
ReturnValue_t fileCheck(std::string obcFile);
|
||||
void handleAckApidFailure(const ploc::SpTmReader& reader);
|
||||
void handleExeFailure();
|
||||
void handleAckApidFailure(const SpacePacketReader& reader);
|
||||
void handleExeFailure(const SpacePacketReader& reader);
|
||||
ReturnValue_t handleTmReception();
|
||||
ReturnValue_t checkReceivedTm();
|
||||
};
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <fstream>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "linux/payload/plocSupvDefs.h"
|
||||
#include "tas/hdlc.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/FilesystemHelper.h"
|
||||
@ -21,9 +23,13 @@
|
||||
|
||||
#include "fsfw/tasks/TaskFactory.h"
|
||||
#include "fsfw/timemanager/Countdown.h"
|
||||
|
||||
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
#include "mission/utility/Filenaming.h"
|
||||
#include "mission/utility/ProgressPrinter.h"
|
||||
#include "mission/utility/Timestamp.h"
|
||||
#endif
|
||||
|
||||
#include "tas/crc.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
@ -277,23 +283,6 @@ ReturnValue_t PlocSupvUartManager::initiateUpdateContinuation() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
// ReturnValue_t PlocSupvHelper::startEventBufferRequest(std::string path) {
|
||||
// #ifdef XIPHOS_Q7S
|
||||
// ReturnValue_t result = FilesystemHelper::checkPath(path);
|
||||
// if (result != returnvalue::OK) {
|
||||
// return result;
|
||||
// }
|
||||
// #endif
|
||||
// if (not std::filesystem::exists(path)) {
|
||||
// return PATH_NOT_EXISTS;
|
||||
// }
|
||||
// eventBufferReq.path = path;
|
||||
// request = Request::REQUEST_EVENT_BUFFER;
|
||||
// //uartComIF->flushUartTxAndRxBuf(comCookie);
|
||||
// semaphore->release();
|
||||
// return returnvalue::OK;
|
||||
// }
|
||||
|
||||
void PlocSupvUartManager::stop() {
|
||||
MutexGuard mg(lock);
|
||||
if (state == InternalState::SLEEPING or state == InternalState::GO_TO_SLEEP) {
|
||||
@ -437,6 +426,8 @@ ReturnValue_t PlocSupvUartManager::writeUpdatePackets() {
|
||||
// Useful to allow restarting the update
|
||||
triggerEvent(SUPV_UPDATE_PROGRESS, buildProgParams1(progPercent, update.sequenceCount),
|
||||
update.bytesWritten);
|
||||
sif::info << "PLOC SUPV update progress " << (int)progPercent << " % at "
|
||||
<< update.bytesWritten << " bytes" << std::endl;
|
||||
}
|
||||
}
|
||||
supv::WriteMemory packet(spParams);
|
||||
@ -447,10 +438,8 @@ ReturnValue_t PlocSupvUartManager::writeUpdatePackets() {
|
||||
update.bytesWritten);
|
||||
return result;
|
||||
}
|
||||
result = handlePacketTransmissionNoReply(packet, 5000);
|
||||
result = writeMemoryHandlingWithRetryLogic(packet, progPercent);
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(WRITE_MEMORY_FAILED, buildProgParams1(progPercent, update.sequenceCount),
|
||||
update.bytesWritten);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -461,7 +450,25 @@ ReturnValue_t PlocSupvUartManager::writeUpdatePackets() {
|
||||
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
progressPrinter.print(update.bytesWritten);
|
||||
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
|
||||
// TaskFactory::delayTask(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvUartManager::writeMemoryHandlingWithRetryLogic(supv::WriteMemory& packet,
|
||||
unsigned progPercent) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
// Simple re-try logic in place to deal with communication unreliability in orbit.
|
||||
for (uint8_t retryCount = 0; retryCount < MAX_RETRY_COUNT; retryCount++) {
|
||||
result = handlePacketTransmissionNoReply(packet, COM_TIMEOUT_MS);
|
||||
if (result == returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
triggerEvent(WRITE_MEMORY_FAILED, buildProgParams1(progPercent, update.sequenceCount),
|
||||
update.bytesWritten);
|
||||
// Clear data structures related to reply handling.
|
||||
serial::flushTxRxBuf(serialPort);
|
||||
recRingBuf.clear();
|
||||
decodedRingBuf.clear();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -570,7 +577,16 @@ ReturnValue_t PlocSupvUartManager::handlePacketTransmissionNoReply(
|
||||
bool ackReceived = false;
|
||||
bool packetWasHandled = false;
|
||||
while (true) {
|
||||
handleUartReception();
|
||||
ReturnValue_t status = handleUartReception();
|
||||
if (status != returnvalue::OK) {
|
||||
result = status;
|
||||
if (result == HDLC_ERROR) {
|
||||
// We could bail here immediately.. but I prefer to wait for the timeout, because we should
|
||||
// ensure that all packets which might be related to the transfer are still received and
|
||||
// cleared from all data structures related to reply handling.
|
||||
// return result;
|
||||
}
|
||||
}
|
||||
if (not decodedQueue.empty()) {
|
||||
size_t packetLen = 0;
|
||||
decodedQueue.retrieve(&packetLen);
|
||||
@ -613,7 +629,7 @@ ReturnValue_t PlocSupvUartManager::handlePacketTransmissionNoReply(
|
||||
return result::NO_REPLY_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
int PlocSupvUartManager::handleAckReception(supv::TcBase& tc, size_t packetLen) {
|
||||
@ -945,15 +961,7 @@ ReturnValue_t PlocSupvUartManager::handleRunningLongerRequest() {
|
||||
break;
|
||||
}
|
||||
case Request::REQUEST_EVENT_BUFFER: {
|
||||
// result = performEventBufferRequest();
|
||||
// if (result == returnvalue::OK) {
|
||||
// triggerEvent(SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL, result);
|
||||
// } else if (result == PROCESS_TERMINATED) {
|
||||
// // Event already triggered
|
||||
// break;
|
||||
// } else {
|
||||
// triggerEvent(SUPV_EVENT_BUFFER_REQUEST_FAILED, result);
|
||||
// }
|
||||
sif::error << "Requesting event buffer is not implemented" << std::endl;
|
||||
break;
|
||||
}
|
||||
case Request::DEFAULT: {
|
||||
|
@ -118,6 +118,7 @@ class PlocSupvUartManager : public DeviceCommunicationIF,
|
||||
static constexpr Event HDLC_FRAME_REMOVAL_ERROR = MAKE_EVENT(31, severity::INFO);
|
||||
static constexpr Event HDLC_CRC_ERROR = MAKE_EVENT(32, severity::INFO);
|
||||
|
||||
static constexpr unsigned MAX_RETRY_COUNT = 3;
|
||||
PlocSupvUartManager(object_id_t objectId);
|
||||
virtual ~PlocSupvUartManager();
|
||||
/**
|
||||
@ -199,6 +200,8 @@ class PlocSupvUartManager : public DeviceCommunicationIF,
|
||||
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS_CONSECUTIVE_END = returnvalue::makeCode(1, 4);
|
||||
static constexpr ReturnValue_t HDLC_ERROR = returnvalue::makeCode(1, 5);
|
||||
|
||||
static constexpr uint32_t COM_TIMEOUT_MS = 3000;
|
||||
|
||||
static const uint16_t CRC16_INIT = 0xFFFF;
|
||||
// Event buffer reply will carry 24 space packets with 1016 bytes and one space packet with
|
||||
// 192 bytes
|
||||
@ -369,6 +372,8 @@ class PlocSupvUartManager : public DeviceCommunicationIF,
|
||||
*/
|
||||
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
|
||||
|
||||
ReturnValue_t writeMemoryHandlingWithRetryLogic(supv::WriteMemory& packet, unsigned progPercent);
|
||||
|
||||
void performUartShutdown();
|
||||
void updateVtime(uint8_t vtime);
|
||||
};
|
||||
|
126
linux/payload/SerialCommunicationHelper.cpp
Normal file
126
linux/payload/SerialCommunicationHelper.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include "SerialCommunicationHelper.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw_hal/linux/serial/helper.h"
|
||||
|
||||
SerialCommunicationHelper::SerialCommunicationHelper(SerialConfig cfg) : cfg(cfg) {}
|
||||
|
||||
ReturnValue_t SerialCommunicationHelper::initialize() {
|
||||
fd = configureUartPort();
|
||||
if (fd < 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
int SerialCommunicationHelper::rawFd() const { return fd; }
|
||||
|
||||
ReturnValue_t SerialCommunicationHelper::send(const uint8_t* data, size_t dataLen) {
|
||||
if (write(fd, data, dataLen) != static_cast<int>(dataLen)) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "UartComIF::sendMessage: Failed to send data with error code " << errno
|
||||
<< ": Error description: " << strerror(errno) << std::endl;
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
int SerialCommunicationHelper::configureUartPort() {
|
||||
struct termios options = {};
|
||||
|
||||
int flags = O_RDWR;
|
||||
if (cfg.getUartMode() == UartModes::CANONICAL) {
|
||||
// In non-canonical mode, don't specify O_NONBLOCK because these properties will be
|
||||
// controlled by the VTIME and VMIN parameters and O_NONBLOCK would override this
|
||||
flags |= O_NONBLOCK;
|
||||
}
|
||||
int fd = open(cfg.getDeviceFile().c_str(), flags);
|
||||
|
||||
if (fd < 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UartComIF::configureUartPort: Failed to open uart "
|
||||
<< cfg.getDeviceFile().c_str()
|
||||
|
||||
<< "with error code " << errno << strerror(errno) << std::endl;
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Read in existing settings */
|
||||
if (tcgetattr(fd, &options) != 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UartComIF::configureUartPort: Error " << errno
|
||||
<< "from tcgetattr: " << strerror(errno) << std::endl;
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
serial::setParity(options, cfg.getParity());
|
||||
serial::setStopbits(options, cfg.getStopBits());
|
||||
serial::setBitsPerWord(options, cfg.getBitsPerWord());
|
||||
setFixedOptions(&options);
|
||||
serial::setMode(options, cfg.getUartMode());
|
||||
tcflush(fd, TCIFLUSH);
|
||||
|
||||
/* Sets uart to non-blocking mode. Read returns immediately when there are no data available */
|
||||
options.c_cc[VTIME] = 0;
|
||||
options.c_cc[VMIN] = 0;
|
||||
|
||||
serial::setBaudrate(options, cfg.getBaudrate());
|
||||
|
||||
/* Save option settings */
|
||||
if (tcsetattr(fd, TCSANOW, &options) != 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UartComIF::configureUartPort: Failed to set options with error " << errno
|
||||
<< ": " << strerror(errno);
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void SerialCommunicationHelper::setFixedOptions(struct termios* options) {
|
||||
/* Disable RTS/CTS hardware flow control */
|
||||
options->c_cflag &= ~CRTSCTS;
|
||||
/* Turn on READ & ignore ctrl lines (CLOCAL = 1) */
|
||||
options->c_cflag |= CREAD | CLOCAL;
|
||||
/* Disable echo */
|
||||
options->c_lflag &= ~ECHO;
|
||||
/* Disable erasure */
|
||||
options->c_lflag &= ~ECHOE;
|
||||
/* Disable new-line echo */
|
||||
options->c_lflag &= ~ECHONL;
|
||||
/* Disable interpretation of INTR, QUIT and SUSP */
|
||||
options->c_lflag &= ~ISIG;
|
||||
/* Turn off s/w flow ctrl */
|
||||
options->c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
/* Disable any special handling of received bytes */
|
||||
options->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
|
||||
/* Prevent special interpretation of output bytes (e.g. newline chars) */
|
||||
options->c_oflag &= ~OPOST;
|
||||
/* Prevent conversion of newline to carriage return/line feed */
|
||||
options->c_oflag &= ~ONLCR;
|
||||
}
|
||||
|
||||
ReturnValue_t SerialCommunicationHelper::flushUartRxBuffer() {
|
||||
serial::flushRxBuf(fd);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SerialCommunicationHelper::flushUartTxBuffer() {
|
||||
serial::flushTxBuf(fd);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SerialCommunicationHelper::flushUartTxAndRxBuf() {
|
||||
serial::flushTxRxBuf(fd);
|
||||
return returnvalue::OK;
|
||||
}
|
69
linux/payload/SerialCommunicationHelper.h
Normal file
69
linux/payload/SerialCommunicationHelper.h
Normal file
@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw_hal/linux/serial/SerialCookie.h>
|
||||
#include <fsfw_hal/linux/serial/helper.h>
|
||||
|
||||
#include "SerialConfig.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
/**
|
||||
* @brief This is the communication interface to access serial ports on linux based operating
|
||||
* systems.
|
||||
*
|
||||
* @details The implementation follows the instructions from https://blog.mbedded.ninja/programming/
|
||||
* operating-systems/linux/linux-serial-ports-using-c-cpp/#disabling-canonical-mode
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class SerialCommunicationHelper {
|
||||
public:
|
||||
SerialCommunicationHelper(SerialConfig serialCfg);
|
||||
|
||||
ReturnValue_t send(const uint8_t* data, size_t dataLen);
|
||||
|
||||
int rawFd() const;
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
/**
|
||||
* @brief This function discards all data received but not read in the UART buffer.
|
||||
*/
|
||||
ReturnValue_t flushUartRxBuffer();
|
||||
|
||||
/**
|
||||
* @brief This function discards all data in the transmit buffer of the UART driver.
|
||||
*/
|
||||
ReturnValue_t flushUartTxBuffer();
|
||||
|
||||
/**
|
||||
* @brief This function discards both data in the transmit and receive buffer of the UART.
|
||||
*/
|
||||
ReturnValue_t flushUartTxAndRxBuf();
|
||||
|
||||
private:
|
||||
SerialConfig cfg;
|
||||
int fd = 0;
|
||||
|
||||
/**
|
||||
* @brief This function opens and configures a uart device by using the information stored
|
||||
* in the uart cookie.
|
||||
* @param uartCookie Pointer to uart cookie with information about the uart. Contains the
|
||||
* uart device file, baudrate, parity, stopbits etc.
|
||||
* @return The file descriptor of the configured uart.
|
||||
*/
|
||||
int configureUartPort();
|
||||
|
||||
void setStopBitOptions(struct termios* options);
|
||||
|
||||
/**
|
||||
* @brief This function sets options which are not configurable by the uartCookie.
|
||||
*/
|
||||
void setFixedOptions(struct termios* options);
|
||||
|
||||
/**
|
||||
* @brief With this function the datasize settings are added to the termios options struct.
|
||||
*/
|
||||
void setDatasizeOptions(struct termios* options);
|
||||
};
|
70
linux/payload/SerialConfig.h
Normal file
70
linux/payload/SerialConfig.h
Normal file
@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
#include <fsfw_hal/linux/serial/helper.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief Cookie for the UartComIF. There are many options available to configure the UART driver.
|
||||
* The constructor only requests for common options like the baudrate. Other options can
|
||||
* be set by member functions.
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class SerialConfig : public CookieIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the uart cookie.
|
||||
* @param deviceFile The device file specifying the uart to use, e.g. "/dev/ttyPS1"
|
||||
* @param uartMode Specify the UART mode. The canonical mode should be used if the
|
||||
* messages are separated by a delimited character like '\n'. See the
|
||||
* termios documentation for more information
|
||||
* @param baudrate The baudrate to use for input and output.
|
||||
* @param maxReplyLen The maximum size an object using this cookie expects
|
||||
* @details
|
||||
* Default configuration: No parity
|
||||
* 8 databits (number of bits transfered with one uart frame)
|
||||
* One stop bit
|
||||
*/
|
||||
SerialConfig(std::string deviceFile, UartBaudRate baudrate, size_t maxReplyLen,
|
||||
UartModes uartMode = UartModes::NON_CANONICAL)
|
||||
: deviceFile(deviceFile), baudrate(baudrate), maxReplyLen(maxReplyLen), uartMode(uartMode) {}
|
||||
|
||||
virtual ~SerialConfig() = default;
|
||||
|
||||
UartBaudRate getBaudrate() const { return baudrate; }
|
||||
size_t getMaxReplyLen() const { return maxReplyLen; }
|
||||
std::string getDeviceFile() const { return deviceFile; }
|
||||
Parity getParity() const { return parity; }
|
||||
BitsPerWord getBitsPerWord() const { return bitsPerWord; }
|
||||
StopBits getStopBits() const { return stopBits; }
|
||||
UartModes getUartMode() const { return uartMode; }
|
||||
|
||||
/**
|
||||
* Functions two enable parity checking.
|
||||
*/
|
||||
void setParityOdd() { parity = Parity::ODD; }
|
||||
void setParityEven() { parity = Parity::EVEN; }
|
||||
|
||||
/**
|
||||
* Function two set number of bits per UART frame.
|
||||
*/
|
||||
void setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
|
||||
|
||||
/**
|
||||
* Function to specify the number of stopbits.
|
||||
*/
|
||||
void setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; }
|
||||
void setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; }
|
||||
|
||||
private:
|
||||
std::string deviceFile;
|
||||
UartBaudRate baudrate;
|
||||
size_t maxReplyLen = 0;
|
||||
const UartModes uartMode;
|
||||
Parity parity = Parity::NONE;
|
||||
BitsPerWord bitsPerWord = BitsPerWord::BITS_8;
|
||||
StopBits stopBits = StopBits::ONE_STOP_BIT;
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
#ifndef MPSOC_RETURN_VALUES_IF_H_
|
||||
#define MPSOC_RETURN_VALUES_IF_H_
|
||||
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
class MPSoCReturnValuesIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::MPSOC_RETURN_VALUES_IF;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Space Packet received from PLOC has invalid CRC
|
||||
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0);
|
||||
//! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC
|
||||
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1);
|
||||
//! [EXPORT] : [COMMENT] Received execution failure reply from PLOC
|
||||
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2);
|
||||
//! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC
|
||||
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3);
|
||||
//! [EXPORT] : [COMMENT] Received command with invalid length
|
||||
static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xA4);
|
||||
//! [EXPORT] : [COMMENT] Filename of file in OBC filesystem is too long
|
||||
static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA5);
|
||||
//! [EXPORT] : [COMMENT] MPSoC helper is currently executing a command
|
||||
static const ReturnValue_t MPSOC_HELPER_EXECUTING = MAKE_RETURN_CODE(0xA6);
|
||||
//! [EXPORT] : [COMMENT] Filename of MPSoC file is to long (max. 256 bytes)
|
||||
static const ReturnValue_t MPSOC_FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA7);
|
||||
//! [EXPORT] : [COMMENT] Command has invalid parameter
|
||||
static const ReturnValue_t INVALID_PARAMETER = MAKE_RETURN_CODE(0xA8);
|
||||
//! [EXPORT] : [COMMENT] Received command has file string with invalid length
|
||||
static const ReturnValue_t NAME_TOO_LONG = MAKE_RETURN_CODE(0xA9);
|
||||
};
|
||||
|
||||
#endif /* MPSOC_RETURN_VALUES_IF_H_ */
|
@ -1,87 +1,94 @@
|
||||
#include "plocMpsocHelpers.h"
|
||||
|
||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
|
||||
#include "mission/payload/plocSpBase.h"
|
||||
|
||||
uint16_t mpsoc::getStatusFromRawData(const uint8_t* data) {
|
||||
return (*(data + STATUS_OFFSET) << 8) | *(data + STATUS_OFFSET + 1);
|
||||
}
|
||||
std::string mpsoc::getStatusString(uint16_t status) {
|
||||
switch (status) {
|
||||
case (mpsoc::status_code::UNKNOWN_APID): {
|
||||
case (mpsoc::statusCode::UNKNOWN_APID): {
|
||||
return "Unknown APID";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INCORRECT_LENGTH): {
|
||||
case (mpsoc::statusCode::INCORRECT_LENGTH): {
|
||||
return "Incorrect length";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INCORRECT_CRC): {
|
||||
case (mpsoc::statusCode::FLASH_DRIVE_ERROR): {
|
||||
return "flash drive error";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::statusCode::INCORRECT_CRC): {
|
||||
return "Incorrect crc";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INCORRECT_PKT_SEQ_CNT): {
|
||||
case (mpsoc::statusCode::INCORRECT_PKT_SEQ_CNT): {
|
||||
return "Incorrect packet sequence count";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::TC_NOT_ALLOWED_IN_MODE): {
|
||||
case (mpsoc::statusCode::TC_NOT_ALLOWED_IN_MODE): {
|
||||
return "TC not allowed in this mode";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::TC_EXEUTION_DISABLED): {
|
||||
case (mpsoc::statusCode::TC_EXEUTION_DISABLED): {
|
||||
return "TC execution disabled";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_MOUNT_FAILED): {
|
||||
case (mpsoc::statusCode::FLASH_MOUNT_FAILED): {
|
||||
return "Flash mount failed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_FILE_ALREADY_OPEN): {
|
||||
case (mpsoc::statusCode::FLASH_FILE_ALREADY_OPEN): {
|
||||
return "Flash file already open";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_FILE_ALREADY_CLOSED): {
|
||||
case (mpsoc::statusCode::FLASH_FILE_ALREADY_CLOSED): {
|
||||
return "Flash file already closed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_FILE_OPEN_FAILED): {
|
||||
case (mpsoc::statusCode::FLASH_FILE_OPEN_FAILED): {
|
||||
return "Flash file open failed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_FILE_NOT_OPEN): {
|
||||
case (mpsoc::statusCode::FLASH_FILE_NOT_OPEN): {
|
||||
return "Flash file not open";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_UNMOUNT_FAILED): {
|
||||
case (mpsoc::statusCode::FLASH_UNMOUNT_FAILED): {
|
||||
return "Flash unmount failed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::HEAP_ALLOCATION_FAILED): {
|
||||
case (mpsoc::statusCode::HEAP_ALLOCATION_FAILED): {
|
||||
return "Heap allocation failed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INVALID_PARAMETER): {
|
||||
case (mpsoc::statusCode::INVALID_PARAMETER): {
|
||||
return "Invalid parameter";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::NOT_INITIALIZED): {
|
||||
case (mpsoc::statusCode::NOT_INITIALIZED): {
|
||||
return "Not initialized";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::REBOOT_IMMINENT): {
|
||||
case (mpsoc::statusCode::REBOOT_IMMINENT): {
|
||||
return "Reboot imminent";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::CORRUPT_DATA): {
|
||||
case (mpsoc::statusCode::CORRUPT_DATA): {
|
||||
return "Corrupt data";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_CORRECTABLE_MISMATCH): {
|
||||
case (mpsoc::statusCode::FLASH_CORRECTABLE_MISMATCH): {
|
||||
return "Flash correctable mismatch";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_UNCORRECTABLE_MISMATCH): {
|
||||
case (mpsoc::statusCode::FLASH_UNCORRECTABLE_MISMATCH): {
|
||||
return "Flash uncorrectable mismatch";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::DEFAULT_ERROR_CODE): {
|
||||
case (mpsoc::statusCode::DEFAULT_ERROR_CODE): {
|
||||
return "Default error code";
|
||||
break;
|
||||
}
|
||||
@ -93,3 +100,19 @@ std::string mpsoc::getStatusString(uint16_t status) {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void mpsoc::printRxPacket(const SpacePacketReader& spReader) {
|
||||
if (mpsoc::MPSOC_RX_WIRETAPPING) {
|
||||
sif::debug << "RECV MPSOC packet. APID 0x" << std::hex << std::setw(3) << spReader.getApid()
|
||||
<< std::dec << " Size " << spReader.getFullPacketLen() << " SSC "
|
||||
<< spReader.getSequenceCount() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void mpsoc::printTxPacket(const ploc::SpTcBase& tcBase) {
|
||||
if (mpsoc::MPSOC_TX_WIRETAPPING) {
|
||||
sif::debug << "SEND MPSOC packet. APID 0x" << std::hex << std::setw(3) << tcBase.getApid()
|
||||
<< " Size " << std::dec << tcBase.getFullPacketLen() << " SSC "
|
||||
<< tcBase.getSeqCount() << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,124 @@
|
||||
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <linux/payload/mpsocRetvals.h>
|
||||
#include <mission/payload/plocSpBase.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/action/HasActionsIF.h"
|
||||
#include "fsfw/events/Event.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
|
||||
namespace mpsoc {
|
||||
|
||||
static constexpr bool MPSOC_TX_WIRETAPPING = false;
|
||||
static constexpr bool MPSOC_RX_WIRETAPPING = false;
|
||||
|
||||
static constexpr size_t CRC_SIZE = 2;
|
||||
|
||||
/**
|
||||
* @brief Abstract base class for TC space packet of MPSoC.
|
||||
*/
|
||||
class TcBase : public ploc::SpTcBase {
|
||||
public:
|
||||
virtual ~TcBase() = default;
|
||||
|
||||
// Initial length field of space packet. Will always be updated when packet is created.
|
||||
static const uint16_t INIT_LENGTH = CRC_SIZE;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param sequenceCount Sequence count of space packet which will be incremented with each
|
||||
* sent and received packets.
|
||||
*/
|
||||
TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount)
|
||||
: ploc::SpTcBase(params, apid, 0, sequenceCount) {
|
||||
payloadStart = spParams.buf + ccsds::HEADER_LEN;
|
||||
spParams.setFullPayloadLen(INIT_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to finsh and write the space packet. It is expected that the user has
|
||||
* set the payload fields in the child class*
|
||||
* @return returnvalue::OK if packet creation was successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t finishPacket() {
|
||||
updateSpFields();
|
||||
ReturnValue_t res = checkSizeAndSerializeHeader();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
return calcAndSetCrc();
|
||||
}
|
||||
};
|
||||
|
||||
void printRxPacket(const SpacePacketReader& spReader);
|
||||
void printTxPacket(const ploc::SpTcBase& tcBase);
|
||||
|
||||
static constexpr uint32_t DEFAULT_CMD_TIMEOUT_MS = 5000;
|
||||
static constexpr uint32_t CMD_TIMEOUT_MKFS = 15000;
|
||||
|
||||
enum FlashId : uint8_t { FLASH_0 = 0, FLASH_1 = 1 };
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::MPSOC_RETURN_VALUES_IF;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Space Packet received from PLOC has invalid CRC
|
||||
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0);
|
||||
//! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC
|
||||
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1);
|
||||
//! [EXPORT] : [COMMENT] Received execution failure reply from PLOC
|
||||
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2);
|
||||
//! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC
|
||||
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3);
|
||||
//! [EXPORT] : [COMMENT] Received command with invalid length
|
||||
static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xA4);
|
||||
//! [EXPORT] : [COMMENT] Filename of file in OBC filesystem is too long
|
||||
static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA5);
|
||||
//! [EXPORT] : [COMMENT] MPSoC helper is currently executing a command
|
||||
static const ReturnValue_t MPSOC_HELPER_EXECUTING = MAKE_RETURN_CODE(0xA6);
|
||||
//! [EXPORT] : [COMMENT] Filename of MPSoC file is to long (max. 256 bytes)
|
||||
static const ReturnValue_t MPSOC_FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA7);
|
||||
//! [EXPORT] : [COMMENT] Command has invalid parameter
|
||||
static const ReturnValue_t INVALID_PARAMETER = MAKE_RETURN_CODE(0xA8);
|
||||
//! [EXPORT] : [COMMENT] Received command has file string with invalid length
|
||||
static const ReturnValue_t NAME_TOO_LONG = MAKE_RETURN_CODE(0xA9);
|
||||
//! [EXPORT] : [COMMENT] Command has timed out.
|
||||
static const ReturnValue_t COMMAND_TIMEOUT = MAKE_RETURN_CODE(0x10);
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] PLOC crc failure in telemetry packet
|
||||
static const Event MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] PLOC receive acknowledgment failure report
|
||||
//! P1: Command Id which leads the acknowledgment failure report
|
||||
//! P2: The status field inserted by the MPSoC into the data field
|
||||
static const Event ACK_FAILURE = MAKE_EVENT(2, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] PLOC receive execution failure report
|
||||
//! P1: Command Id which leads the execution failure report
|
||||
//! P2: The status field inserted by the MPSoC into the data field
|
||||
static const Event EXE_FAILURE = MAKE_EVENT(3, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] PLOC reply has invalid crc
|
||||
static const Event MPSOC_HANDLER_CRC_FAILURE = MAKE_EVENT(4, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Packet sequence count in received space packet does not match expected
|
||||
//! count P1: Expected sequence count P2: Received sequence count
|
||||
static const Event MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH = MAKE_EVENT(5, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and
|
||||
//! thus also to shutdown the supervisor.
|
||||
static const Event MPSOC_SHUTDOWN_FAILED = MAKE_EVENT(6, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for
|
||||
//! ON transition.
|
||||
static constexpr Event SUPV_NOT_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] SUPV reply timeout.
|
||||
static constexpr Event SUPV_REPLY_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 8, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Camera must be commanded on first.
|
||||
static constexpr Event CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE =
|
||||
event::makeEvent(SUBSYSTEM_ID, 9, severity::LOW);
|
||||
|
||||
enum ParamId : uint8_t { SKIP_SUPV_ON_COMMANDING = 0x01 };
|
||||
|
||||
enum FileAccessModes : uint8_t {
|
||||
// Opens a file, fails if the file does not exist.
|
||||
OPEN_EXISTING = 0x00,
|
||||
@ -28,6 +136,8 @@ enum FileAccessModes : uint8_t {
|
||||
};
|
||||
|
||||
static constexpr uint32_t HK_SET_ID = 0;
|
||||
static constexpr uint32_t DEADBEEF_ADDR = 0x40000004;
|
||||
static constexpr uint32_t DEADBEEF_VALUE = 0xdeadbeef;
|
||||
|
||||
namespace poolid {
|
||||
enum {
|
||||
@ -90,7 +200,8 @@ static const DeviceCommandId_t TM_CAM_CMD_RPT = 19;
|
||||
static const DeviceCommandId_t SET_UART_TX_TRISTATE = 20;
|
||||
static const DeviceCommandId_t RELEASE_UART_TX = 21;
|
||||
static const DeviceCommandId_t TC_CAM_TAKE_PIC = 22;
|
||||
static const DeviceCommandId_t TC_SIMPLEX_SEND_FILE = 23;
|
||||
// Stream file down using E-Band component directly.
|
||||
static const DeviceCommandId_t TC_SIMPLEX_STREAM_FILE = 23;
|
||||
static const DeviceCommandId_t TC_DOWNLINK_DATA_MODULATE = 24;
|
||||
static const DeviceCommandId_t TC_MODE_SNAPSHOT = 25;
|
||||
static const DeviceCommandId_t TC_GET_HK_REPORT = 26;
|
||||
@ -98,16 +209,31 @@ static const DeviceCommandId_t TM_GET_HK_REPORT = 27;
|
||||
static const DeviceCommandId_t TC_FLASH_GET_DIRECTORY_CONTENT = 28;
|
||||
static const DeviceCommandId_t TM_FLASH_DIRECTORY_CONTENT = 29;
|
||||
static constexpr DeviceCommandId_t TC_FLASH_READ_FULL_FILE = 30;
|
||||
// Store file on MPSoC.
|
||||
static const DeviceCommandId_t TC_SPLIT_FILE = 31;
|
||||
static const DeviceCommandId_t TC_VERIFY_BOOT = 32;
|
||||
static const DeviceCommandId_t TC_ENABLE_TC_EXECTION = 33;
|
||||
static const DeviceCommandId_t TC_FLASH_MKFS = 34;
|
||||
|
||||
// Will reset the sequence count of the OBSW
|
||||
static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT = 50;
|
||||
// Will reset the sequence count of the OBSW. Not required anymore after MPSoC update.
|
||||
static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT_LEGACY = 50;
|
||||
|
||||
static const uint16_t SIZE_ACK_REPORT = 14;
|
||||
static const uint16_t SIZE_EXE_REPORT = 14;
|
||||
static const uint16_t SIZE_TM_MEM_READ_REPORT = 18;
|
||||
static const uint16_t SIZE_TM_CAM_CMD_RPT = 18;
|
||||
static constexpr size_t SIZE_TM_HK_REPORT = 369;
|
||||
|
||||
enum Submode : uint8_t { IDLE_OR_NONE = 0, REPLAY = 1, SNAPSHOT = 2 };
|
||||
|
||||
// Setting the internal mode value to the actual telecommand ID
|
||||
/*
|
||||
enum InternalMode {
|
||||
OFF = HasModesIF::MODE_OFF,
|
||||
IDLE = ,
|
||||
REPLAY = TC_MODE_REPLAY,
|
||||
SNAPSHOT = TC_MODE_SNAPSHOT
|
||||
};
|
||||
*/
|
||||
|
||||
/**
|
||||
* SpacePacket apids of PLOC telecommands and telemetry.
|
||||
*/
|
||||
@ -132,6 +258,8 @@ static const uint16_t TC_MODE_SNAPSHOT = 0x120;
|
||||
static const uint16_t TC_DOWNLINK_DATA_MODULATE = 0x121;
|
||||
static constexpr uint16_t TC_HK_GET_REPORT = 0x123;
|
||||
static const uint16_t TC_DOWNLINK_PWR_OFF = 0x124;
|
||||
static constexpr uint16_t TC_ENABLE_TC_EXECUTION = 0x129;
|
||||
static constexpr uint16_t TC_FLASH_MKFS = 0x12A;
|
||||
static const uint16_t TC_CAM_CMD_SEND = 0x12C;
|
||||
static constexpr uint16_t TC_FLASH_COPY_FILE = 0x12E;
|
||||
static const uint16_t TC_SIMPLEX_SEND_FILE = 0x130;
|
||||
@ -156,15 +284,15 @@ static const uint8_t SPACE_PACKET_HEADER_SIZE = 6;
|
||||
|
||||
static const uint8_t STATUS_OFFSET = 10;
|
||||
|
||||
static constexpr size_t CRC_SIZE = 2;
|
||||
|
||||
/**
|
||||
* The size of payload data which will be forwarded to the requesting object. e.g. PUS Service
|
||||
* 8.
|
||||
*/
|
||||
static const uint8_t SIZE_MEM_READ_RPT_FIX = 6;
|
||||
|
||||
static const size_t MAX_FILENAME_SIZE = 256;
|
||||
static const size_t FILENAME_FIELD_SIZE = 256;
|
||||
// Subtract size of NULL terminator.
|
||||
static const size_t MAX_FILENAME_SIZE = FILENAME_FIELD_SIZE - 1;
|
||||
|
||||
/**
|
||||
* PLOC space packet length for fixed size packets. This is the size of the whole packet data
|
||||
@ -199,8 +327,9 @@ static const uint16_t TC_DOWNLINK_PWR_ON_EXECUTION_DELAY = 8;
|
||||
static const uint16_t TC_CAM_TAKE_PIC_EXECUTION_DELAY = 20;
|
||||
static const uint16_t TC_SIMPLEX_SEND_FILE_DELAY = 80;
|
||||
|
||||
namespace status_code {
|
||||
namespace statusCode {
|
||||
static const uint16_t DEFAULT_ERROR_CODE = 0x1;
|
||||
static constexpr uint16_t FLASH_DRIVE_ERROR = 0xb;
|
||||
static const uint16_t UNKNOWN_APID = 0x5DD;
|
||||
static const uint16_t INCORRECT_LENGTH = 0x5DE;
|
||||
static const uint16_t INCORRECT_CRC = 0x5DF;
|
||||
@ -225,49 +354,12 @@ static const uint16_t RESERVED_1 = 0x5F1;
|
||||
static const uint16_t RESERVED_2 = 0x5F2;
|
||||
static const uint16_t RESERVED_3 = 0x5F3;
|
||||
static const uint16_t RESERVED_4 = 0x5F4;
|
||||
} // namespace status_code
|
||||
|
||||
/**
|
||||
* @brief Abstract base class for TC space packet of MPSoC.
|
||||
*/
|
||||
class TcBase : public ploc::SpTcBase, public MPSoCReturnValuesIF {
|
||||
public:
|
||||
virtual ~TcBase() = default;
|
||||
|
||||
// Initial length field of space packet. Will always be updated when packet is created.
|
||||
static const uint16_t INIT_LENGTH = CRC_SIZE;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param sequenceCount Sequence count of space packet which will be incremented with each
|
||||
* sent and received packets.
|
||||
*/
|
||||
TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount)
|
||||
: ploc::SpTcBase(params, apid, 0, sequenceCount) {
|
||||
payloadStart = spParams.buf + ccsds::HEADER_LEN;
|
||||
spParams.setFullPayloadLen(INIT_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to finsh and write the space packet. It is expected that the user has
|
||||
* set the payload fields in the child class*
|
||||
* @return returnvalue::OK if packet creation was successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t finishPacket() {
|
||||
updateSpFields();
|
||||
ReturnValue_t res = checkSizeAndSerializeHeader();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
return calcAndSetCrc();
|
||||
}
|
||||
};
|
||||
} // namespace statusCode
|
||||
|
||||
/**
|
||||
* @brief This class helps to build the memory read command for the PLOC.
|
||||
*/
|
||||
class TcMemRead : public TcBase {
|
||||
class TcMemRead : public mpsoc::TcBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
@ -317,7 +409,7 @@ class TcMemRead : public TcBase {
|
||||
* @brief This class helps to generate the space packet to write data to a memory address within
|
||||
* the PLOC.
|
||||
*/
|
||||
class TcMemWrite : public TcBase {
|
||||
class TcMemWrite : public mpsoc::TcBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
@ -367,24 +459,21 @@ class TcMemWrite : public TcBase {
|
||||
/**
|
||||
* @brief Class to help creation of flash fopen command.
|
||||
*/
|
||||
class FlashFopen : public TcBase {
|
||||
class TcFlashFopen : public mpsoc::TcBase {
|
||||
public:
|
||||
FlashFopen(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
TcFlashFopen(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {}
|
||||
|
||||
ReturnValue_t setPayload(std::string filename, uint8_t mode) {
|
||||
accessMode = mode;
|
||||
size_t nameSize = filename.size();
|
||||
spParams.setFullPayloadLen(256 + sizeof(uint8_t) + CRC_SIZE);
|
||||
ReturnValue_t result = checkPayloadLen();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(payloadStart, filename.c_str(), nameSize);
|
||||
// payloadStart[nameSize] = NULL_TERMINATOR;
|
||||
std::memset(payloadStart + nameSize, 0, 256 - nameSize);
|
||||
// payloadStart[255] = NULL_TERMINATOR;
|
||||
payloadStart[256] = accessMode;
|
||||
std::memset(payloadStart, 0, FILENAME_FIELD_SIZE);
|
||||
std::memcpy(payloadStart, filename.c_str(), filename.size());
|
||||
payloadStart[FILENAME_FIELD_SIZE] = accessMode;
|
||||
spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + 1 + CRC_SIZE);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -395,14 +484,46 @@ class FlashFopen : public TcBase {
|
||||
/**
|
||||
* @brief Class to help creation of flash fclose command.
|
||||
*/
|
||||
class FlashFclose : public TcBase {
|
||||
class TcFlashFclose : public TcBase {
|
||||
public:
|
||||
FlashFclose(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
TcFlashFclose(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) {
|
||||
spParams.setFullPayloadLen(CRC_SIZE);
|
||||
}
|
||||
};
|
||||
|
||||
class TcEnableTcExec : public TcBase {
|
||||
public:
|
||||
TcEnableTcExec(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_ENABLE_TC_EXECUTION, sequenceCount) {
|
||||
spParams.setFullPayloadLen(CRC_SIZE);
|
||||
}
|
||||
|
||||
ReturnValue_t setPayload(const uint8_t* cmdData, size_t cmdDataLen) {
|
||||
if (cmdDataLen != 2) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
std::memcpy(payloadStart, cmdData, 2);
|
||||
spParams.setFullPayloadLen(2 + CRC_SIZE);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
class TcFlashMkfs : public TcBase {
|
||||
public:
|
||||
TcFlashMkfs(ploc::SpTcParams params, uint16_t sequenceCount, FlashId flashId)
|
||||
: TcBase(params, apid::TC_FLASH_MKFS, sequenceCount) {
|
||||
const char* flashIdStr = "0:\\";
|
||||
if (flashId == FlashId::FLASH_1) {
|
||||
flashIdStr = "1:\\";
|
||||
}
|
||||
std::memcpy(payloadStart, flashIdStr, 3);
|
||||
// Null terminator
|
||||
payloadStart[3] = 0;
|
||||
spParams.setFullPayloadLen(4 + CRC_SIZE);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to build flash write space packet.
|
||||
*/
|
||||
@ -462,15 +583,6 @@ class TcFlashRead : public TcBase {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
updateSpFields();
|
||||
result = checkSizeAndSerializeHeader();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = calcAndSetCrc();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
readSize = readLen;
|
||||
return result;
|
||||
}
|
||||
@ -488,20 +600,14 @@ class TcFlashDelete : public TcBase {
|
||||
|
||||
ReturnValue_t setPayload(std::string filename) {
|
||||
size_t nameSize = filename.size();
|
||||
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE);
|
||||
spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE);
|
||||
auto res = checkPayloadLen();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
std::memcpy(payloadStart, filename.c_str(), nameSize);
|
||||
*(payloadStart + nameSize) = NULL_TERMINATOR;
|
||||
|
||||
updateSpFields();
|
||||
res = checkSizeAndSerializeHeader();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
return calcAndSetCrc();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
@ -653,8 +759,9 @@ class TcGetDirContent : public TcBase {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memset(payloadStart, 0, 256);
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
payloadStart[255] = '\0';
|
||||
payloadStart[255] = 0;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@ -695,7 +802,7 @@ class TcReplayWriteSeq : public TcBase {
|
||||
static const size_t USE_DECODING_LENGTH = 1;
|
||||
|
||||
ReturnValue_t lengthCheck(size_t commandDataLen) {
|
||||
if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE or
|
||||
if (commandDataLen > USE_DECODING_LENGTH + FILENAME_FIELD_SIZE or
|
||||
checkPayloadLen() != returnvalue::OK) {
|
||||
sif::warning << "TcReplayWriteSeq: Command has invalid length " << commandDataLen
|
||||
<< std::endl;
|
||||
@ -708,24 +815,24 @@ class TcReplayWriteSeq : public TcBase {
|
||||
/**
|
||||
* @brief Helps to extract the fields of the flash write command from the PUS packet.
|
||||
*/
|
||||
class FlashBasePusCmd : public MPSoCReturnValuesIF {
|
||||
class FlashBasePusCmd {
|
||||
public:
|
||||
FlashBasePusCmd() = default;
|
||||
virtual ~FlashBasePusCmd() = default;
|
||||
|
||||
virtual ReturnValue_t extractFields(const uint8_t* commandData, size_t commandDataLen) {
|
||||
if (commandDataLen > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE + MAX_FILENAME_SIZE)) {
|
||||
if (commandDataLen > FILENAME_FIELD_SIZE) {
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
size_t fileLen = strnlen(reinterpret_cast<const char*>(commandData), commandDataLen);
|
||||
if (fileLen > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE)) {
|
||||
if (fileLen > MAX_FILENAME_SIZE) {
|
||||
return FILENAME_TOO_LONG;
|
||||
}
|
||||
obcFile = std::string(reinterpret_cast<const char*>(commandData), fileLen);
|
||||
fileLen =
|
||||
strnlen(reinterpret_cast<const char*>(commandData + obcFile.size() + SIZE_NULL_TERMINATOR),
|
||||
commandDataLen - obcFile.size() - 1);
|
||||
if (fileLen > MAX_FILENAME_SIZE) {
|
||||
if (fileLen > FILENAME_FIELD_SIZE) {
|
||||
return MPSOC_FILENAME_TOO_LONG;
|
||||
}
|
||||
mpsocFile = std::string(
|
||||
@ -736,11 +843,11 @@ class FlashBasePusCmd : public MPSoCReturnValuesIF {
|
||||
|
||||
const std::string& getObcFile() const { return obcFile; }
|
||||
|
||||
const std::string& getMPSoCFile() const { return mpsocFile; }
|
||||
const std::string& getMpsocFile() const { return mpsocFile; }
|
||||
|
||||
protected:
|
||||
size_t getParsedSize() const {
|
||||
return getObcFile().size() + getMPSoCFile().size() + 2 * SIZE_NULL_TERMINATOR;
|
||||
return getObcFile().size() + getMpsocFile().size() + 2 * SIZE_NULL_TERMINATOR;
|
||||
}
|
||||
static const size_t SIZE_NULL_TERMINATOR = 1;
|
||||
|
||||
@ -807,49 +914,191 @@ class TcCamTakePic : public TcBase {
|
||||
: TcBase(params, apid::TC_CAM_TAKE_PIC, sequenceCount) {}
|
||||
|
||||
ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) {
|
||||
if (commandDataLen > MAX_DATA_LENGTH) {
|
||||
const uint8_t** dataPtr = &commandData;
|
||||
if (commandDataLen > FULL_PAYLOAD_SIZE) {
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
std::string fileName(reinterpret_cast<const char*>(commandData));
|
||||
if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) {
|
||||
size_t deserLen = commandDataLen;
|
||||
size_t serLen = 0;
|
||||
fileName = std::string(reinterpret_cast<const char*>(commandData));
|
||||
if (fileName.size() > MAX_FILENAME_SIZE) {
|
||||
return FILENAME_TOO_LONG;
|
||||
}
|
||||
if (commandDataLen - (fileName.size() + sizeof(NULL_TERMINATOR)) != PARAMETER_SIZE) {
|
||||
return INVALID_LENGTH;
|
||||
deserLen -= fileName.length() + 1;
|
||||
*dataPtr += fileName.length() + 1;
|
||||
uint8_t** payloadPtr = &payloadStart;
|
||||
memset(payloadStart, 0, FILENAME_FIELD_SIZE);
|
||||
memcpy(payloadStart, fileName.data(), fileName.size());
|
||||
*payloadPtr += FILENAME_FIELD_SIZE;
|
||||
serLen += FILENAME_FIELD_SIZE;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&encoderSettingY, dataPtr, &deserLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
spParams.setFullPayloadLen(commandDataLen + CRC_SIZE);
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
result = SerializeAdapter::serialize(&encoderSettingY, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&quantizationY, dataPtr, &deserLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&quantizationY, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&encoderSettingsCb, dataPtr, &deserLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&encoderSettingsCb, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&quantizationCb, dataPtr, &deserLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&quantizationCb, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&encoderSettingsCr, dataPtr, &deserLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&encoderSettingsCr, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&quantizationCr, dataPtr, &deserLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&quantizationCr, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&bypassCompressor, dataPtr, &deserLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&bypassCompressor, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
spParams.setFullPayloadLen(FULL_PAYLOAD_SIZE + CRC_SIZE);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
std::string fileName;
|
||||
uint8_t encoderSettingY = 7;
|
||||
uint64_t quantizationY = 0;
|
||||
uint8_t encoderSettingsCb = 7;
|
||||
uint64_t quantizationCb = 0;
|
||||
uint8_t encoderSettingsCr = 7;
|
||||
uint64_t quantizationCr = 0;
|
||||
uint8_t bypassCompressor = 0;
|
||||
|
||||
private:
|
||||
static const size_t MAX_DATA_LENGTH = 286;
|
||||
static const size_t PARAMETER_SIZE = 28;
|
||||
static constexpr size_t FULL_PAYLOAD_SIZE = FILENAME_FIELD_SIZE + PARAMETER_SIZE;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to build simplex send file command
|
||||
*/
|
||||
class TcSimplexSendFile : public TcBase {
|
||||
class TcSimplexStreamFile : public TcBase {
|
||||
public:
|
||||
TcSimplexSendFile(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
TcSimplexStreamFile(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {}
|
||||
|
||||
ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) {
|
||||
if (commandDataLen > MAX_DATA_LENGTH) {
|
||||
if (commandDataLen > MAX_FILENAME_SIZE) {
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
std::string fileName(reinterpret_cast<const char*>(commandData));
|
||||
if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) {
|
||||
if (fileName.size() > MAX_FILENAME_SIZE) {
|
||||
return FILENAME_TOO_LONG;
|
||||
}
|
||||
spParams.setFullPayloadLen(commandDataLen + CRC_SIZE);
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
|
||||
std::memset(payloadStart, 0, FILENAME_FIELD_SIZE);
|
||||
std::memcpy(payloadStart, fileName.data(), fileName.length());
|
||||
payloadStart[fileName.length()] = 0;
|
||||
spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE);
|
||||
;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
static const size_t MAX_DATA_LENGTH = 256;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to build simplex send file command
|
||||
*/
|
||||
class TcSplitFile : public TcBase {
|
||||
public:
|
||||
TcSplitFile(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {}
|
||||
|
||||
ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) {
|
||||
if (commandDataLen < MIN_DATA_LENGTH) {
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
if (commandDataLen > MAX_DATA_LENGTH) {
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
const uint8_t** dataPtr = &commandData;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&chunkParameter, dataPtr, &commandDataLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
/// No chunks makes no sense, and DIV str can not be longer than whats representable with 3
|
||||
/// decimal digits.
|
||||
if (chunkParameter == 0 or chunkParameter > 999) {
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
std::string fileName(reinterpret_cast<const char*>(*dataPtr));
|
||||
if (fileName.size() > MAX_FILENAME_SIZE) {
|
||||
return FILENAME_TOO_LONG;
|
||||
}
|
||||
char divStr[16]{};
|
||||
sprintf(divStr, "DIV%03u", chunkParameter);
|
||||
std::memcpy(payloadStart, divStr, DIV_STR_LEN);
|
||||
payloadStart[DIV_STR_LEN] = 0;
|
||||
std::memset(payloadStart + DIV_STR_LEN + 1, 0, FILENAME_FIELD_SIZE - DIV_STR_LEN - 1);
|
||||
std::memcpy(payloadStart + DIV_STR_LEN + 1, fileName.data(), fileName.length());
|
||||
spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t chunkParameter = 0;
|
||||
static constexpr size_t MIN_DATA_LENGTH = 4;
|
||||
static constexpr size_t DIV_STR_LEN = 6;
|
||||
static constexpr size_t MAX_DATA_LENGTH = 4 + MAX_FILENAME_SIZE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -49,7 +49,7 @@ static const Event SUPV_EXE_ACK_UNKNOWN_COMMAND = MAKE_EVENT(10, severity::LOW);
|
||||
extern std::atomic_bool SUPV_ON;
|
||||
static constexpr uint32_t INTER_COMMAND_DELAY = 20;
|
||||
static constexpr uint32_t BOOT_TIMEOUT_MS = 4000;
|
||||
static constexpr uint32_t MAX_TRANSITION_TIME_TO_ON_MS = BOOT_TIMEOUT_MS + 2000;
|
||||
static constexpr uint32_t MAX_TRANSITION_TIME_TO_ON_MS = BOOT_TIMEOUT_MS + 3000;
|
||||
static constexpr uint32_t MAX_TRANSITION_TIME_TO_OFF_MS = 1000;
|
||||
|
||||
namespace result {
|
||||
@ -159,6 +159,7 @@ static const DeviceCommandId_t ENABLE_NVMS = 59;
|
||||
static const DeviceCommandId_t CONTINUE_UPDATE = 60;
|
||||
static const DeviceCommandId_t MEMORY_CHECK_WITH_FILE = 61;
|
||||
static constexpr DeviceCommandId_t MEMORY_CHECK = 62;
|
||||
static constexpr DeviceCommandId_t ABORT_LONGER_REQUEST = 63;
|
||||
|
||||
/** Reply IDs */
|
||||
enum ReplyId : DeviceCommandId_t {
|
||||
@ -1145,14 +1146,14 @@ class WriteMemory : public TcBase {
|
||||
: TcBase(params, Apid::MEM_MAN, static_cast<uint8_t>(tc::MemManId::WRITE), 1) {}
|
||||
|
||||
ReturnValue_t buildPacket(ccsds::SequenceFlags seqFlags, uint16_t sequenceCount, uint8_t memoryId,
|
||||
uint32_t startAddress, uint16_t length, uint8_t* updateData) {
|
||||
uint32_t currentAddr, uint16_t length, uint8_t* updateData) {
|
||||
if (length > CHUNK_MAX) {
|
||||
sif::error << "WriteMemory::WriteMemory: Invalid length" << std::endl;
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
spParams.creator.setSeqFlags(seqFlags);
|
||||
spParams.creator.setSeqCount(sequenceCount);
|
||||
auto res = initPacket(memoryId, startAddress, length, updateData);
|
||||
auto res = initPacket(memoryId, currentAddr, length, updateData);
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
@ -1170,7 +1171,7 @@ class WriteMemory : public TcBase {
|
||||
static const uint16_t META_DATA_LENGTH = 8;
|
||||
uint8_t n = 1;
|
||||
|
||||
ReturnValue_t initPacket(uint8_t memoryId, uint32_t startAddr, uint16_t updateDataLen,
|
||||
ReturnValue_t initPacket(uint8_t memoryId, uint32_t currentAddr, uint16_t updateDataLen,
|
||||
uint8_t* updateData) {
|
||||
uint8_t* data = payloadStart;
|
||||
if (updateDataLen % 2 != 0) {
|
||||
@ -1188,7 +1189,7 @@ class WriteMemory : public TcBase {
|
||||
SerializeIF::Endianness::BIG);
|
||||
SerializeAdapter::serialize(&n, &data, &serializedSize, spParams.maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
SerializeAdapter::serialize(&startAddr, &data, &serializedSize, spParams.maxSize,
|
||||
SerializeAdapter::serialize(¤tAddr, &data, &serializedSize, spParams.maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
SerializeAdapter::serialize(&updateDataLen, &data, &serializedSize, spParams.maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
@ -1805,7 +1806,7 @@ class LatchupStatusReport : public StaticLocalDataSet<LATCHUP_RPT_SET_ENTRIES> {
|
||||
lp_var_t<uint8_t> timeMon = lp_var_t<uint8_t>(sid.objectId, PoolIds::LATCHUP_RPT_TIME_MON, this);
|
||||
lp_var_t<uint8_t> timeYear =
|
||||
lp_var_t<uint8_t>(sid.objectId, PoolIds::LATCHUP_RPT_TIME_YEAR, this);
|
||||
lp_var_t<uint8_t> isSet = lp_var_t<uint8_t>(sid.objectId, PoolIds::LATCHUP_RPT_IS_SET, this);
|
||||
lp_var_t<uint8_t> isSynced = lp_var_t<uint8_t>(sid.objectId, PoolIds::LATCHUP_RPT_IS_SET, this);
|
||||
|
||||
static const uint8_t IS_SET_BIT_POS = 15;
|
||||
};
|
||||
|
@ -795,9 +795,9 @@ ReturnValue_t ImtqHandler::initializeLocalDataPool(localpool::DataPool& localDat
|
||||
localDataPoolMap.emplace(imtq::FINA_NEG_Z_COIL_Z_TEMPERATURE, new PoolEntry<int16_t>({0}));
|
||||
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetNoTorque.getSid(), enableHkSets, 30.0));
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetNoTorque.getSid(), enableHkSets, 60.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetWithTorque.getSid(), enableHkSets, 30.0));
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetWithTorque.getSid(), enableHkSets, 60.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(rawMtmNoTorque.getSid(), false, 10.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
|
@ -340,7 +340,7 @@ ReturnValue_t RwHandler::initializeLocalDataPool(localpool::DataPool& localDataP
|
||||
localDataPoolMap.emplace(rws::SPI_REG_OVERRUN_ERRORS, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(rws::SPI_TOTAL_ERRORS, new PoolEntry<uint32_t>({0}));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(statusSet.getSid(), false, 12.0));
|
||||
subdp::DiagnosticsHkPeriodicParams(statusSet.getSid(), false, 30.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(tmDataset.getSid(), false, 30.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
|
@ -59,6 +59,7 @@ class RwHandler : public DeviceHandlerBase {
|
||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::RW_HANDLER;
|
||||
//! [EXPORT] : [COMMENT] Action Message with invalid speed was received. Valid speeds must be in
|
||||
//! the range of [-65000; 1000] or [1000; 65000]
|
||||
static const ReturnValue_t INVALID_SPEED = MAKE_RETURN_CODE(0xA0);
|
||||
|
@ -22,10 +22,10 @@ enum AcsMode : Mode_t {
|
||||
|
||||
enum SafeSubmode : Submode_t { DEFAULT = 0, DETUMBLE = 1 };
|
||||
|
||||
enum SafeModeStrategy : uint8_t {
|
||||
SAFECTRL_OFF = 0,
|
||||
SAFECTRL_NO_MAG_FIELD_FOR_CONTROL = 1,
|
||||
SAFECTRL_NO_SENSORS_FOR_CONTROL = 2,
|
||||
enum ControlModeStrategy : uint8_t {
|
||||
CTRL_OFF = 0,
|
||||
CTRL_NO_MAG_FIELD_FOR_CONTROL = 1,
|
||||
CTRL_NO_SENSORS_FOR_CONTROL = 2,
|
||||
// OBSW version <= v6.1.0
|
||||
LEGACY_SAFECTRL_ACTIVE_MEKF = 10,
|
||||
LEGACY_SAFECTRL_WITHOUT_MEKF = 11,
|
||||
@ -40,20 +40,39 @@ enum SafeModeStrategy : uint8_t {
|
||||
SAFECTRL_ECLIPSE_IDELING = 19,
|
||||
SAFECTRL_DETUMBLE_FULL = 20,
|
||||
SAFECTRL_DETUMBLE_DETERIORATED = 21,
|
||||
// Added in vNext
|
||||
PTGCTRL_MEKF = 100,
|
||||
PTGCTRL_STR = 101,
|
||||
PTGCTRL_QUEST = 102,
|
||||
};
|
||||
|
||||
enum GpsSource : uint8_t {
|
||||
namespace gps {
|
||||
enum Source : uint8_t {
|
||||
NONE,
|
||||
GPS,
|
||||
GPS_EXTRAPOLATED,
|
||||
SPG4,
|
||||
};
|
||||
}
|
||||
|
||||
namespace rotrate {
|
||||
enum Source : uint8_t {
|
||||
NONE,
|
||||
SUSMGM,
|
||||
QUEST,
|
||||
STR,
|
||||
};
|
||||
}
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::ACS_SUBSYSTEM;
|
||||
//! [EXPORT] : [COMMENT] The limits for the rotation in safe mode were violated.
|
||||
static constexpr Event SAFE_RATE_VIOLATION = MAKE_EVENT(0, severity::MEDIUM);
|
||||
//! [EXPORT] : [COMMENT] The system has recovered from a safe rate rotation violation.
|
||||
static constexpr Event SAFE_RATE_RECOVERY = MAKE_EVENT(1, severity::MEDIUM);
|
||||
//! [EXPORT] : [COMMENT] The limits for the rotation in pointing mode were violated.
|
||||
static constexpr Event PTG_RATE_VIOLATION = MAKE_EVENT(10, severity::MEDIUM);
|
||||
//! [EXPORT] : [COMMENT] The system has recovered from a rate rotation violation.
|
||||
static constexpr Event RATE_RECOVERY = MAKE_EVENT(1, severity::MEDIUM);
|
||||
//! [EXPORT] : [COMMENT] The detumble transition has failed.
|
||||
//! //! P1: Last detumble state before failure.
|
||||
static constexpr Event DETUMBLE_TRANSITION_FAILED = MAKE_EVENT(11, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Multiple RWs are invalid, uncommandable and therefore higher ACS modes
|
||||
//! cannot be maintained.
|
||||
static constexpr Event MULTIPLE_RW_INVALID = MAKE_EVENT(2, severity::HIGH);
|
||||
@ -64,15 +83,17 @@ static constexpr Event MEKF_INVALID_INFO = MAKE_EVENT(3, severity::INFO);
|
||||
static constexpr Event MEKF_RECOVERY = MAKE_EVENT(4, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] MEKF performed an automatic reset after detection of nonfinite values.
|
||||
static constexpr Event MEKF_AUTOMATIC_RESET = MAKE_EVENT(5, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] MEKF was not able to compute a solution during any pointing ACS mode for a
|
||||
//! prolonged time.
|
||||
static constexpr Event MEKF_INVALID_MODE_VIOLATION = MAKE_EVENT(6, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] For a prolonged time, no attitude information was available for the
|
||||
//! Pointing Controller. Falling back to Safe Mode.
|
||||
static constexpr Event PTG_CTRL_NO_ATTITUDE_INFORMATION = MAKE_EVENT(6, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] The ACS safe mode controller was not able to compute a solution and has
|
||||
//! failed.
|
||||
//! P1: Missing information about magnetic field, P2: Missing information about rotational rate
|
||||
static constexpr Event SAFE_MODE_CONTROLLER_FAILURE = MAKE_EVENT(7, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] The TLE for the SGP4 Propagator has become too old.
|
||||
static constexpr Event TLE_TOO_OLD = MAKE_EVENT(8, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] The TLE could not be read from the filesystem.
|
||||
static constexpr Event TLE_FILE_READ_FAILED = MAKE_EVENT(9, severity::LOW);
|
||||
|
||||
extern const char* getModeStr(AcsMode mode);
|
||||
|
||||
|
@ -32,7 +32,7 @@ ReturnValue_t ArcsecDatalinkLayer::checkRingBufForFrame(const uint8_t** decodedF
|
||||
size_t encodedDataSize = 0;
|
||||
slip_error_t slipError =
|
||||
slip_decode_frame(decodedRxFrame, &rxFrameSize, rxAnalysisBuffer + startIdx,
|
||||
idx - startIdx + 1, &encodedDataSize, ARC_DEF_SAGITTA_SLIP_ID);
|
||||
idx - startIdx + 1, &encodedDataSize, ARC_DEF_SAGITTA_SLIP_ID, 0);
|
||||
decodeRingBuf.deleteData(idx + 1);
|
||||
switch (slipError) {
|
||||
case (SLIP_OK): {
|
||||
@ -76,7 +76,7 @@ void ArcsecDatalinkLayer::reset() { decodeRingBuf.clear(); }
|
||||
|
||||
void ArcsecDatalinkLayer::encodeFrame(const uint8_t* data, size_t length, const uint8_t** txFrame,
|
||||
size_t& size) {
|
||||
slip_encode_frame(data, length, txEncoded, &size, ARC_DEF_SAGITTA_SLIP_ID);
|
||||
slip_encode_frame(data, length, txEncoded, sizeof(txEncoded), &size, ARC_DEF_SAGITTA_SLIP_ID);
|
||||
if (txFrame != nullptr) {
|
||||
*txFrame = txEncoded;
|
||||
}
|
||||
|
@ -5,7 +5,12 @@
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
#include <mission/acs/str/strJsonCommands.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "fsfw/filesystem/HasFileSystemIF.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "mission/memory/SdCardMountedIF.h"
|
||||
|
||||
extern "C" {
|
||||
#include <sagitta/client/actionreq.h>
|
||||
@ -16,7 +21,6 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include <atomic>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
@ -27,7 +31,8 @@ std::atomic_bool JCFG_DONE(false);
|
||||
|
||||
StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
StrComHandler* strHelper, power::Switch_t powerSwitch,
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter)
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter,
|
||||
SdCardMountedIF& sdCardIF)
|
||||
: DeviceHandlerBase(objectId, comIF, comCookie),
|
||||
temperatureSet(this),
|
||||
versionSet(this),
|
||||
@ -58,8 +63,10 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
|
||||
centroidSet(this),
|
||||
centroidsSet(this),
|
||||
contrastSet(this),
|
||||
blobStatsSet(this),
|
||||
strHelper(strHelper),
|
||||
powerSwitch(powerSwitch),
|
||||
sdCardIF(sdCardIF),
|
||||
cfgPathGetter(cfgPathGetter) {
|
||||
if (comCookie == nullptr) {
|
||||
sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl;
|
||||
@ -138,6 +145,9 @@ ReturnValue_t StarTrackerHandler::initialize() {
|
||||
// delay whole satellite boot process.
|
||||
reloadJsonCfgFile();
|
||||
|
||||
// Default firmware target is always initialized from persistent file.
|
||||
loadTargetFirmwareFromPersistentCfg();
|
||||
|
||||
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||
if (manager == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
@ -165,6 +175,19 @@ ReturnValue_t StarTrackerHandler::initialize() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void StarTrackerHandler::loadTargetFirmwareFromPersistentCfg() {
|
||||
const char* prefix = sdCardIF.getCurrentMountPrefix();
|
||||
std::filesystem::path path = std::filesystem::path(prefix) / startracker::FW_TARGET_CFG_PATH;
|
||||
std::ifstream ifile(path);
|
||||
if (ifile.is_open() and !ifile.bad()) {
|
||||
std::string targetStr;
|
||||
std::getline(ifile, targetStr);
|
||||
if (targetStr == "backup") {
|
||||
firmwareTargetRaw = static_cast<uint8_t>(startracker::FirmwareTarget::BACKUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool StarTrackerHandler::reloadJsonCfgFile() {
|
||||
jcfgCountdown.resetTimer();
|
||||
auto strCfgPath = cfgPathGetter.getCfgPath();
|
||||
@ -307,21 +330,11 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
strHelper->setFlashReadFilename(std::string(reinterpret_cast<const char*>(data), size));
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (startracker::FIRMWARE_UPDATE): {
|
||||
result = DeviceHandlerBase::acceptExternalDeviceCommands();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
case (startracker::FIRMWARE_UPDATE_MAIN): {
|
||||
return handleFirmwareUpdateCommand(data, size, startracker::FirmwareTarget::MAIN);
|
||||
}
|
||||
if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) {
|
||||
return FILE_PATH_TOO_LONG;
|
||||
}
|
||||
result =
|
||||
strHelper->startFirmwareUpdate(std::string(reinterpret_cast<const char*>(data), size));
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
strHelperHandlingSpecialRequest = true;
|
||||
return EXECUTION_FINISHED;
|
||||
case (startracker::FIRMWARE_UPDATE_BACKUP): {
|
||||
return handleFirmwareUpdateCommand(data, size, startracker::FirmwareTarget::BACKUP);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@ -330,6 +343,23 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
reinitNextSetParam = true;
|
||||
return DeviceHandlerBase::executeAction(actionId, commandedBy, data, size);
|
||||
}
|
||||
ReturnValue_t StarTrackerHandler::handleFirmwareUpdateCommand(const uint8_t* data, size_t size,
|
||||
startracker::FirmwareTarget target) {
|
||||
ReturnValue_t result = DeviceHandlerBase::acceptExternalDeviceCommands();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) {
|
||||
return FILE_PATH_TOO_LONG;
|
||||
}
|
||||
result = strHelper->startFirmwareUpdate(std::string(reinterpret_cast<const char*>(data), size),
|
||||
target);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
strHelperHandlingSpecialRequest = true;
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
|
||||
void StarTrackerHandler::performOperationHook() {
|
||||
EventMessage event;
|
||||
@ -543,7 +573,7 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
Clock::getClock(&tv);
|
||||
setTimeRequest.unixTime =
|
||||
(static_cast<uint64_t>(tv.tv_sec) * 1000 * 1000) + (static_cast<uint64_t>(tv.tv_usec));
|
||||
arc_pack_settime_action_req(&setTimeRequest, commandBuffer, &rawPacketLen);
|
||||
prv_arc_pack_settime_action_req(&setTimeRequest, commandBuffer, &rawPacketLen);
|
||||
size_t serLen = 0;
|
||||
// Time in milliseconds. Manual serialization because arcsec API ignores endianness.
|
||||
SerializeAdapter::serialize(&setTimeRequest.unixTime, commandBuffer + 2, &serLen,
|
||||
@ -568,8 +598,12 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
prepareRequestContrastTm();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_BLOB_STATS): {
|
||||
prepareRequestBlobStatsTm();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::BOOT): {
|
||||
prepareBootCommand();
|
||||
prepareBootCommand(static_cast<startracker::FirmwareTarget>(firmwareTargetRaw));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_VERSION): {
|
||||
@ -856,6 +890,8 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::REQ_CONTRAST, 3, &contrastSet,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::REQ_BLOB_STATS, 3, &blobStatsSet,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
||||
@ -1053,6 +1089,12 @@ void StarTrackerHandler::resetSecondaryTmSet() {
|
||||
histogramSet.setValidity(false, true);
|
||||
}
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(&blobStatsSet);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
histogramSet.setValidity(false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StarTrackerHandler::bootBootloader() {
|
||||
@ -1162,7 +1204,7 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_SOLUTION): {
|
||||
result = handleTm(packet, solutionSet, "REQ_SOLUTION");
|
||||
result = handleSolution(packet);
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_CONTRAST): {
|
||||
@ -1201,6 +1243,10 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
result = handleTm(packet, histogramSet, "REQ_HISTO");
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_BLOB_STATS): {
|
||||
result = handleTm(packet, blobStatsSet, "REQ_BLOB_STATS");
|
||||
break;
|
||||
}
|
||||
case (startracker::SUBSCRIPTION):
|
||||
case (startracker::LOGLEVEL):
|
||||
case (startracker::LOGSUBSCRIPTION):
|
||||
@ -1602,6 +1648,13 @@ ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& l
|
||||
localDataPoolMap.emplace(startracker::PoolIds::CONTRAST_C, new PoolEntry<uint32_t>(9));
|
||||
localDataPoolMap.emplace(startracker::PoolIds::CONTRAST_D, new PoolEntry<uint32_t>(9));
|
||||
|
||||
localDataPoolMap.emplace(startracker::TICKS_BLOB_STATS, new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(startracker::TIME_BLOB_STATS, new PoolEntry<uint64_t>());
|
||||
localDataPoolMap.emplace(startracker::PoolIds::BLOB_STATS_NOISE, new PoolEntry<uint8_t>(16));
|
||||
localDataPoolMap.emplace(startracker::PoolIds::BLOB_STATS_THOLD, new PoolEntry<uint8_t>(16));
|
||||
localDataPoolMap.emplace(startracker::PoolIds::BLOB_STATS_LVALID, new PoolEntry<uint8_t>(16));
|
||||
localDataPoolMap.emplace(startracker::PoolIds::BLOB_STATS_OFLOW, new PoolEntry<uint8_t>(16));
|
||||
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(temperatureSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
@ -1609,7 +1662,7 @@ ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& l
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(interfaceSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(solutionSet.getSid(), false, 12.0));
|
||||
subdp::DiagnosticsHkPeriodicParams(solutionSet.getSid(), false, 30.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(cameraSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
@ -1630,6 +1683,8 @@ ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& l
|
||||
subdp::RegularHkPeriodicParams(centroidsSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(contrastSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(blobStatsSet.getSid(), false, 10.0));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -1659,7 +1714,8 @@ ReturnValue_t StarTrackerHandler::checkMode(ActionId_t actionId) {
|
||||
case startracker::UPLOAD_IMAGE:
|
||||
case startracker::DOWNLOAD_IMAGE:
|
||||
case startracker::FLASH_READ:
|
||||
case startracker::FIRMWARE_UPDATE: {
|
||||
case startracker::FIRMWARE_UPDATE_BACKUP:
|
||||
case startracker::FIRMWARE_UPDATE_MAIN: {
|
||||
return DeviceHandlerBase::acceptExternalDeviceCommands();
|
||||
default:
|
||||
break;
|
||||
@ -1875,6 +1931,10 @@ ReturnValue_t StarTrackerHandler::scanForTmReply(uint8_t replyId, DeviceCommandI
|
||||
*foundId = startracker::REQ_BLOB;
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::BLOB_STATS): {
|
||||
*foundId = startracker::REQ_BLOB_STATS;
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::BLOBS): {
|
||||
*foundId = startracker::REQ_BLOBS;
|
||||
break;
|
||||
@ -1956,10 +2016,10 @@ ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* command
|
||||
return result;
|
||||
}
|
||||
|
||||
void StarTrackerHandler::prepareBootCommand() {
|
||||
void StarTrackerHandler::prepareBootCommand(startracker::FirmwareTarget target) {
|
||||
uint32_t length = 0;
|
||||
struct BootActionRequest bootRequest = {BOOT_REGION_ID};
|
||||
arc_pack_boot_action_req(&bootRequest, commandBuffer, &length);
|
||||
struct BootActionRequest bootRequest = {static_cast<uint8_t>(target)};
|
||||
prv_arc_pack_boot_action_req(&bootRequest, commandBuffer, &length);
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = length;
|
||||
}
|
||||
@ -1992,7 +2052,7 @@ ReturnValue_t StarTrackerHandler::prepareChecksumCommand(const uint8_t* commandD
|
||||
return result;
|
||||
}
|
||||
uint32_t rawCmdLength = 0;
|
||||
arc_pack_checksum_action_req(&req, commandBuffer, &rawCmdLength);
|
||||
prv_arc_pack_checksum_action_req(&req, commandBuffer, &rawCmdLength);
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = rawCmdLength;
|
||||
checksumCmd.rememberRegion = req.region;
|
||||
@ -2011,7 +2071,7 @@ void StarTrackerHandler::prepareTimeRequest() {
|
||||
void StarTrackerHandler::preparePingRequest() {
|
||||
uint32_t length = 0;
|
||||
struct PingActionRequest pingRequest = {PING_ID};
|
||||
arc_pack_ping_action_req(&pingRequest, commandBuffer, &length);
|
||||
prv_arc_pack_ping_action_req(&pingRequest, commandBuffer, &length);
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = length;
|
||||
}
|
||||
@ -2040,7 +2100,7 @@ void StarTrackerHandler::preparePowerRequest() {
|
||||
void StarTrackerHandler::prepareSwitchToBootloaderCmd() {
|
||||
uint32_t length = 0;
|
||||
struct RebootActionRequest rebootReq {};
|
||||
arc_pack_reboot_action_req(&rebootReq, commandBuffer, &length);
|
||||
prv_arc_pack_reboot_action_req(&rebootReq, commandBuffer, &length);
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = length;
|
||||
}
|
||||
@ -2049,7 +2109,7 @@ void StarTrackerHandler::prepareTakeImageCommand(const uint8_t* commandData) {
|
||||
uint32_t length = 0;
|
||||
struct CameraActionRequest camReq;
|
||||
camReq.actionid = *commandData;
|
||||
arc_pack_camera_action_req(&camReq, commandBuffer, &length);
|
||||
prv_arc_pack_camera_action_req(&camReq, commandBuffer, &length);
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = length;
|
||||
}
|
||||
@ -2115,6 +2175,14 @@ ReturnValue_t StarTrackerHandler::prepareRequestCentroidTm() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestBlobStatsTm() {
|
||||
uint32_t length = 0;
|
||||
arc_tm_pack_blobstats_req(commandBuffer, &length);
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = length;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestCentroidsTm() {
|
||||
uint32_t length = 0;
|
||||
arc_tm_pack_centroids_req(commandBuffer, &length);
|
||||
@ -2389,7 +2457,8 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
|
||||
internalState = InternalState::DONE;
|
||||
}
|
||||
break;
|
||||
case startracker::Program::FIRMWARE:
|
||||
case startracker::Program::FIRMWARE_BACKUP:
|
||||
case startracker::Program::FIRMWARE_MAIN: {
|
||||
if (startupState == StartupState::WAIT_CHECK_PROGRAM) {
|
||||
startupState = StartupState::BOOT_BOOTLOADER;
|
||||
}
|
||||
@ -2400,9 +2469,10 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
|
||||
internalState = InternalState::FAILED_BOOTLOADER_BOOT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sif::warning << "StarTrackerHandler::checkProgram: Version set has invalid program ID"
|
||||
<< std::endl;
|
||||
sif::warning << "StarTrackerHandler::checkProgram: Version set has invalid program ID "
|
||||
<< static_cast<int>(versionSet.program.value) << std::endl;
|
||||
return INVALID_PROGRAM;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
@ -2438,6 +2508,36 @@ ReturnValue_t StarTrackerHandler::handleTm(const uint8_t* rawFrame, LocalPoolDat
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleSolution(const uint8_t* rawFrame) {
|
||||
ReturnValue_t result = statusFieldCheck(rawFrame);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
PoolReadGuard pg(&solutionSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
const uint8_t* reply = rawFrame + TICKS_OFFSET;
|
||||
solutionSet.setValidityBufferGeneration(false);
|
||||
size_t sizeLeft = fullPacketLen;
|
||||
result = solutionSet.deSerialize(&reply, &sizeLeft, SerializeIF::Endianness::LITTLE);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StarTrackerHandler::handleTm: Deserialization failed for solution set: 0x"
|
||||
<< std::hex << std::setw(4) << result << std::dec << std::endl;
|
||||
}
|
||||
solutionSet.setValidityBufferGeneration(true);
|
||||
solutionSet.setValidity(true, true);
|
||||
solutionSet.caliQw.setValid(solutionSet.isTrustWorthy.value);
|
||||
solutionSet.caliQx.setValid(solutionSet.isTrustWorthy.value);
|
||||
solutionSet.caliQy.setValid(solutionSet.isTrustWorthy.value);
|
||||
solutionSet.caliQz.setValid(solutionSet.isTrustWorthy.value);
|
||||
solutionSet.trackQw.setValid(solutionSet.isTrustWorthy.value);
|
||||
solutionSet.trackQx.setValid(solutionSet.isTrustWorthy.value);
|
||||
solutionSet.trackQy.setValid(solutionSet.isTrustWorthy.value);
|
||||
solutionSet.trackQz.setValid(solutionSet.isTrustWorthy.value);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleAutoBlobTm(const uint8_t* rawFrame) {
|
||||
ReturnValue_t result = statusFieldCheck(rawFrame);
|
||||
if (result != returnvalue::OK) {
|
||||
@ -2832,17 +2932,19 @@ ReturnValue_t StarTrackerHandler::checkCommand(ActionId_t actionId) {
|
||||
case startracker::REQ_MATCHED_CENTROIDS:
|
||||
case startracker::REQ_BLOB:
|
||||
case startracker::REQ_BLOBS:
|
||||
case startracker::REQ_BLOB_STATS:
|
||||
case startracker::REQ_CENTROID:
|
||||
case startracker::REQ_CENTROIDS:
|
||||
case startracker::REQ_CONTRAST: {
|
||||
if (getMode() == MODE_ON and getSubmode() != startracker::Program::FIRMWARE) {
|
||||
if (getMode() == MODE_ON and getSubmode() != startracker::SUBMODE_FIRMWARE) {
|
||||
return STARTRACKER_NOT_RUNNING_FIRMWARE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case startracker::FIRMWARE_UPDATE:
|
||||
case startracker::FIRMWARE_UPDATE_MAIN:
|
||||
case startracker::FIRMWARE_UPDATE_BACKUP:
|
||||
case startracker::FLASH_READ:
|
||||
if (getMode() != MODE_ON or getSubmode() != startracker::Program::BOOTLOADER) {
|
||||
if (getMode() != MODE_ON or getSubmode() != startracker::SUBMODE_BOOTLOADER) {
|
||||
return STARTRACKER_NOT_RUNNING_BOOTLOADER;
|
||||
}
|
||||
break;
|
||||
@ -2853,3 +2955,42 @@ ReturnValue_t StarTrackerHandler::checkCommand(ActionId_t actionId) {
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::acceptExternalDeviceCommands() { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t StarTrackerHandler::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) {
|
||||
auto firmwareTargetUpdate = [&](bool persistent) {
|
||||
uint8_t value = 0;
|
||||
newValues->getElement(&value);
|
||||
if (value != static_cast<uint8_t>(startracker::FirmwareTarget::MAIN) &&
|
||||
value != static_cast<uint8_t>(startracker::FirmwareTarget::BACKUP)) {
|
||||
return HasParametersIF::INVALID_VALUE;
|
||||
}
|
||||
parameterWrapper->set(firmwareTargetRaw);
|
||||
if (persistent) {
|
||||
if (sdCardIF.isSdCardUsable(std::nullopt)) {
|
||||
const char* prefix = sdCardIF.getCurrentMountPrefix();
|
||||
std::filesystem::path path =
|
||||
std::filesystem::path(prefix) / startracker::FW_TARGET_CFG_PATH;
|
||||
std::ofstream of(path, std::ofstream::out | std::ofstream::trunc);
|
||||
if (value == static_cast<uint8_t>(startracker::FirmwareTarget::MAIN)) {
|
||||
of << "main\n";
|
||||
} else {
|
||||
of << "backup\n";
|
||||
}
|
||||
} else {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
}
|
||||
};
|
||||
return returnvalue::OK;
|
||||
};
|
||||
if (uniqueId == startracker::ParamId::FIRMWARE_TARGET) {
|
||||
return firmwareTargetUpdate(false);
|
||||
}
|
||||
if (uniqueId == startracker::ParamId::FIRMWARE_TARGET_PERSISTENT) {
|
||||
return firmwareTargetUpdate(true);
|
||||
}
|
||||
return DeviceHandlerBase::getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||
startAtIndex);
|
||||
}
|
||||
|
@ -11,10 +11,7 @@
|
||||
#include <set>
|
||||
#include <thread>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "devices/powerSwitcherList.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
#include "fsfw/src/fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/timemanager/Countdown.h"
|
||||
|
||||
extern "C" {
|
||||
@ -45,7 +42,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
*/
|
||||
StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
StrComHandler* strHelper, power::Switch_t powerSwitch,
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter);
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter, SdCardMountedIF& sdCardIF);
|
||||
virtual ~StarTrackerHandler();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
@ -61,6 +58,9 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
|
||||
Submode_t getInitialSubmode() override;
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
|
||||
|
||||
protected:
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
@ -161,7 +161,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
|
||||
// Ping request will reply ping with this ID (data field)
|
||||
static const uint32_t PING_ID = 0x55;
|
||||
static const uint32_t BOOT_REGION_ID = 1;
|
||||
uint8_t firmwareTargetRaw = static_cast<uint8_t>(startracker::FirmwareTarget::MAIN);
|
||||
|
||||
static const MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
|
||||
static const uint32_t MUTEX_TIMEOUT = 20;
|
||||
static const uint32_t BOOT_TIMEOUT = 1000;
|
||||
@ -215,6 +216,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
startracker::CentroidSet centroidSet;
|
||||
startracker::CentroidsSet centroidsSet;
|
||||
startracker::ContrastSet contrastSet;
|
||||
startracker::BlobStatsSet blobStatsSet;
|
||||
|
||||
// Pointer to object responsible for uploading and downloading images to/from the star tracker
|
||||
StrComHandler* strHelper = nullptr;
|
||||
@ -314,12 +316,14 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
std::set<DeviceCommandId_t> additionalRequestedTm{};
|
||||
std::set<DeviceCommandId_t>::iterator currentSecondaryTmIter;
|
||||
|
||||
SdCardMountedIF& sdCardIF;
|
||||
startracker::SdCardConfigPathGetter& cfgPathGetter;
|
||||
|
||||
/**
|
||||
* @brief Handles internal state
|
||||
*/
|
||||
void handleInternalState();
|
||||
void loadTargetFirmwareFromPersistentCfg();
|
||||
|
||||
/**
|
||||
* @brief Checks mode for commands requiring MODE_ON of MODE_NORMAL for execution.
|
||||
@ -380,7 +384,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
* @brief Fills command buffer with data to boot image (works only when star tracker is
|
||||
* in bootloader mode).
|
||||
*/
|
||||
void prepareBootCommand();
|
||||
void prepareBootCommand(startracker::FirmwareTarget target);
|
||||
|
||||
/**
|
||||
* @brief Fills command buffer with command to get the checksum of a flash part
|
||||
@ -467,6 +471,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t prepareRequestCentroidTm();
|
||||
ReturnValue_t prepareRequestCentroidsTm();
|
||||
ReturnValue_t prepareRequestContrastTm();
|
||||
ReturnValue_t prepareRequestBlobStatsTm();
|
||||
ReturnValue_t prepareRequestTrackingParams();
|
||||
ReturnValue_t prepareRequestValidationParams();
|
||||
ReturnValue_t prepareRequestAlgoParams();
|
||||
@ -527,6 +532,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t handleTm(const uint8_t* rawFrame, LocalPoolDataSetBase& dataset,
|
||||
const char* context);
|
||||
|
||||
ReturnValue_t handleSolution(const uint8_t* rawFrame);
|
||||
ReturnValue_t handleAutoBlobTm(const uint8_t* rawFrame);
|
||||
ReturnValue_t handleMatchedCentroidTm(const uint8_t* rawFrame);
|
||||
ReturnValue_t handleBlobTm(const uint8_t* rawFrame);
|
||||
@ -549,6 +555,9 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
void bootBootloader();
|
||||
bool reloadJsonCfgFile();
|
||||
ReturnValue_t acceptExternalDeviceCommands() override;
|
||||
|
||||
ReturnValue_t handleFirmwareUpdateCommand(const uint8_t* data, size_t size,
|
||||
startracker::FirmwareTarget target);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */
|
||||
|
@ -14,6 +14,12 @@ namespace startracker {
|
||||
static const Submode_t SUBMODE_BOOTLOADER = 1;
|
||||
static const Submode_t SUBMODE_FIRMWARE = 2;
|
||||
|
||||
enum class FirmwareTarget : uint8_t { MAIN = 1, BACKUP = 10 };
|
||||
|
||||
static constexpr char FW_TARGET_CFG_PATH[] = "startracker/fw-target.txt";
|
||||
|
||||
enum ParamId : uint32_t { FIRMWARE_TARGET = 1, FIRMWARE_TARGET_PERSISTENT = 2 };
|
||||
|
||||
class SdCardConfigPathGetter {
|
||||
public:
|
||||
virtual ~SdCardConfigPathGetter() = default;
|
||||
@ -322,6 +328,13 @@ enum PoolIds : lp_id_t {
|
||||
CONTRAST_B,
|
||||
CONTRAST_C,
|
||||
CONTRAST_D,
|
||||
|
||||
TICKS_BLOB_STATS,
|
||||
TIME_BLOB_STATS,
|
||||
BLOB_STATS_NOISE,
|
||||
BLOB_STATS_THOLD,
|
||||
BLOB_STATS_LVALID,
|
||||
BLOB_STATS_OFLOW,
|
||||
};
|
||||
|
||||
static const DeviceCommandId_t PING_REQUEST = 0;
|
||||
@ -373,7 +386,7 @@ static const DeviceCommandId_t REQ_DEBUG_CAMERA = 80;
|
||||
static const DeviceCommandId_t LOGLEVEL = 81;
|
||||
static const DeviceCommandId_t LOGSUBSCRIPTION = 82;
|
||||
static const DeviceCommandId_t DEBUG_CAMERA = 83;
|
||||
static const DeviceCommandId_t FIRMWARE_UPDATE = 84;
|
||||
static const DeviceCommandId_t FIRMWARE_UPDATE_MAIN = 84;
|
||||
static const DeviceCommandId_t DISABLE_TIMESTAMP_GENERATION = 85;
|
||||
static const DeviceCommandId_t ENABLE_TIMESTAMP_GENERATION = 86;
|
||||
static constexpr DeviceCommandId_t SET_TIME_FROM_SYS_TIME = 87;
|
||||
@ -388,6 +401,9 @@ static constexpr DeviceCommandId_t ADD_SECONDARY_TM_TO_NORMAL_MODE = 95;
|
||||
static constexpr DeviceCommandId_t RESET_SECONDARY_TM_SET = 96;
|
||||
static constexpr DeviceCommandId_t READ_SECONDARY_TM_SET = 97;
|
||||
static constexpr DeviceCommandId_t RELOAD_JSON_CFG_FILE = 100;
|
||||
static constexpr DeviceCommandId_t FIRMWARE_UPDATE_BACKUP = 101;
|
||||
static constexpr DeviceCommandId_t REQ_BLOB_STATS = 102;
|
||||
|
||||
static const DeviceCommandId_t NONE = 0xFFFFFFFF;
|
||||
|
||||
static const uint32_t VERSION_SET_ID = REQ_VERSION;
|
||||
@ -419,6 +435,7 @@ static const uint32_t BLOBS_SET_ID = REQ_BLOBS;
|
||||
static const uint32_t CENTROID_SET_ID = REQ_CENTROID;
|
||||
static const uint32_t CENTROIDS_SET_ID = REQ_CENTROIDS;
|
||||
static const uint32_t CONTRAST_SET_ID = REQ_CONTRAST;
|
||||
static const uint32_t BLOB_STATS_SET_ID = REQ_BLOB_STATS;
|
||||
|
||||
/** Max size of unencoded frame */
|
||||
static const size_t MAX_FRAME_SIZE = 1200;
|
||||
@ -485,11 +502,13 @@ static constexpr uint8_t CENTROID = 26;
|
||||
static constexpr uint8_t CENTROIDS = 37;
|
||||
static constexpr uint8_t AUTO_BLOB = 39;
|
||||
static constexpr uint8_t MATCHED_CENTROIDS = 40;
|
||||
static constexpr uint8_t BLOB_STATS = 49;
|
||||
} // namespace ID
|
||||
|
||||
namespace Program {
|
||||
static const uint8_t BOOTLOADER = 1;
|
||||
static const uint8_t FIRMWARE = 2;
|
||||
static const uint8_t FIRMWARE_MAIN = 2;
|
||||
static const uint8_t FIRMWARE_BACKUP = 3;
|
||||
} // namespace Program
|
||||
|
||||
namespace region_secrets {
|
||||
@ -509,7 +528,7 @@ static const uint32_t REGION_12_SECRET = 0x42fedef6;
|
||||
static const uint32_t REGION_13_SECRET = 0xe53cf10d;
|
||||
static const uint32_t REGION_14_SECRET = 0xe862b70b;
|
||||
static const uint32_t REGION_15_SECRET = 0x79b537ca;
|
||||
static const uint32_t secret[16]{
|
||||
static const uint32_t SECRETS[16]{
|
||||
REGION_0_SECRET, REGION_1_SECRET, REGION_2_SECRET, REGION_3_SECRET,
|
||||
REGION_4_SECRET, REGION_5_SECRET, REGION_6_SECRET, REGION_7_SECRET,
|
||||
REGION_8_SECRET, REGION_9_SECRET, REGION_10_SECRET, REGION_11_SECRET,
|
||||
@ -538,7 +557,12 @@ enum class FlashSections : uint8_t {
|
||||
};
|
||||
|
||||
// Flash region IDs of firmware partition
|
||||
enum class FirmwareRegions : uint32_t { FIRST = 1, LAST = 8 };
|
||||
enum class FirmwareRegions : uint32_t {
|
||||
FIRST_MAIN = 1,
|
||||
LAST_MAIN = 8,
|
||||
FIRST_BACKUP = 10,
|
||||
LAST_BACKUP = 16
|
||||
};
|
||||
|
||||
static const uint32_t FLASH_REGION_SIZE = 0x20000;
|
||||
|
||||
@ -1545,6 +1569,23 @@ class CentroidsSet : public StaticLocalDataSet<10> {
|
||||
lp_vec_t<uint8_t, 16>(sid.objectId, PoolIds::CENTROIDS_MAGNITUDES, this);
|
||||
};
|
||||
|
||||
class BlobStatsSet : public StaticLocalDataSet<6> {
|
||||
public:
|
||||
BlobStatsSet(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, BLOB_STATS_SET_ID) {}
|
||||
|
||||
// Data received from the Centroids Telemetry Set (ID 49)
|
||||
lp_var_t<uint32_t> ticks = lp_var_t<uint32_t>(sid.objectId, PoolIds::TICKS_BLOB_STATS, this);
|
||||
lp_var_t<uint64_t> time = lp_var_t<uint64_t>(sid.objectId, PoolIds::TIME_BLOB_STATS, this);
|
||||
lp_vec_t<uint8_t, 16> noise =
|
||||
lp_vec_t<uint8_t, 16>(sid.objectId, PoolIds::BLOB_STATS_NOISE, this);
|
||||
lp_vec_t<uint8_t, 16> thold =
|
||||
lp_vec_t<uint8_t, 16>(sid.objectId, PoolIds::BLOB_STATS_THOLD, this);
|
||||
lp_vec_t<uint8_t, 16> lvalid =
|
||||
lp_vec_t<uint8_t, 16>(sid.objectId, PoolIds::BLOB_STATS_LVALID, this);
|
||||
lp_vec_t<uint8_t, 16> oflow =
|
||||
lp_vec_t<uint8_t, 16>(sid.objectId, PoolIds::BLOB_STATS_OFLOW, this);
|
||||
};
|
||||
|
||||
class ContrastSet : public StaticLocalDataSet<8> {
|
||||
public:
|
||||
ContrastSet(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, CONTRAST_SET_ID) {}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,16 +4,20 @@
|
||||
#include <eive/objects.h>
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
#include <fsfw/coordinates/Sgp4Propagator.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/health/HealthTable.h>
|
||||
#include <fsfw/parameters/ParameterHelper.h>
|
||||
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
||||
#include <fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h>
|
||||
#include <fsfw_hal/devicehandlers/MgmRM3100Handler.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/acs/imtqHelpers.h>
|
||||
#include <mission/acs/rwHelpers.h>
|
||||
#include <mission/acs/susMax1227Helpers.h>
|
||||
#include <mission/config/torquer.h>
|
||||
#include <mission/controller/acs/ActuatorCmd.h>
|
||||
#include <mission/controller/acs/AttitudeEstimation.h>
|
||||
#include <mission/controller/acs/FusedRotationEstimation.h>
|
||||
#include <mission/controller/acs/Guidance.h>
|
||||
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
|
||||
@ -23,13 +27,18 @@
|
||||
#include <mission/controller/acs/control/PtgCtrl.h>
|
||||
#include <mission/controller/acs/control/SafeCtrl.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
#include <mission/memory/SdCardMountedIF.h>
|
||||
#include <mission/utility/trace.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
|
||||
class AcsController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
||||
public:
|
||||
static constexpr dur_millis_t INIT_DELAY = 500;
|
||||
|
||||
AcsController(object_id_t objectId, bool enableHkSets);
|
||||
AcsController(object_id_t objectId, bool enableHkSets, SdCardMountedIF& sdcMan);
|
||||
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
@ -37,11 +46,8 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
uint16_t startAtIndex) override;
|
||||
|
||||
protected:
|
||||
void performSafe();
|
||||
void performDetumble();
|
||||
void performPointingCtrl();
|
||||
|
||||
private:
|
||||
static constexpr int16_t ZERO_VEC3_INT16[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC3[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC4[4] = {0, 0, 0, 0};
|
||||
static constexpr double RW_OFF_TORQUE[4] = {0, 0, 0, 0};
|
||||
@ -49,8 +55,16 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
|
||||
bool enableHkSets = false;
|
||||
|
||||
SdCardMountedIF& sdcMan;
|
||||
|
||||
timeval timeAbsolute;
|
||||
timeval timeRelative;
|
||||
double timeDelta = 0.0;
|
||||
timeval oldTimeRelative;
|
||||
|
||||
AcsParameters acsParameters;
|
||||
SensorProcessing sensorProcessing;
|
||||
AttitudeEstimation attitudeEstimation;
|
||||
FusedRotationEstimation fusedRotationEstimation;
|
||||
Navigation navigation;
|
||||
ActuatorCmd actuatorCmd;
|
||||
@ -66,7 +80,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
uint8_t detumbleCounter = 0;
|
||||
uint8_t multipleRwUnavailableCounter = 0;
|
||||
bool mekfInvalidFlag = false;
|
||||
uint16_t mekfInvalidCounter = 0;
|
||||
uint16_t ptgCtrlLostCounter = 0;
|
||||
bool safeCtrlFailureFlag = false;
|
||||
uint8_t safeCtrlFailureCounter = 0;
|
||||
uint8_t resetMekfCount = 0;
|
||||
@ -75,6 +89,8 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
int32_t cmdSpeedRws[4] = {0, 0, 0, 0};
|
||||
int16_t cmdDipoleMtqs[3] = {0, 0, 0};
|
||||
|
||||
acsctrl::RwAvail rwAvail;
|
||||
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
uint32_t opCounter = 0;
|
||||
#endif
|
||||
@ -82,15 +98,22 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
enum class InternalState { STARTUP, INITIAL_DELAY, READY };
|
||||
InternalState internalState = InternalState::STARTUP;
|
||||
|
||||
enum class DetumbleState {
|
||||
NO_DETUMBLE,
|
||||
DETUMBLE_FROM_PTG,
|
||||
PTG_TO_SAFE_TRANSITION,
|
||||
DETUMBLE_FROM_SAFE,
|
||||
IN_DETUMBLE
|
||||
};
|
||||
DetumbleState detumbleState = DetumbleState::NO_DETUMBLE;
|
||||
|
||||
/** Device command IDs */
|
||||
static const DeviceCommandId_t SOLAR_ARRAY_DEPLOYMENT_SUCCESSFUL = 0x0;
|
||||
static const DeviceCommandId_t RESET_MEKF = 0x1;
|
||||
static const DeviceCommandId_t RESTORE_MEKF_NONFINITE_RECOVERY = 0x2;
|
||||
static const DeviceCommandId_t UPDATE_TLE = 0x3;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_CTRL;
|
||||
//! [EXPORT] : [COMMENT] File deletion failed and at least one file is still existent.
|
||||
static constexpr ReturnValue_t FILE_DELETION_FAILED = MAKE_RETURN_CODE(0);
|
||||
static const DeviceCommandId_t READ_TLE = 0x4;
|
||||
static const DeviceCommandId_t UPDATE_MEKF_STANDARD_DEVIATIONS = 0x5;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
@ -110,6 +133,13 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void modeChanged(Mode_t mode, Submode_t submode);
|
||||
void announceMode(bool recursive);
|
||||
|
||||
void performAttitudeControl();
|
||||
void performSafe();
|
||||
void performDetumble();
|
||||
void performPointingCtrl();
|
||||
|
||||
void handleDetumbling();
|
||||
|
||||
void safeCtrlFailure(uint8_t mgmFailure, uint8_t sensorFailure);
|
||||
|
||||
ReturnValue_t commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
@ -120,10 +150,16 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void updateActuatorCmdData(const int16_t* mtqTargetDipole);
|
||||
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
|
||||
const int16_t* mtqTargetDipole);
|
||||
void updateCtrlValData(uint8_t safeModeStrat);
|
||||
void updateCtrlValData(double errAng, uint8_t safeModeStrat);
|
||||
void updateCtrlValData(acs::ControlModeStrategy ctrlStrat);
|
||||
void updateCtrlValData(double errAng, acs::ControlModeStrategy ctrlStrat);
|
||||
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
|
||||
const double* tgtRotRate);
|
||||
const double* tgtRotRate, acs::ControlModeStrategy cStrat);
|
||||
|
||||
ReturnValue_t updateTle(const uint8_t* line1, const uint8_t* line2, bool fromFile);
|
||||
ReturnValue_t writeTleToFs(const uint8_t* tle);
|
||||
ReturnValue_t readTleFromFs(uint8_t* line1, uint8_t* line2);
|
||||
|
||||
const std::string TLE_FILE = "/conf/tle.txt";
|
||||
|
||||
/* ACS Sensor Values */
|
||||
ACS::SensorValues sensorValues;
|
||||
@ -212,11 +248,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
PoolEntry<double> gpsVelocity = PoolEntry<double>(3);
|
||||
PoolEntry<uint8_t> gpsSource = PoolEntry<uint8_t>();
|
||||
|
||||
// MEKF
|
||||
acsctrl::MekfData mekfData;
|
||||
// Attitude Estimation
|
||||
acsctrl::AttitudeEstimationData attitudeEstimationData;
|
||||
PoolEntry<double> quatMekf = PoolEntry<double>(4);
|
||||
PoolEntry<double> satRotRateMekf = PoolEntry<double>(3);
|
||||
PoolEntry<uint8_t> mekfStatus = PoolEntry<uint8_t>();
|
||||
PoolEntry<double> quatQuest = PoolEntry<double>(4);
|
||||
|
||||
// Ctrl Values
|
||||
acsctrl::CtrlValData ctrlValData;
|
||||
@ -234,17 +271,24 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
|
||||
// Fused Rot Rate
|
||||
acsctrl::FusedRotRateData fusedRotRateData;
|
||||
PoolEntry<double> rotRateOrthogonal = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateParallel = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotal = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotSusMgm = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotSource = PoolEntry<double>(3);
|
||||
PoolEntry<uint8_t> rotRateSource = PoolEntry<uint8_t>();
|
||||
|
||||
// TLE Dataset
|
||||
acsctrl::TleData tleData;
|
||||
PoolEntry<uint8_t> line1 = PoolEntry<uint8_t>(69);
|
||||
PoolEntry<uint8_t> line2 = PoolEntry<uint8_t>(69);
|
||||
// Fused Rot Rate Sources
|
||||
acsctrl::FusedRotRateSourcesData fusedRotRateSourcesData;
|
||||
PoolEntry<double> rotRateOrthogonalSusMgm = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateParallelSusMgm = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotalSusMgm = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotalQuest = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotalStr = PoolEntry<double>(3);
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners
|
||||
Countdown initialCountdown = Countdown(INIT_DELAY);
|
||||
|
||||
// Countdown after which the detumbling mode change should have been finished
|
||||
static constexpr dur_millis_t MAX_DURATION = 60 * 1e3;
|
||||
Countdown detumbleTransitionCountdow = Countdown(MAX_DURATION);
|
||||
};
|
||||
|
||||
#endif /* MISSION_CONTROLLER_ACSCONTROLLER_H_ */
|
||||
|
@ -157,7 +157,12 @@ ReturnValue_t PowerController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
|
||||
void PowerController::calculateStateOfCharge() {
|
||||
// get time
|
||||
Clock::getClock_timeval(&now);
|
||||
Clock::getClockMonotonic(&now);
|
||||
double timeDelta = 0.0;
|
||||
if (now.tv_sec != 0 and oldTime.tv_sec != 0) {
|
||||
timeDelta = timevalOperations::toDouble(now - oldTime);
|
||||
}
|
||||
oldTime = now;
|
||||
|
||||
// update EPS HK values
|
||||
ReturnValue_t result = updateEpsData();
|
||||
@ -173,13 +178,11 @@ void PowerController::calculateStateOfCharge() {
|
||||
pwrCtrlCoreHk.setValidity(false, true);
|
||||
}
|
||||
}
|
||||
// store time for next run
|
||||
oldTime = now;
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate total battery current
|
||||
iBat = p60CoreHk.batteryCurrent.value + bpxBatteryHk.dischargeCurrent.value;
|
||||
iBat = p60CoreHk.batteryCurrent.value - bpxBatteryHk.dischargeCurrent.value;
|
||||
|
||||
result = calculateOpenCircuitVoltageCharge();
|
||||
if (result != returnvalue::OK) {
|
||||
@ -195,12 +198,10 @@ void PowerController::calculateStateOfCharge() {
|
||||
pwrCtrlCoreHk.coulombCounterCharge.setValid(false);
|
||||
}
|
||||
}
|
||||
// store time for next run
|
||||
oldTime = now;
|
||||
return;
|
||||
}
|
||||
|
||||
result = calculateCoulombCounterCharge();
|
||||
result = calculateCoulombCounterCharge(timeDelta);
|
||||
if (result != returnvalue::OK) {
|
||||
// notifying events have already been triggered
|
||||
{
|
||||
@ -215,8 +216,6 @@ void PowerController::calculateStateOfCharge() {
|
||||
pwrCtrlCoreHk.coulombCounterCharge.setValid(false);
|
||||
}
|
||||
}
|
||||
// store time for next run
|
||||
oldTime = now;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -231,8 +230,6 @@ void PowerController::calculateStateOfCharge() {
|
||||
pwrCtrlCoreHk.setValidity(true, true);
|
||||
}
|
||||
}
|
||||
// store time for next run
|
||||
oldTime = now;
|
||||
}
|
||||
|
||||
void PowerController::watchStateOfCharge() {
|
||||
@ -285,12 +282,14 @@ ReturnValue_t PowerController::calculateOpenCircuitVoltageCharge() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PowerController::calculateCoulombCounterCharge() {
|
||||
double timeDiff = timevalOperations::toDouble(now - oldTime);
|
||||
if (timeDiff > maxAllowedTimeDiff) {
|
||||
ReturnValue_t PowerController::calculateCoulombCounterCharge(double timeDelta) {
|
||||
if (timeDelta == 0.0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (timeDelta > maxAllowedTimeDiff) {
|
||||
// should not be a permanent state so no spam protection required
|
||||
triggerEvent(power::TIMEDELTA_OUT_OF_BOUNDS, static_cast<uint32_t>(timeDiff * 10));
|
||||
sif::error << "Power Controller::Time delta too large for Coulomb Counter: " << timeDiff
|
||||
triggerEvent(power::TIMEDELTA_OUT_OF_BOUNDS, static_cast<uint32_t>(timeDelta * 10));
|
||||
sif::error << "Power Controller::Time delta too large for Coulomb Counter: " << timeDelta
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
@ -298,7 +297,7 @@ ReturnValue_t PowerController::calculateCoulombCounterCharge() {
|
||||
coulombCounterCharge = openCircuitVoltageCharge;
|
||||
} else {
|
||||
coulombCounterCharge =
|
||||
coulombCounterCharge + iBat * CONVERT_FROM_MILLI * timeDiff * SECONDS_TO_HOURS;
|
||||
coulombCounterCharge + iBat * CONVERT_FROM_MILLI * timeDelta * SECONDS_TO_HOURS;
|
||||
if (coulombCounterCharge >= coulombCounterChargeUpperThreshold) {
|
||||
coulombCounterCharge = coulombCounterChargeUpperThreshold;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class PowerController : public ExtendedControllerBase, public ReceivesParameterM
|
||||
void calculateStateOfCharge();
|
||||
void watchStateOfCharge();
|
||||
ReturnValue_t calculateOpenCircuitVoltageCharge();
|
||||
ReturnValue_t calculateCoulombCounterCharge();
|
||||
ReturnValue_t calculateCoulombCounterCharge(double timeDelta);
|
||||
ReturnValue_t updateEpsData();
|
||||
float charge2stateOfCharge(float capacity, bool coulombCounter);
|
||||
ReturnValue_t lookUpTableOcvIdxFinder(float voltage, uint8_t& idx, bool paramCmd);
|
||||
@ -57,9 +57,9 @@ class PowerController : public ExtendedControllerBase, public ReceivesParameterM
|
||||
float batteryMaximumCapacity = 2.6 * 2; // [Ah]
|
||||
float coulombCounterVoltageUpperThreshold = 16.2; // [V]
|
||||
double maxAllowedTimeDiff = 1.5; // [s]
|
||||
float payloadOpLimitOn = 0.90; // [%]
|
||||
float payloadOpLimitLow = 0.75; // [%]
|
||||
float higherModesLimit = 0.6; // [%]
|
||||
float payloadOpLimitOn = 0.80; // [%]
|
||||
float payloadOpLimitLow = 0.65; // [%]
|
||||
float higherModesLimit = 0.60; // [%]
|
||||
|
||||
// OCV Look-up-Table {[Ah],[V]}
|
||||
static constexpr uint8_t LOOK_UP_TABLE_MAX_IDX = 99;
|
||||
|
@ -1641,7 +1641,11 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
|
||||
bool heaterAvailable = true;
|
||||
|
||||
HasHealthIF::HealthState mainHealth = heaterHandler.getHealth(switchNr);
|
||||
heater::SwitchState mainState = heaterHandler.getSwitchState(switchNr);
|
||||
HasHealthIF::HealthState redHealth = heaterHandler.getHealth(redSwitchNr);
|
||||
if (mainHealth == HasHealthIF::EXTERNAL_CONTROL and mainState == heater::SwitchState::ON) {
|
||||
return false;
|
||||
}
|
||||
if (mainHealth != HasHealthIF::HEALTHY) {
|
||||
if (redHealth == HasHealthIF::HEALTHY) {
|
||||
switchNr = redSwitchNr;
|
||||
@ -1656,6 +1660,7 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
|
||||
} else {
|
||||
ctrlCtx.redSwitchNrInUse = false;
|
||||
}
|
||||
|
||||
return heaterAvailable;
|
||||
}
|
||||
|
||||
@ -1792,7 +1797,8 @@ void ThermalController::heaterMaxDurationControl(
|
||||
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) {
|
||||
// Right now, we only track the maximum duration for heater which were commanded by the TCS
|
||||
// controller.
|
||||
if (currentHeaterStates[i] == heater::SwitchState::ON and
|
||||
if (heaterHandler.getHealth(static_cast<heater::Switch>(i)) != HasHealthIF::EXTERNAL_CONTROL and
|
||||
currentHeaterStates[i] == heater::SwitchState::ON and
|
||||
heaterStates[i].trackHeaterMaxBurnTime and
|
||||
heaterStates[i].heaterOnMaxBurnTime.hasTimedOut()) {
|
||||
heaterStates[i].switchTransition = false;
|
||||
|
@ -24,11 +24,23 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(onBoardParams.sampleTime);
|
||||
break;
|
||||
case 0x1:
|
||||
parameterWrapper->set(onBoardParams.mekfViolationTimer);
|
||||
parameterWrapper->set(onBoardParams.ptgCtrlLostTimer);
|
||||
break;
|
||||
case 0x2:
|
||||
parameterWrapper->set(onBoardParams.fusedRateSafeDuringEclipse);
|
||||
break;
|
||||
case 0x3:
|
||||
parameterWrapper->set(onBoardParams.fusedRateFromStr);
|
||||
break;
|
||||
case 0x4:
|
||||
parameterWrapper->set(onBoardParams.fusedRateFromQuest);
|
||||
break;
|
||||
case 0x5:
|
||||
parameterWrapper->set(onBoardParams.questFilterWeight);
|
||||
break;
|
||||
case 0x6:
|
||||
parameterWrapper->set(onBoardParams.questAngleLimit);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -324,16 +336,16 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->setMatrix(rwMatrices.pseudoInverse);
|
||||
break;
|
||||
case 0x2:
|
||||
parameterWrapper->setMatrix(rwMatrices.without1);
|
||||
parameterWrapper->setMatrix(rwMatrices.pseudoInverseWithoutRW1);
|
||||
break;
|
||||
case 0x3:
|
||||
parameterWrapper->setMatrix(rwMatrices.without2);
|
||||
parameterWrapper->setMatrix(rwMatrices.pseudoInverseWithoutRW2);
|
||||
break;
|
||||
case 0x4:
|
||||
parameterWrapper->setMatrix(rwMatrices.without3);
|
||||
parameterWrapper->setMatrix(rwMatrices.pseudoInverseWithoutRW3);
|
||||
break;
|
||||
case 0x5:
|
||||
parameterWrapper->setMatrix(rwMatrices.without4);
|
||||
parameterWrapper->setMatrix(rwMatrices.pseudoInverseWithoutRW4);
|
||||
break;
|
||||
case 0x6:
|
||||
parameterWrapper->setVector(rwMatrices.nullspaceVector);
|
||||
@ -423,7 +435,7 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(idleModeControllerParameters.desatOn);
|
||||
break;
|
||||
case 0x9:
|
||||
parameterWrapper->set(idleModeControllerParameters.enableAntiStiction);
|
||||
parameterWrapper->set(idleModeControllerParameters.useMekf);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
@ -459,7 +471,7 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(targetModeControllerParameters.desatOn);
|
||||
break;
|
||||
case 0x9:
|
||||
parameterWrapper->set(targetModeControllerParameters.enableAntiStiction);
|
||||
parameterWrapper->set(targetModeControllerParameters.useMekf);
|
||||
break;
|
||||
case 0xA:
|
||||
parameterWrapper->setVector(targetModeControllerParameters.refDirection);
|
||||
@ -528,7 +540,7 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(gsTargetModeControllerParameters.desatOn);
|
||||
break;
|
||||
case 0x9:
|
||||
parameterWrapper->set(gsTargetModeControllerParameters.enableAntiStiction);
|
||||
parameterWrapper->set(gsTargetModeControllerParameters.useMekf);
|
||||
break;
|
||||
case 0xA:
|
||||
parameterWrapper->setVector(gsTargetModeControllerParameters.refDirection);
|
||||
@ -545,6 +557,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0xE:
|
||||
parameterWrapper->set(gsTargetModeControllerParameters.altitudeTgt);
|
||||
break;
|
||||
case 0xF:
|
||||
parameterWrapper->set(gsTargetModeControllerParameters.rotRateLimit);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -579,7 +594,7 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(nadirModeControllerParameters.desatOn);
|
||||
break;
|
||||
case 0x9:
|
||||
parameterWrapper->set(nadirModeControllerParameters.enableAntiStiction);
|
||||
parameterWrapper->set(nadirModeControllerParameters.useMekf);
|
||||
break;
|
||||
case 0xA:
|
||||
parameterWrapper->setVector(nadirModeControllerParameters.refDirection);
|
||||
@ -627,7 +642,7 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(inertialModeControllerParameters.desatOn);
|
||||
break;
|
||||
case 0x9:
|
||||
parameterWrapper->set(inertialModeControllerParameters.enableAntiStiction);
|
||||
parameterWrapper->set(inertialModeControllerParameters.useMekf);
|
||||
break;
|
||||
case 0xA:
|
||||
parameterWrapper->setVector(inertialModeControllerParameters.tgtQuat);
|
||||
@ -708,22 +723,25 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case (0x11): // KalmanFilterParameters
|
||||
switch (parameterId) {
|
||||
case 0x0:
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseSTR);
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseStr);
|
||||
break;
|
||||
case 0x1:
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseSS);
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseSus);
|
||||
break;
|
||||
case 0x2:
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseMAG);
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseMgm);
|
||||
break;
|
||||
case 0x3:
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseGYR);
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseGyr);
|
||||
break;
|
||||
case 0x4:
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseArwGYR);
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseGyrArw);
|
||||
break;
|
||||
case 0x5:
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseBsGYR);
|
||||
parameterWrapper->set(kalmanFilterParameters.sensorNoiseGyrBs);
|
||||
break;
|
||||
case 0x6:
|
||||
parameterWrapper->set(kalmanFilterParameters.allowStr);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
|
@ -8,6 +8,9 @@
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
class AcsParameters : public HasParametersIF {
|
||||
private:
|
||||
static constexpr double DEG2RAD = M_PI / 180.;
|
||||
|
||||
public:
|
||||
AcsParameters();
|
||||
virtual ~AcsParameters();
|
||||
@ -18,8 +21,12 @@ class AcsParameters : public HasParametersIF {
|
||||
|
||||
struct OnBoardParams {
|
||||
double sampleTime = 0.4; // [s]
|
||||
uint16_t mekfViolationTimer = 750;
|
||||
uint16_t ptgCtrlLostTimer = 750;
|
||||
uint8_t fusedRateSafeDuringEclipse = true;
|
||||
uint8_t fusedRateFromStr = true;
|
||||
uint8_t fusedRateFromQuest = true;
|
||||
double questFilterWeight = 0.9;
|
||||
double questAngleLimit = 5 * DEG2RAD;
|
||||
} onBoardParams;
|
||||
|
||||
struct InertiaEIVE {
|
||||
@ -75,9 +82,9 @@ class AcsParameters : public HasParametersIF {
|
||||
{-0.007534, 1.253879, 0.006812},
|
||||
{-0.037072, 0.006812, 1.313158}};
|
||||
|
||||
float mgm02variance[3] = {pow(3.2e-7, 2), pow(3.2e-7, 2), pow(4.1e-7, 2)};
|
||||
float mgm13variance[3] = {pow(1.5e-8, 2), pow(1.5e-8, 2), pow(1.5e-8, 2)};
|
||||
float mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)};
|
||||
double mgm02variance[3] = {pow(3.2e-7, 2), pow(3.2e-7, 2), pow(4.1e-7, 2)};
|
||||
double mgm13variance[3] = {pow(1.5e-8, 2), pow(1.5e-8, 2), pow(1.5e-8, 2)};
|
||||
double mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)};
|
||||
float mgmVectorFilterWeight = 0.85;
|
||||
float mgmDerivativeFilterWeight = 0.99;
|
||||
uint8_t useMgm4 = false;
|
||||
@ -770,7 +777,7 @@ class AcsParameters : public HasParametersIF {
|
||||
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
|
||||
-0.000889232196185857, -0.00168429567131815}};
|
||||
float susBrightnessThreshold = 0.7;
|
||||
float susVectorFilterWeight = .85;
|
||||
float susVectorFilterWeight = .95;
|
||||
float susRateFilterWeight = .99;
|
||||
} susHandlingParameters;
|
||||
|
||||
@ -787,10 +794,10 @@ class AcsParameters : public HasParametersIF {
|
||||
|
||||
/* var = sigma^2, sigma = RND*sqrt(freq), following values are RND^2 and not var as freq is
|
||||
* assumed to be equal for the same class of sensors */
|
||||
float gyr02variance[3] = {pow(4.6e-3, 2), // RND_x = 3.0e-3 deg/s/sqrt(Hz) rms
|
||||
double gyr02variance[3] = {pow(4.6e-3, 2), // RND_x = 3.0e-3 deg/s/sqrt(Hz) rms
|
||||
pow(4.6e-3, 2), // RND_y = 3.0e-3 deg/s/sqrt(Hz) rms
|
||||
pow(6.1e-3, 2)}; // RND_z = 4.3e-3 deg/s/sqrt(Hz) rms
|
||||
float gyr13variance[3] = {pow(11e-3, 2), pow(11e-3, 2), pow(11e-3, 2)};
|
||||
double gyr13variance[3] = {pow(11e-3, 2), pow(11e-3, 2), pow(11e-3, 2)};
|
||||
uint8_t preferAdis = false;
|
||||
float gyrFilterWeight = 0.6;
|
||||
} gyrHandlingParameters;
|
||||
@ -809,19 +816,19 @@ class AcsParameters : public HasParametersIF {
|
||||
} rwHandlingParameters;
|
||||
|
||||
struct RwMatrices {
|
||||
double alignmentMatrix[3][4] = {{0.9205, 0.0000, -0.9205, 0.0000},
|
||||
{0.0000, -0.9205, 0.0000, 0.9205},
|
||||
{0.3907, 0.3907, 0.3907, 0.3907}};
|
||||
double alignmentMatrix[3][4] = {{-0.9205, 0.0000, 0.9205, 0.0000},
|
||||
{0.0000, 0.9205, 0.0000, -0.9205},
|
||||
{-0.3907, -0.3907, -0.3907, -0.3907}};
|
||||
double pseudoInverse[4][3] = {
|
||||
{0.5432, 0, 0.6398}, {0, -0.5432, 0.6398}, {-0.5432, 0, 0.6398}, {0, 0.5432, 0.6398}};
|
||||
double without1[4][3] = {
|
||||
{0, 0, 0}, {0.5432, -0.5432, 1.2797}, {-1.0864, 0, 0}, {0.5432, 0.5432, 1.2797}};
|
||||
double without2[4][3] = {
|
||||
{0.5432, -0.5432, 1.2797}, {0, 0, 0}, {-0.5432, -0.5432, 1.2797}, {0, 1.0864, 0}};
|
||||
double without3[4][3] = {
|
||||
{1.0864, 0, 0}, {-0.5432, -0.5432, 1.2797}, {0, 0, 0}, {-0.5432, 0.5432, 1.2797}};
|
||||
double without4[4][3] = {
|
||||
{0.5432, 0.5432, 1.2797}, {0, -1.0864, 0}, {-0.5432, 0.5432, 1.2797}, {0, 0, 0}};
|
||||
{-0.5432, 0, -0.6399}, {0, 0.5432, -0.6399}, {0.5432, 0, -0.6399}, {0, -0.5432, -0.6399}};
|
||||
double pseudoInverseWithoutRW1[4][3] = {
|
||||
{0, 0, 0}, {-0.5432, 0.5432, -1.2798}, {1.0864, 0, 0}, {-0.5432, -0.5432, -1.2798}};
|
||||
double pseudoInverseWithoutRW2[4][3] = {
|
||||
{-0.5432, 0.5432, -1.2798}, {0, 0, 0}, {0.5432, 0.5432, -1.2798}, {0, -1.0864, 0}};
|
||||
double pseudoInverseWithoutRW3[4][3] = {
|
||||
{-1.0864, 0, 0}, {0.5432, 0.5432, -1.2798}, {0, 0, 0}, {0.5432, -0.5432, -1.2798}};
|
||||
double pseudoInverseWithoutRW4[4][3] = {
|
||||
{-0.5432, -0.5432, -1.2798}, {0, 1.0864, 0}, {0.5432, -0.5432, -1.2798}, {0, 0, 0}};
|
||||
double nullspaceVector[4] = {-1, 1, -1, 1};
|
||||
} rwMatrices;
|
||||
|
||||
@ -851,7 +858,7 @@ class AcsParameters : public HasParametersIF {
|
||||
struct PointingLawParameters {
|
||||
double zeta = 0.3;
|
||||
double om = 0.3;
|
||||
double omMax = 1 * M_PI / 180;
|
||||
double omMax = 1 * DEG2RAD;
|
||||
double qiMin = 0.1;
|
||||
|
||||
double gainNullspace = 0.01;
|
||||
@ -860,7 +867,7 @@ class AcsParameters : public HasParametersIF {
|
||||
double desatMomentumRef[3] = {0, 0, 0};
|
||||
double deSatGainFactor = 1000;
|
||||
uint8_t desatOn = true;
|
||||
uint8_t enableAntiStiction = true;
|
||||
uint8_t useMekf = true;
|
||||
} pointingLawParameters;
|
||||
|
||||
struct IdleModeControllerParameters : PointingLawParameters {
|
||||
@ -873,15 +880,15 @@ class AcsParameters : public HasParametersIF {
|
||||
uint8_t timeElapsedMax = 10; // rot rate calculations
|
||||
|
||||
// Default is Stuttgart GS
|
||||
double latitudeTgt = 48.7495 * M_PI / 180.; // [rad] Latitude
|
||||
double longitudeTgt = 9.10384 * M_PI / 180.; // [rad] Longitude
|
||||
double latitudeTgt = 48.7495 * DEG2RAD; // [rad] Latitude
|
||||
double longitudeTgt = 9.10384 * DEG2RAD; // [rad] Longitude
|
||||
double altitudeTgt = 500; // [m]
|
||||
|
||||
// For one-axis control:
|
||||
uint8_t avoidBlindStr = true;
|
||||
double blindAvoidStart = 1.5;
|
||||
double blindAvoidStop = 2.5;
|
||||
double blindRotRate = 1 * M_PI / 180;
|
||||
double blindRotRate = 1. * DEG2RAD;
|
||||
} targetModeControllerParameters;
|
||||
|
||||
struct GsTargetModeControllerParameters : PointingLawParameters {
|
||||
@ -889,9 +896,10 @@ class AcsParameters : public HasParametersIF {
|
||||
uint8_t timeElapsedMax = 10; // rot rate calculations
|
||||
|
||||
// Default is Stuttgart GS
|
||||
double latitudeTgt = 48.7495 * M_PI / 180.; // [rad] Latitude
|
||||
double longitudeTgt = 9.10384 * M_PI / 180.; // [rad] Longitude
|
||||
double latitudeTgt = 48.7495 * DEG2RAD; // [rad] Latitude
|
||||
double longitudeTgt = 9.10384 * DEG2RAD; // [rad] Longitude
|
||||
double altitudeTgt = 500; // [m]
|
||||
double rotRateLimit = .75 * DEG2RAD;
|
||||
} gsTargetModeControllerParameters;
|
||||
|
||||
struct NadirModeControllerParameters : PointingLawParameters {
|
||||
@ -908,8 +916,8 @@ class AcsParameters : public HasParametersIF {
|
||||
} inertialModeControllerParameters;
|
||||
|
||||
struct StrParameters {
|
||||
double exclusionAngle = 20 * M_PI / 180;
|
||||
double boresightAxis[3] = {0.7593, 0.0000, -0.6508}; // geometry frame
|
||||
double exclusionAngle = 20. * DEG2RAD;
|
||||
double boresightAxis[3] = {0.7593, 0.0000, -0.6508}; // body rf
|
||||
} strParameters;
|
||||
|
||||
struct GpsParameters {
|
||||
@ -922,25 +930,27 @@ class AcsParameters : public HasParametersIF {
|
||||
|
||||
struct SunModelParameters {
|
||||
float domega = 36000.771;
|
||||
float omega_0 = 280.46 * M_PI / 180.; // RAAN plus argument of
|
||||
float omega_0 = 280.46 * DEG2RAD; // RAAN plus argument of
|
||||
// perigee
|
||||
float m_0 = 357.5277; // coefficients for mean anomaly
|
||||
float dm = 35999.049; // coefficients for mean anomaly
|
||||
float e = 23.4392911 * M_PI / 180.; // angle of earth's rotation axis
|
||||
float e1 = 0.74508 * M_PI / 180.;
|
||||
float e = 23.4392911 * DEG2RAD; // angle of earth's rotation axis
|
||||
float e1 = 0.74508 * DEG2RAD;
|
||||
|
||||
float p1 = 6892. / 3600. * M_PI / 180.; // some parameter
|
||||
float p2 = 72. / 3600. * M_PI / 180.; // some parameter
|
||||
float p1 = 6892. / 3600. * DEG2RAD; // some parameter
|
||||
float p2 = 72. / 3600. * DEG2RAD; // some parameter
|
||||
} sunModelParameters;
|
||||
|
||||
struct KalmanFilterParameters {
|
||||
double sensorNoiseSTR = 0.1 * M_PI / 180;
|
||||
double sensorNoiseSS = 8 * M_PI / 180;
|
||||
double sensorNoiseMAG = 4 * M_PI / 180;
|
||||
double sensorNoiseGYR = 0.1 * M_PI / 180;
|
||||
double sensorNoiseStr = 0.0028 * DEG2RAD;
|
||||
double sensorNoiseSus = 8. * DEG2RAD;
|
||||
double sensorNoiseMgm = 4. * DEG2RAD;
|
||||
double sensorNoiseGyr = 0.1 * DEG2RAD;
|
||||
|
||||
double sensorNoiseArwGYR = 3 * 0.0043 * M_PI / sqrt(10) / 180; // Angular Random Walk
|
||||
double sensorNoiseBsGYR = 3 * M_PI / 180 / 3600; // Bias Stability
|
||||
double sensorNoiseGyrArw = 3. * 0.0043 / sqrt(10) * DEG2RAD; // Angular Random Walk
|
||||
double sensorNoiseGyrBs = 3. / 3600. * DEG2RAD; // Bias Stability
|
||||
|
||||
uint8_t allowStr = true;
|
||||
} kalmanFilterParameters;
|
||||
|
||||
struct MagnetorquerParameter {
|
||||
@ -956,8 +966,8 @@ class AcsParameters : public HasParametersIF {
|
||||
|
||||
struct DetumbleParameter {
|
||||
uint8_t detumblecounter = 75; // 30 s
|
||||
double omegaDetumbleStart = 2 * M_PI / 180;
|
||||
double omegaDetumbleEnd = 1 * M_PI / 180;
|
||||
double omegaDetumbleStart = 2 * DEG2RAD;
|
||||
double omegaDetumbleEnd = 1 * DEG2RAD;
|
||||
double gainBdot = pow(10.0, -3.3);
|
||||
double gainFull = pow(10.0, -2.3);
|
||||
uint8_t useFullDetumbleLaw = false;
|
||||
|
123
mission/controller/acs/AttitudeEstimation.cpp
Normal file
123
mission/controller/acs/AttitudeEstimation.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include "AttitudeEstimation.h"
|
||||
|
||||
AttitudeEstimation::AttitudeEstimation(AcsParameters *acsParameters_) {
|
||||
acsParameters = acsParameters_;
|
||||
}
|
||||
|
||||
AttitudeEstimation::~AttitudeEstimation() {}
|
||||
|
||||
void AttitudeEstimation::quest(acsctrl::SusDataProcessed *susData,
|
||||
acsctrl::MgmDataProcessed *mgmData,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData) {
|
||||
if (not(susData->susVecTot.isValid() and susData->sunIjkModel.isValid() and
|
||||
mgmData->mgmVecTot.isValid() and mgmData->magIgrfModel.isValid())) {
|
||||
{
|
||||
PoolReadGuard pg{attitudeEstimationData};
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(attitudeEstimationData->quatQuest.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
attitudeEstimationData->quatQuest.setValid(false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize Data
|
||||
double normMgmB[3] = {0, 0, 0}, normMgmI[3] = {0, 0, 0}, normSusB[3] = {0, 0, 0},
|
||||
normSusI[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(susData->susVecTot.value, normSusB, 3);
|
||||
VectorOperations<double>::normalize(susData->sunIjkModel.value, normSusI, 3);
|
||||
VectorOperations<double>::normalize(mgmData->mgmVecTot.value, normMgmB, 3);
|
||||
VectorOperations<double>::normalize(mgmData->magIgrfModel.value, normMgmI, 3);
|
||||
|
||||
if ((std::acos(VectorOperations<double>::dot(normSusB, normMgmB)) <
|
||||
acsParameters->onBoardParams.questAngleLimit) or
|
||||
(std::acos(VectorOperations<double>::dot(normSusI, normMgmI)) <
|
||||
acsParameters->onBoardParams.questAngleLimit)) {
|
||||
{
|
||||
PoolReadGuard pg{attitudeEstimationData};
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(attitudeEstimationData->quatQuest.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
attitudeEstimationData->quatQuest.setValid(false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Helper Vectors
|
||||
double normHelperB[3] = {0, 0, 0}, normHelperI[3] = {0, 0, 0}, helperCross[3] = {0, 0, 0},
|
||||
helperSum[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(normSusB, normMgmB, normHelperB);
|
||||
VectorOperations<double>::cross(normSusI, normMgmI, normHelperI);
|
||||
VectorOperations<double>::normalize(normHelperB, normHelperB, 3);
|
||||
VectorOperations<double>::normalize(normHelperI, normHelperI, 3);
|
||||
VectorOperations<double>::cross(normHelperB, normHelperI, helperCross);
|
||||
VectorOperations<double>::add(normHelperB, normHelperI, helperSum, 3);
|
||||
|
||||
// Sensor Weights
|
||||
double kSus = 0, kMgm = 0;
|
||||
kSus = std::pow(acsParameters->kalmanFilterParameters.sensorNoiseSus, -2);
|
||||
kMgm = std::pow(acsParameters->kalmanFilterParameters.sensorNoiseMgm, -2);
|
||||
|
||||
// Weighted Vectors
|
||||
double weightedSusB[3] = {0, 0, 0}, weightedMgmB[3] = {0, 0, 0}, kSusVec[3] = {0, 0, 0},
|
||||
kMgmVec[3] = {0, 0, 0}, kSumVec[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(normSusB, kSus, weightedSusB, 3);
|
||||
VectorOperations<double>::mulScalar(normMgmB, kMgm, weightedMgmB, 3);
|
||||
VectorOperations<double>::cross(weightedSusB, normSusI, kSusVec);
|
||||
VectorOperations<double>::cross(weightedMgmB, normMgmI, kMgmVec);
|
||||
VectorOperations<double>::add(kSusVec, kMgmVec, kSumVec, 3);
|
||||
|
||||
// Some weird Angles
|
||||
double alpha = (1 + VectorOperations<double>::dot(normHelperB, normHelperI)) *
|
||||
(VectorOperations<double>::dot(weightedSusB, normSusI) +
|
||||
VectorOperations<double>::dot(weightedMgmB, normMgmI)) +
|
||||
VectorOperations<double>::dot(helperCross, kSumVec);
|
||||
double beta = VectorOperations<double>::dot(helperSum, kSumVec);
|
||||
double gamma = std::sqrt(std::pow(alpha, 2) + std::pow(beta, 2));
|
||||
|
||||
// I don't even know what this is supposed to be
|
||||
double constPlus =
|
||||
1. / (2 * std::sqrt(gamma * (gamma + alpha) *
|
||||
(1 + VectorOperations<double>::dot(normHelperB, normHelperI))));
|
||||
double constMinus =
|
||||
1. / (2 * std::sqrt(gamma * (gamma - alpha) *
|
||||
(1 + VectorOperations<double>::dot(normHelperB, normHelperI))));
|
||||
|
||||
// Calculate Quaternion
|
||||
double qBI[4] = {0, 0, 0, 0}, qRotVecTot[3] = {0, 0, 0}, qRotVecPt0[3] = {0, 0, 0},
|
||||
qRotVecPt1[3] = {0, 0, 0};
|
||||
if (alpha >= 0) {
|
||||
// Scalar Part
|
||||
qBI[3] = (gamma + alpha) * (1 + VectorOperations<double>::dot(normHelperB, normHelperI));
|
||||
// Rotational Vector Part
|
||||
VectorOperations<double>::mulScalar(helperCross, gamma + alpha, qRotVecPt0, 3);
|
||||
VectorOperations<double>::mulScalar(helperSum, beta, qRotVecPt1, 3);
|
||||
VectorOperations<double>::add(qRotVecPt0, qRotVecPt1, qRotVecTot, 3);
|
||||
std::memcpy(qBI, qRotVecTot, sizeof(qRotVecTot));
|
||||
|
||||
VectorOperations<double>::mulScalar(qBI, constPlus, qBI, 4);
|
||||
QuaternionOperations::normalize(qBI, qBI);
|
||||
} else {
|
||||
// Scalar Part
|
||||
qBI[3] = (beta) * (1 + VectorOperations<double>::dot(normHelperB, normHelperI));
|
||||
// Rotational Vector Part
|
||||
VectorOperations<double>::mulScalar(helperCross, beta, qRotVecPt0, 3);
|
||||
VectorOperations<double>::mulScalar(helperSum, gamma - alpha, qRotVecPt1, 3);
|
||||
VectorOperations<double>::add(qRotVecPt0, qRotVecPt1, qRotVecTot, 3);
|
||||
std::memcpy(qBI, qRotVecTot, sizeof(qRotVecTot));
|
||||
|
||||
VectorOperations<double>::mulScalar(qBI, constMinus, qBI, 4);
|
||||
QuaternionOperations::normalize(qBI, qBI);
|
||||
}
|
||||
// Low Pass
|
||||
if (VectorOperations<double>::norm(qOld, 4) != 0.0) {
|
||||
QuaternionOperations::slerp(qBI, qOld, acsParameters->onBoardParams.questFilterWeight, qBI);
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg{attitudeEstimationData};
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(attitudeEstimationData->quatQuest.value, qBI, 4 * sizeof(double));
|
||||
attitudeEstimationData->quatQuest.setValid(true);
|
||||
}
|
||||
}
|
||||
}
|
31
mission/controller/acs/AttitudeEstimation.h
Normal file
31
mission/controller/acs/AttitudeEstimation.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef MISSION_CONTROLLER_ACS_ATTITUDEESTIMATION_H_
|
||||
#define MISSION_CONTROLLER_ACS_ATTITUDEESTIMATION_H_
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
class AttitudeEstimation {
|
||||
public:
|
||||
AttitudeEstimation(AcsParameters *acsParameters_);
|
||||
virtual ~AttitudeEstimation();
|
||||
;
|
||||
|
||||
void quest(acsctrl::SusDataProcessed *susData, acsctrl::MgmDataProcessed *mgmData,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimation);
|
||||
|
||||
protected:
|
||||
private:
|
||||
AcsParameters *acsParameters;
|
||||
|
||||
double qOld[4] = {0, 0, 0, 0};
|
||||
|
||||
static constexpr double ZERO_VEC4[4] = {0, 0, 0, 0};
|
||||
};
|
||||
|
||||
#endif /* MISSION_CONTROLLER_ACS_ATTITUDEESTIMATION_H_ */
|
@ -2,6 +2,7 @@ target_sources(
|
||||
${LIB_EIVE_MISSION}
|
||||
PRIVATE AcsParameters.cpp
|
||||
ActuatorCmd.cpp
|
||||
AttitudeEstimation.cpp
|
||||
FusedRotationEstimation.cpp
|
||||
Guidance.cpp
|
||||
Igrf13Model.cpp
|
||||
|
@ -4,19 +4,214 @@ FusedRotationEstimation::FusedRotationEstimation(AcsParameters *acsParameters_)
|
||||
acsParameters = acsParameters_;
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
void FusedRotationEstimation::estimateFusedRotationRate(
|
||||
const Mode_t mode, acsctrl::SusDataProcessed *susDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed, acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
ACS::SensorValues *sensorValues, acsctrl::AttitudeEstimationData *attitudeEstimationData,
|
||||
const double timeDelta, acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData,
|
||||
acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||
estimateFusedRotationRateStr(sensorValues, timeDelta, fusedRotRateSourcesData);
|
||||
estimateFusedRotationRateQuest(attitudeEstimationData, timeDelta, fusedRotRateSourcesData);
|
||||
estimateFusedRotationRateSusMgm(susDataProcessed, mgmDataProcessed, gyrDataProcessed,
|
||||
fusedRotRateSourcesData);
|
||||
|
||||
if (not(mode == acs::AcsMode::SAFE) and (fusedRotRateSourcesData->rotRateTotalStr.isValid() and
|
||||
acsParameters->onBoardParams.fusedRateFromStr)) {
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateData->rotRateTotalSource.value,
|
||||
fusedRotRateSourcesData->rotRateTotalStr.value, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotalSource.setValid(true);
|
||||
fusedRotRateData->rotRateSource.value = acs::rotrate::Source::STR;
|
||||
fusedRotRateData->rotRateSource.setValid(true);
|
||||
}
|
||||
} else if (not(mode == acs::AcsMode::SAFE) and
|
||||
(fusedRotRateSourcesData->rotRateTotalQuest.isValid() and
|
||||
acsParameters->onBoardParams.fusedRateFromQuest)) {
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateData->rotRateTotalSource.value,
|
||||
fusedRotRateSourcesData->rotRateTotalQuest.value, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotalSource.setValid(true);
|
||||
fusedRotRateData->rotRateSource.value = acs::rotrate::Source::QUEST;
|
||||
fusedRotRateData->rotRateSource.setValid(true);
|
||||
}
|
||||
} else if (fusedRotRateSourcesData->rotRateTotalSusMgm.isValid()) {
|
||||
std::memcpy(fusedRotRateData->rotRateTotalSource.value,
|
||||
fusedRotRateSourcesData->rotRateTotalSusMgm.value, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotalSource.setValid(true);
|
||||
fusedRotRateData->rotRateSource.value = acs::rotrate::Source::SUSMGM;
|
||||
fusedRotRateData->rotRateSource.setValid(true);
|
||||
} else {
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateData->rotRateTotalSource.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotalSource.setValid(false);
|
||||
fusedRotRateData->rotRateSource.value = acs::rotrate::Source::NONE;
|
||||
fusedRotRateData->rotRateSource.setValid(true);
|
||||
}
|
||||
}
|
||||
if (fusedRotRateSourcesData->rotRateTotalSusMgm.isValid()) {
|
||||
std::memcpy(fusedRotRateData->rotRateTotalSusMgm.value,
|
||||
fusedRotRateSourcesData->rotRateTotalSusMgm.value, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotalSusMgm.setValid(true);
|
||||
} else {
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateData->rotRateTotalSusMgm.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotalSusMgm.setValid(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateStr(
|
||||
ACS::SensorValues *sensorValues, const double timeDelta,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData) {
|
||||
if (not(sensorValues->strSet.caliQw.isValid() and sensorValues->strSet.caliQx.isValid() and
|
||||
sensorValues->strSet.caliQy.isValid() and sensorValues->strSet.caliQz.isValid())) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalStr.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalStr.setValid(false);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldStr, ZERO_VEC4, sizeof(quatOldStr));
|
||||
return;
|
||||
}
|
||||
|
||||
double quatNew[4] = {sensorValues->strSet.caliQx.value, sensorValues->strSet.caliQy.value,
|
||||
sensorValues->strSet.caliQz.value, sensorValues->strSet.caliQw.value};
|
||||
if (VectorOperations<double>::norm(quatOldStr, 4) != 0 and timeDelta != 0) {
|
||||
double quatOldInv[4] = {0, 0, 0, 0};
|
||||
double quatDelta[4] = {0, 0, 0, 0};
|
||||
|
||||
QuaternionOperations::inverse(quatOldStr, quatOldInv);
|
||||
QuaternionOperations::multiply(quatNew, quatOldInv, quatDelta);
|
||||
if (VectorOperations<double>::norm(quatDelta, 4) != 0.0) {
|
||||
QuaternionOperations::normalize(quatDelta);
|
||||
}
|
||||
|
||||
double rotVec[3] = {0, 0, 0};
|
||||
double angle = QuaternionOperations::getAngle(quatDelta);
|
||||
if (VectorOperations<double>::norm(quatDelta, 3) == 0.0) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalStr.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalStr.setValid(true);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldStr, quatNew, sizeof(quatOldStr));
|
||||
return;
|
||||
}
|
||||
VectorOperations<double>::normalize(quatDelta, rotVec, 3);
|
||||
VectorOperations<double>::mulScalar(rotVec, angle / timeDelta, rotVec, 3);
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalStr.value, rotVec, 3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalStr.setValid(true);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldStr, quatNew, sizeof(quatOldStr));
|
||||
return;
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalStr.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalStr.setValid(false);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldStr, quatNew, sizeof(quatOldStr));
|
||||
return;
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateQuest(
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData, const double timeDelta,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData) {
|
||||
if (not attitudeEstimationData->quatQuest.isValid()) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalQuest.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalQuest.setValid(false);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldQuest, ZERO_VEC4, sizeof(quatOldQuest));
|
||||
}
|
||||
|
||||
if (VectorOperations<double>::norm(quatOldQuest, 4) != 0 and timeDelta != 0) {
|
||||
double quatOldInv[4] = {0, 0, 0, 0};
|
||||
double quatDelta[4] = {0, 0, 0, 0};
|
||||
|
||||
QuaternionOperations::inverse(quatOldQuest, quatOldInv);
|
||||
QuaternionOperations::multiply(attitudeEstimationData->quatQuest.value, quatOldInv, quatDelta);
|
||||
if (VectorOperations<double>::norm(quatDelta, 4) != 0.0) {
|
||||
QuaternionOperations::normalize(quatDelta);
|
||||
}
|
||||
|
||||
double rotVec[3] = {0, 0, 0};
|
||||
double angle = QuaternionOperations::getAngle(quatDelta);
|
||||
if (VectorOperations<double>::norm(quatDelta, 3) == 0.0) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalQuest.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalQuest.setValid(true);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldQuest, attitudeEstimationData->quatQuest.value, sizeof(quatOldQuest));
|
||||
return;
|
||||
}
|
||||
VectorOperations<double>::normalize(quatDelta, rotVec, 3);
|
||||
VectorOperations<double>::mulScalar(rotVec, angle / timeDelta, rotVec, 3);
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalQuest.value, rotVec, 3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalQuest.setValid(true);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldQuest, attitudeEstimationData->quatQuest.value, sizeof(quatOldQuest));
|
||||
return;
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalQuest.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalQuest.setValid(false);
|
||||
}
|
||||
}
|
||||
std::memcpy(quatOldQuest, attitudeEstimationData->quatQuest.value, sizeof(quatOldQuest));
|
||||
return;
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateSusMgm(
|
||||
acsctrl::SusDataProcessed *susDataProcessed, acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData) {
|
||||
if ((not mgmDataProcessed->mgmVecTot.isValid() and not susDataProcessed->susVecTot.isValid() and
|
||||
not fusedRotRateData->rotRateTotal.isValid()) or
|
||||
not fusedRotRateSourcesData->rotRateTotalSusMgm.isValid()) or
|
||||
(not susDataProcessed->susVecTotDerivative.isValid() and
|
||||
not mgmDataProcessed->mgmVecTotDerivative.isValid())) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(false, true);
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateOrthogonalSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateOrthogonalSusMgm.setValid(false);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateParallelSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateParallelSusMgm.setValid(false);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalSusMgm.setValid(false);
|
||||
}
|
||||
}
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
@ -25,7 +220,7 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
return;
|
||||
}
|
||||
if (not susDataProcessed->susVecTot.isValid()) {
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateSourcesData);
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||
@ -49,7 +244,7 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
VectorOperations<double>::mulScalar(susDataProcessed->susVecTot.value, omegaParallel,
|
||||
fusedRotRateParallel, 3);
|
||||
} else {
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateSourcesData);
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||
@ -71,12 +266,18 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
VectorOperations<double>::add(fusedRotRateParallel, fusedRotRateOrthogonal, fusedRotRateTotal);
|
||||
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, fusedRotRateOrthogonal,
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateOrthogonalSusMgm.value, fusedRotRateOrthogonal,
|
||||
3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, fusedRotRateParallel, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(true, true);
|
||||
fusedRotRateSourcesData->rotRateOrthogonalSusMgm.setValid(true);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateParallelSusMgm.value, fusedRotRateParallel,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateParallelSusMgm.setValid(true);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalSusMgm.value, fusedRotRateTotal,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalSusMgm.setValid(true);
|
||||
}
|
||||
}
|
||||
|
||||
// store for calculation of angular acceleration
|
||||
@ -86,31 +287,44 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateEclipse(
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData) {
|
||||
if (not acsParameters->onBoardParams.fusedRateSafeDuringEclipse or
|
||||
not gyrDataProcessed->gyrVecTot.isValid() or
|
||||
VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) {
|
||||
VectorOperations<double>::norm(fusedRotRateSourcesData->rotRateTotalSusMgm.value, 3) == 0) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(false, true);
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateOrthogonalSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateOrthogonalSusMgm.setValid(false);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateParallelSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateParallelSusMgm.setValid(false);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalSusMgm.setValid(false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
double angAccelB[3] = {0, 0, 0};
|
||||
VectorOperations<double>::subtract(gyrDataProcessed->gyrVecTot.value, rotRateOldB, angAccelB, 3);
|
||||
double fusedRotRateTotal[3] = {0, 0, 0};
|
||||
VectorOperations<double>::add(fusedRotRateData->rotRateTotal.value, angAccelB, fusedRotRateTotal,
|
||||
3);
|
||||
VectorOperations<double>::add(fusedRotRateSourcesData->rotRateTotalSusMgm.value, angAccelB,
|
||||
fusedRotRateTotal, 3);
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateOrthogonal.setValid(false);
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateParallel.setValid(false);
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotal.setValid(true);
|
||||
PoolReadGuard pg(fusedRotRateSourcesData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateOrthogonalSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateOrthogonalSusMgm.setValid(false);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateParallelSusMgm.value, ZERO_VEC3,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateParallelSusMgm.setValid(false);
|
||||
std::memcpy(fusedRotRateSourcesData->rotRateTotalSusMgm.value, fusedRotRateTotal,
|
||||
3 * sizeof(double));
|
||||
fusedRotRateSourcesData->rotRateTotalSusMgm.setValid(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,28 +2,46 @@
|
||||
#define MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
class FusedRotationEstimation {
|
||||
public:
|
||||
FusedRotationEstimation(AcsParameters *acsParameters_);
|
||||
|
||||
void estimateFusedRotationRateSafe(acsctrl::SusDataProcessed *susDataProcessed,
|
||||
void estimateFusedRotationRate(const Mode_t mode, acsctrl::SusDataProcessed *susDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
ACS::SensorValues *sensorValues,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData,
|
||||
const double timeDelta,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData,
|
||||
acsctrl::FusedRotRateData *fusedRotRateData);
|
||||
|
||||
protected:
|
||||
private:
|
||||
static constexpr double ZERO_VEC[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC3[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC4[4] = {0, 0, 0, 0};
|
||||
|
||||
AcsParameters *acsParameters;
|
||||
double quatOldQuest[4] = {0, 0, 0, 0};
|
||||
double quatOldStr[4] = {0, 0, 0, 0};
|
||||
double rotRateOldB[3] = {0, 0, 0};
|
||||
|
||||
void estimateFusedRotationRateSusMgm(acsctrl::SusDataProcessed *susDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData);
|
||||
void estimateFusedRotationRateEclipse(acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::FusedRotRateData *fusedRotRateData);
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData);
|
||||
void estimateFusedRotationRateQuest(acsctrl::AttitudeEstimationData *attitudeEstimationData,
|
||||
const double timeDelta,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData);
|
||||
void estimateFusedRotationRateStr(ACS::SensorValues *sensorValues, const double timeDelta,
|
||||
acsctrl::FusedRotRateSourcesData *fusedRotRateSourcesData);
|
||||
};
|
||||
|
||||
#endif /* MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_ */
|
||||
|
@ -1,422 +1,312 @@
|
||||
#include "Guidance.h"
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "string.h"
|
||||
#include "util/CholeskyDecomposition.h"
|
||||
#include "util/MathOperations.h"
|
||||
|
||||
Guidance::Guidance(AcsParameters *acsParameters_) { acsParameters = acsParameters_; }
|
||||
|
||||
Guidance::~Guidance() {}
|
||||
|
||||
void Guidance::targetQuatPtgSingleAxis(timeval now, double posSatE[3], double velSatE[3],
|
||||
double sunDirI[3], double refDirB[3], double quatBI[4],
|
||||
void Guidance::targetQuatPtgIdle(timeval timeAbsolute, const double timeDelta,
|
||||
const double sunDirI[3], const double posSatF[4],
|
||||
double targetQuat[4], double targetSatRotRate[3]) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of target quaternion to groundstation or given latitude, longitude and altitude
|
||||
//-------------------------------------------------------------------------------------
|
||||
// transform longitude, latitude and altitude to ECEF
|
||||
double targetE[3] = {0, 0, 0};
|
||||
// positive z-Axis of EIVE in direction of sun
|
||||
double zAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(sunDirI, zAxisIX, 3);
|
||||
|
||||
MathOperations<double>::cartesianFromLatLongAlt(
|
||||
acsParameters->targetModeControllerParameters.latitudeTgt,
|
||||
acsParameters->targetModeControllerParameters.longitudeTgt,
|
||||
acsParameters->targetModeControllerParameters.altitudeTgt, targetE);
|
||||
// determine helper vector to point x-Axis and therefore the STR away from Earth
|
||||
double helperXI[3] = {0, 0, 0}, posSatI[3] = {0, 0, 0};
|
||||
CoordinateTransformations::positionEcfToEci(posSatF, posSatI, &timeAbsolute);
|
||||
VectorOperations<double>::normalize(posSatI, helperXI, 3);
|
||||
|
||||
// target direction in the ECEF frame
|
||||
double targetDirE[3] = {0, 0, 0};
|
||||
VectorOperations<double>::subtract(targetE, posSatE, targetDirE, 3);
|
||||
// construct y-axis from helper vector and z-axis
|
||||
double yAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(zAxisIX, helperXI, yAxisIX);
|
||||
VectorOperations<double>::normalize(yAxisIX, yAxisIX, 3);
|
||||
|
||||
// transformation between ECEF and ECI frame
|
||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::ecfToEciWithNutPre(now, *dcmEI, *dcmEIDot);
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
||||
// x-axis completes RHS
|
||||
double xAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(yAxisIX, zAxisIX, xAxisIX);
|
||||
VectorOperations<double>::normalize(xAxisIX, xAxisIX, 3);
|
||||
|
||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
||||
// join transformation matrix
|
||||
double dcmIX[3][3] = {{xAxisIX[0], yAxisIX[0], zAxisIX[0]},
|
||||
{xAxisIX[1], yAxisIX[1], zAxisIX[1]},
|
||||
{xAxisIX[2], yAxisIX[2], zAxisIX[2]}};
|
||||
QuaternionOperations::fromDcm(dcmIX, targetQuat);
|
||||
|
||||
// transformation between ECEF and Body frame
|
||||
double dcmBI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmBE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
|
||||
QuaternionOperations::toDcm(quatBI, dcmBI);
|
||||
MatrixOperations<double>::multiply(*dcmBI, *dcmIE, *dcmBE, 3, 3, 3);
|
||||
|
||||
// target Direction in the body frame
|
||||
double targetDirB[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmBE, targetDirE, targetDirB, 3, 3, 1);
|
||||
|
||||
// rotation quaternion from two vectors
|
||||
double refDir[3] = {0, 0, 0};
|
||||
refDir[0] = acsParameters->targetModeControllerParameters.refDirection[0];
|
||||
refDir[1] = acsParameters->targetModeControllerParameters.refDirection[1];
|
||||
refDir[2] = acsParameters->targetModeControllerParameters.refDirection[2];
|
||||
double noramlizedTargetDirB[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(targetDirB, noramlizedTargetDirB, 3);
|
||||
VectorOperations<double>::normalize(refDir, refDir, 3);
|
||||
double normTargetDirB = VectorOperations<double>::norm(noramlizedTargetDirB, 3);
|
||||
double normRefDir = VectorOperations<double>::norm(refDir, 3);
|
||||
double crossDir[3] = {0, 0, 0};
|
||||
double dotDirections = VectorOperations<double>::dot(noramlizedTargetDirB, refDir);
|
||||
VectorOperations<double>::cross(noramlizedTargetDirB, refDir, crossDir);
|
||||
targetQuat[0] = crossDir[0];
|
||||
targetQuat[1] = crossDir[1];
|
||||
targetQuat[2] = crossDir[2];
|
||||
targetQuat[3] = sqrt(pow(normTargetDirB, 2) * pow(normRefDir, 2) + dotDirections);
|
||||
VectorOperations<double>::normalize(targetQuat, targetQuat, 4);
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// calculation of reference rotation rate
|
||||
//-------------------------------------------------------------------------------------
|
||||
double velSatB[3] = {0, 0, 0}, velSatBPart1[3] = {0, 0, 0}, velSatBPart2[3] = {0, 0, 0};
|
||||
// velocity: v_B = dcm_BI * dcmIE * v_E + dcm_BI * DotDcm_IE * v_E
|
||||
MatrixOperations<double>::multiply(*dcmBE, velSatE, velSatBPart1, 3, 3, 1);
|
||||
double dcmBEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MatrixOperations<double>::multiply(*dcmBI, *dcmIEDot, *dcmBEDot, 3, 3, 3);
|
||||
MatrixOperations<double>::multiply(*dcmBEDot, posSatE, velSatBPart2, 3, 3, 1);
|
||||
VectorOperations<double>::add(velSatBPart1, velSatBPart2, velSatB, 3);
|
||||
|
||||
double normVelSatB = VectorOperations<double>::norm(velSatB, 3);
|
||||
double normRefSatRate = normVelSatB / normTargetDirB;
|
||||
|
||||
double satRateDir[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(velSatB, targetDirB, satRateDir);
|
||||
VectorOperations<double>::normalize(satRateDir, satRateDir, 3);
|
||||
VectorOperations<double>::mulScalar(satRateDir, normRefSatRate, targetSatRotRate, 3);
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of reference rotation rate in case of star tracker blinding
|
||||
//-------------------------------------------------------------------------------------
|
||||
if (acsParameters->targetModeControllerParameters.avoidBlindStr) {
|
||||
double sunDirB[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmBI, sunDirI, sunDirB, 3, 3, 1);
|
||||
|
||||
double exclAngle = acsParameters->strParameters.exclusionAngle,
|
||||
blindStart = acsParameters->targetModeControllerParameters.blindAvoidStart,
|
||||
blindEnd = acsParameters->targetModeControllerParameters.blindAvoidStop;
|
||||
double sightAngleSun =
|
||||
VectorOperations<double>::dot(acsParameters->strParameters.boresightAxis, sunDirB);
|
||||
|
||||
if (!(strBlindAvoidFlag)) {
|
||||
double critSightAngle = blindStart * exclAngle;
|
||||
if (sightAngleSun < critSightAngle) {
|
||||
strBlindAvoidFlag = true;
|
||||
}
|
||||
} else {
|
||||
if (sightAngleSun < blindEnd * exclAngle) {
|
||||
double normBlindRefRate = acsParameters->targetModeControllerParameters.blindRotRate;
|
||||
double blindRefRate[3] = {0, 0, 0};
|
||||
if (sunDirB[1] < 0) {
|
||||
blindRefRate[0] = normBlindRefRate;
|
||||
blindRefRate[1] = 0;
|
||||
blindRefRate[2] = 0;
|
||||
} else {
|
||||
blindRefRate[0] = -normBlindRefRate;
|
||||
blindRefRate[1] = 0;
|
||||
blindRefRate[2] = 0;
|
||||
}
|
||||
VectorOperations<double>::add(blindRefRate, targetSatRotRate, targetSatRotRate, 3);
|
||||
} else {
|
||||
strBlindAvoidFlag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// revert calculated quaternion from qBX to qIX
|
||||
double quatIB[4] = {0, 0, 0, 1};
|
||||
QuaternionOperations::inverse(quatBI, quatIB);
|
||||
QuaternionOperations::multiply(quatIB, targetQuat, targetQuat);
|
||||
// calculate of reference rotation rate
|
||||
targetRotationRate(timeDelta, targetQuat, targetSatRotRate);
|
||||
}
|
||||
|
||||
void Guidance::targetQuatPtgThreeAxes(timeval now, double posSatE[3], double velSatE[3],
|
||||
void Guidance::targetQuatPtgTarget(timeval timeAbsolute, const double timeDelta,
|
||||
const double posSatF[3], const double velSatF[3],
|
||||
double targetQuat[4], double targetSatRotRate[3]) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of target quaternion for target pointing
|
||||
//-------------------------------------------------------------------------------------
|
||||
// transform longitude, latitude and altitude to cartesian coordiantes (ECEF)
|
||||
double targetE[3] = {0, 0, 0};
|
||||
MathOperations<double>::cartesianFromLatLongAlt(
|
||||
double targetF[3] = {0, 0, 0};
|
||||
CoordinateTransformations::cartesianFromLatLongAlt(
|
||||
acsParameters->targetModeControllerParameters.latitudeTgt,
|
||||
acsParameters->targetModeControllerParameters.longitudeTgt,
|
||||
acsParameters->targetModeControllerParameters.altitudeTgt, targetE);
|
||||
double targetDirE[3] = {0, 0, 0};
|
||||
VectorOperations<double>::subtract(targetE, posSatE, targetDirE, 3);
|
||||
|
||||
// transformation between ECEF and ECI frame
|
||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::ecfToEciWithNutPre(now, *dcmEI, *dcmEIDot);
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
||||
|
||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
||||
acsParameters->targetModeControllerParameters.altitudeTgt, targetF);
|
||||
|
||||
// target direction in the ECI frame
|
||||
double posSatI[3] = {0, 0, 0}, targetI[3] = {0, 0, 0}, targetDirI[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmIE, posSatE, posSatI, 3, 3, 1);
|
||||
MatrixOperations<double>::multiply(*dcmIE, targetE, targetI, 3, 3, 1);
|
||||
CoordinateTransformations::positionEcfToEci(posSatF, posSatI, &timeAbsolute);
|
||||
CoordinateTransformations::positionEcfToEci(targetF, targetI, &timeAbsolute);
|
||||
VectorOperations<double>::subtract(targetI, posSatI, targetDirI, 3);
|
||||
|
||||
// x-axis aligned with target direction
|
||||
// this aligns with the camera, E- and S-band antennas
|
||||
double xAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(targetDirI, xAxis, 3);
|
||||
double xAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(targetDirI, xAxisIX, 3);
|
||||
VectorOperations<double>::mulScalar(xAxisIX, -1, xAxisIX, 3);
|
||||
|
||||
// transform velocity into inertial frame
|
||||
double velocityI[3] = {0, 0, 0}, velPart1[3] = {0, 0, 0}, velPart2[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmIE, velSatE, velPart1, 3, 3, 1);
|
||||
MatrixOperations<double>::multiply(*dcmIEDot, posSatE, velPart2, 3, 3, 1);
|
||||
VectorOperations<double>::add(velPart1, velPart2, velocityI, 3);
|
||||
double velSatI[3] = {0, 0, 0};
|
||||
CoordinateTransformations::velocityEcfToEci(velSatF, posSatF, velSatI, &timeAbsolute);
|
||||
|
||||
// orbital normal vector of target and velocity vector
|
||||
double orbitalNormalI[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(posSatI, velocityI, orbitalNormalI);
|
||||
VectorOperations<double>::cross(posSatI, velSatI, orbitalNormalI);
|
||||
VectorOperations<double>::normalize(orbitalNormalI, orbitalNormalI, 3);
|
||||
|
||||
// y-axis of satellite in orbit plane so that z-axis is parallel to long side of picture
|
||||
// resolution
|
||||
double yAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(orbitalNormalI, xAxis, yAxis);
|
||||
VectorOperations<double>::normalize(yAxis, yAxis, 3);
|
||||
double yAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(orbitalNormalI, xAxisIX, yAxisIX);
|
||||
VectorOperations<double>::normalize(yAxisIX, yAxisIX, 3);
|
||||
|
||||
// z-axis completes RHS
|
||||
double zAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(xAxis, yAxis, zAxis);
|
||||
double zAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(xAxisIX, yAxisIX, zAxisIX);
|
||||
|
||||
// join transformation matrix
|
||||
double dcmIX[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
||||
{xAxis[1], yAxis[1], zAxis[1]},
|
||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
||||
double dcmIX[3][3] = {{xAxisIX[0], yAxisIX[0], zAxisIX[0]},
|
||||
{xAxisIX[1], yAxisIX[1], zAxisIX[1]},
|
||||
{xAxisIX[2], yAxisIX[2], zAxisIX[2]}};
|
||||
QuaternionOperations::fromDcm(dcmIX, targetQuat);
|
||||
|
||||
int8_t timeElapsedMax = acsParameters->targetModeControllerParameters.timeElapsedMax;
|
||||
targetRotationRate(timeElapsedMax, now, targetQuat, targetSatRotRate);
|
||||
targetRotationRate(timeDelta, targetQuat, targetSatRotRate);
|
||||
}
|
||||
|
||||
void Guidance::targetQuatPtgGs(timeval now, double posSatE[3], double sunDirI[3],
|
||||
void Guidance::targetQuatPtgGs(timeval timeAbsolute, const double timeDelta,
|
||||
const double posSatF[3], const double sunDirI[3],
|
||||
double targetQuat[4], double targetSatRotRate[3]) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of target quaternion for ground station pointing
|
||||
//-------------------------------------------------------------------------------------
|
||||
// transform longitude, latitude and altitude to cartesian coordiantes (ECEF)
|
||||
double groundStationE[3] = {0, 0, 0};
|
||||
|
||||
MathOperations<double>::cartesianFromLatLongAlt(
|
||||
double posGroundStationF[3] = {0, 0, 0};
|
||||
CoordinateTransformations::cartesianFromLatLongAlt(
|
||||
acsParameters->gsTargetModeControllerParameters.latitudeTgt,
|
||||
acsParameters->gsTargetModeControllerParameters.longitudeTgt,
|
||||
acsParameters->gsTargetModeControllerParameters.altitudeTgt, groundStationE);
|
||||
double targetDirE[3] = {0, 0, 0};
|
||||
VectorOperations<double>::subtract(groundStationE, posSatE, targetDirE, 3);
|
||||
|
||||
// transformation between ECEF and ECI frame
|
||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::ecfToEciWithNutPre(now, *dcmEI, *dcmEIDot);
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
||||
|
||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
||||
acsParameters->gsTargetModeControllerParameters.altitudeTgt, posGroundStationF);
|
||||
|
||||
// target direction in the ECI frame
|
||||
double posSatI[3] = {0, 0, 0}, groundStationI[3] = {0, 0, 0}, groundStationDirI[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmIE, posSatE, posSatI, 3, 3, 1);
|
||||
MatrixOperations<double>::multiply(*dcmIE, groundStationE, groundStationI, 3, 3, 1);
|
||||
VectorOperations<double>::subtract(groundStationI, posSatI, groundStationDirI, 3);
|
||||
double posSatI[3] = {0, 0, 0}, posGroundStationI[3] = {0, 0, 0}, groundStationDirI[3] = {0, 0, 0};
|
||||
CoordinateTransformations::positionEcfToEci(posSatF, posSatI, &timeAbsolute);
|
||||
CoordinateTransformations::positionEcfToEci(posGroundStationF, posGroundStationI, &timeAbsolute);
|
||||
VectorOperations<double>::subtract(posGroundStationI, posSatI, groundStationDirI, 3);
|
||||
|
||||
// negative x-axis aligned with target direction
|
||||
// this aligns with the camera, E- and S-band antennas
|
||||
double xAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(groundStationDirI, xAxis, 3);
|
||||
VectorOperations<double>::mulScalar(xAxis, -1, xAxis, 3);
|
||||
double xAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(groundStationDirI, xAxisIX, 3);
|
||||
VectorOperations<double>::mulScalar(xAxisIX, -1, xAxisIX, 3);
|
||||
|
||||
// get sun vector model in ECI
|
||||
VectorOperations<double>::normalize(sunDirI, sunDirI, 3);
|
||||
// get earth vector in ECI
|
||||
double earthDirI[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(posSatI, earthDirI, 3);
|
||||
VectorOperations<double>::mulScalar(earthDirI, -1, earthDirI, 3);
|
||||
|
||||
// calculate z-axis as projection of sun vector into plane defined by x-axis as normal vector
|
||||
// z = sPerpenticular = s - sParallel = s - (x*s)/norm(x)^2 * x
|
||||
double xDotS = VectorOperations<double>::dot(xAxis, sunDirI);
|
||||
xDotS /= pow(VectorOperations<double>::norm(xAxis, 3), 2);
|
||||
double sunParallel[3], zAxis[3];
|
||||
VectorOperations<double>::mulScalar(xAxis, xDotS, sunParallel, 3);
|
||||
VectorOperations<double>::subtract(sunDirI, sunParallel, zAxis, 3);
|
||||
VectorOperations<double>::normalize(zAxis, zAxis, 3);
|
||||
// sun avoidance calculations
|
||||
double sunPerpendicularX[3] = {0, 0, 0}, sunFloorYZ[3] = {0, 0, 0}, zAxisSun[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(xAxisIX, VectorOperations<double>::dot(xAxisIX, sunDirI),
|
||||
sunPerpendicularX, 3);
|
||||
VectorOperations<double>::subtract(sunDirI, sunPerpendicularX, sunFloorYZ, 3);
|
||||
VectorOperations<double>::normalize(sunFloorYZ, sunFloorYZ, 3);
|
||||
VectorOperations<double>::mulScalar(sunFloorYZ, -1, zAxisSun, 3);
|
||||
double sunWeight = 0, strVecSun[3] = {0, 0, 0}, strVecSunX[3] = {0, 0, 0},
|
||||
strVecSunZ[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(xAxisIX, acsParameters->strParameters.boresightAxis[0],
|
||||
strVecSunX, 3);
|
||||
VectorOperations<double>::mulScalar(zAxisSun, acsParameters->strParameters.boresightAxis[2],
|
||||
strVecSunZ, 3);
|
||||
VectorOperations<double>::add(strVecSunX, strVecSunZ, strVecSun, 3);
|
||||
VectorOperations<double>::normalize(strVecSun, strVecSun, 3);
|
||||
sunWeight = VectorOperations<double>::dot(strVecSun, sunDirI);
|
||||
|
||||
// y-axis completes RHS
|
||||
double yAxis[3];
|
||||
VectorOperations<double>::cross(zAxis, xAxis, yAxis);
|
||||
VectorOperations<double>::normalize(yAxis, yAxis, 3);
|
||||
// earth avoidance calculations
|
||||
double earthPerpendicularX[3] = {0, 0, 0}, earthFloorYZ[3] = {0, 0, 0}, zAxisEarth[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(xAxisIX, VectorOperations<double>::dot(xAxisIX, earthDirI),
|
||||
earthPerpendicularX, 3);
|
||||
VectorOperations<double>::subtract(earthDirI, earthPerpendicularX, earthFloorYZ, 3);
|
||||
VectorOperations<double>::normalize(earthFloorYZ, earthFloorYZ, 3);
|
||||
VectorOperations<double>::mulScalar(earthFloorYZ, -1, zAxisEarth, 3);
|
||||
double earthWeight = 0, strVecEarth[3] = {0, 0, 0}, strVecEarthX[3] = {0, 0, 0},
|
||||
strVecEarthZ[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(xAxisIX, acsParameters->strParameters.boresightAxis[0],
|
||||
strVecEarthX, 3);
|
||||
VectorOperations<double>::mulScalar(zAxisEarth, acsParameters->strParameters.boresightAxis[2],
|
||||
strVecEarthZ, 3);
|
||||
VectorOperations<double>::add(strVecEarthX, strVecEarthZ, strVecEarth, 3);
|
||||
VectorOperations<double>::normalize(strVecEarth, strVecEarth, 3);
|
||||
earthWeight = VectorOperations<double>::dot(strVecEarth, earthDirI);
|
||||
|
||||
if ((sunWeight == 0.0) and (earthWeight == 0.0)) {
|
||||
// if this actually ever happens i will eat a broom
|
||||
sunWeight = 0.5;
|
||||
earthWeight = 0.5;
|
||||
}
|
||||
|
||||
// normalize weights for convenience
|
||||
double normFactor = 1. / (std::abs(sunWeight) + std::abs(earthWeight));
|
||||
sunWeight *= normFactor;
|
||||
earthWeight *= normFactor;
|
||||
|
||||
// calculate z-axis for str blinding avoidance
|
||||
double zAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(zAxisSun, sunWeight, zAxisSun, 3);
|
||||
VectorOperations<double>::mulScalar(zAxisEarth, earthWeight, zAxisEarth, 3);
|
||||
VectorOperations<double>::add(zAxisSun, zAxisEarth, zAxisIX, 3);
|
||||
VectorOperations<double>::mulScalar(zAxisIX, -1, zAxisIX, 3);
|
||||
VectorOperations<double>::normalize(zAxisIX, zAxisIX, 3);
|
||||
|
||||
// calculate y-axis
|
||||
double yAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(zAxisIX, xAxisIX, yAxisIX);
|
||||
VectorOperations<double>::normalize(yAxisIX, yAxisIX, 3);
|
||||
|
||||
// join transformation matrix
|
||||
double dcmTgt[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
||||
{xAxis[1], yAxis[1], zAxis[1]},
|
||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
||||
QuaternionOperations::fromDcm(dcmTgt, targetQuat);
|
||||
double dcmIX[3][3] = {{xAxisIX[0], yAxisIX[0], zAxisIX[0]},
|
||||
{xAxisIX[1], yAxisIX[1], zAxisIX[1]},
|
||||
{xAxisIX[2], yAxisIX[2], zAxisIX[2]}};
|
||||
QuaternionOperations::fromDcm(dcmIX, targetQuat);
|
||||
|
||||
int8_t timeElapsedMax = acsParameters->gsTargetModeControllerParameters.timeElapsedMax;
|
||||
targetRotationRate(timeElapsedMax, now, targetQuat, targetSatRotRate);
|
||||
limitReferenceRotation(xAxisIX, targetQuat);
|
||||
targetRotationRate(timeDelta, targetQuat, targetSatRotRate);
|
||||
|
||||
std::memcpy(xAxisIXprev, xAxisIX, sizeof(xAxisIXprev));
|
||||
}
|
||||
|
||||
void Guidance::targetQuatPtgSun(timeval now, double sunDirI[3], double targetQuat[4],
|
||||
double targetSatRotRate[3]) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of target quaternion to sun
|
||||
//-------------------------------------------------------------------------------------
|
||||
// positive z-Axis of EIVE in direction of sun
|
||||
double zAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(sunDirI, zAxis, 3);
|
||||
|
||||
// assign helper vector (north pole inertial)
|
||||
double helperVec[3] = {0, 0, 1};
|
||||
|
||||
// construct y-axis from helper vector and z-axis
|
||||
double yAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(zAxis, helperVec, yAxis);
|
||||
VectorOperations<double>::normalize(yAxis, yAxis, 3);
|
||||
|
||||
// x-axis completes RHS
|
||||
double xAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(yAxis, zAxis, xAxis);
|
||||
VectorOperations<double>::normalize(xAxis, xAxis, 3);
|
||||
|
||||
// join transformation matrix
|
||||
double dcmTgt[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
||||
{xAxis[1], yAxis[1], zAxis[1]},
|
||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
||||
QuaternionOperations::fromDcm(dcmTgt, targetQuat);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Calculation of reference rotation rate
|
||||
//----------------------------------------------------------------------------
|
||||
int8_t timeElapsedMax = acsParameters->gsTargetModeControllerParameters.timeElapsedMax;
|
||||
targetRotationRate(timeElapsedMax, now, targetQuat, targetSatRotRate);
|
||||
}
|
||||
|
||||
void Guidance::targetQuatPtgNadirSingleAxis(timeval now, double posSatE[3], double quatBI[4],
|
||||
double targetQuat[4], double refDirB[3],
|
||||
double refSatRate[3]) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of target quaternion for Nadir pointing
|
||||
//-------------------------------------------------------------------------------------
|
||||
double targetDirE[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(posSatE, -1, targetDirE, 3);
|
||||
|
||||
// transformation between ECEF and ECI frame
|
||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::ecfToEciWithNutPre(now, *dcmEI, *dcmEIDot);
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
||||
|
||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
||||
|
||||
// transformation between ECEF and Body frame
|
||||
double dcmBI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmBE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
QuaternionOperations::toDcm(quatBI, dcmBI);
|
||||
MatrixOperations<double>::multiply(*dcmBI, *dcmIE, *dcmBE, 3, 3, 3);
|
||||
|
||||
// target Direction in the body frame
|
||||
double targetDirB[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmBE, targetDirE, targetDirB, 3, 3, 1);
|
||||
|
||||
// rotation quaternion from two vectors
|
||||
double refDir[3] = {0, 0, 0};
|
||||
refDir[0] = acsParameters->nadirModeControllerParameters.refDirection[0];
|
||||
refDir[1] = acsParameters->nadirModeControllerParameters.refDirection[1];
|
||||
refDir[2] = acsParameters->nadirModeControllerParameters.refDirection[2];
|
||||
double noramlizedTargetDirB[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(targetDirB, noramlizedTargetDirB, 3);
|
||||
VectorOperations<double>::normalize(refDir, refDir, 3);
|
||||
double normTargetDirB = VectorOperations<double>::norm(noramlizedTargetDirB, 3);
|
||||
double normRefDir = VectorOperations<double>::norm(refDir, 3);
|
||||
double crossDir[3] = {0, 0, 0};
|
||||
double dotDirections = VectorOperations<double>::dot(noramlizedTargetDirB, refDir);
|
||||
VectorOperations<double>::cross(noramlizedTargetDirB, refDir, crossDir);
|
||||
targetQuat[0] = crossDir[0];
|
||||
targetQuat[1] = crossDir[1];
|
||||
targetQuat[2] = crossDir[2];
|
||||
targetQuat[3] = sqrt(pow(normTargetDirB, 2) * pow(normRefDir, 2) + dotDirections);
|
||||
VectorOperations<double>::normalize(targetQuat, targetQuat, 4);
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of reference rotation rate
|
||||
//-------------------------------------------------------------------------------------
|
||||
refSatRate[0] = 0;
|
||||
refSatRate[1] = 0;
|
||||
refSatRate[2] = 0;
|
||||
|
||||
// revert calculated quaternion from qBX to qIX
|
||||
double quatIB[4] = {0, 0, 0, 1};
|
||||
QuaternionOperations::inverse(quatBI, quatIB);
|
||||
QuaternionOperations::multiply(quatIB, targetQuat, targetQuat);
|
||||
}
|
||||
|
||||
void Guidance::targetQuatPtgNadirThreeAxes(timeval now, double posSatE[3], double velSatE[3],
|
||||
void Guidance::targetQuatPtgNadir(timeval timeAbsolute, const double timeDelta,
|
||||
const double posSatE[3], const double velSatE[3],
|
||||
double targetQuat[4], double refSatRate[3]) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of target quaternion for Nadir pointing
|
||||
//-------------------------------------------------------------------------------------
|
||||
// transformation between ECEF and ECI frame
|
||||
double dcmEI[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmIE[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dcmEIDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::ecfToEciWithNutPre(now, *dcmEI, *dcmEIDot);
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEI, *dcmIE);
|
||||
|
||||
double dcmIEDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::inverseMatrixDimThree(*dcmEIDot, *dcmIEDot);
|
||||
|
||||
// satellite position in inertial reference frame
|
||||
double posSatI[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmIE, posSatE, posSatI, 3, 3, 1);
|
||||
CoordinateTransformations::positionEcfToEci(posSatE, posSatI, &timeAbsolute);
|
||||
|
||||
// negative x-axis aligned with position vector
|
||||
// this aligns with the camera, E- and S-band antennas
|
||||
double xAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(posSatI, xAxis, 3);
|
||||
VectorOperations<double>::mulScalar(xAxis, -1, xAxis, 3);
|
||||
double xAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(posSatI, xAxisIX, 3);
|
||||
VectorOperations<double>::mulScalar(xAxisIX, -1, xAxisIX, 3);
|
||||
|
||||
// make z-Axis parallel to major part of camera resolution
|
||||
double zAxis[3] = {0, 0, 0};
|
||||
double velocityI[3] = {0, 0, 0}, velPart1[3] = {0, 0, 0}, velPart2[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmIE, velSatE, velPart1, 3, 3, 1);
|
||||
MatrixOperations<double>::multiply(*dcmIEDot, posSatE, velPart2, 3, 3, 1);
|
||||
VectorOperations<double>::add(velPart1, velPart2, velocityI, 3);
|
||||
VectorOperations<double>::cross(xAxis, velocityI, zAxis);
|
||||
VectorOperations<double>::normalize(zAxis, zAxis, 3);
|
||||
double zAxisIX[3] = {0, 0, 0};
|
||||
double velSatI[3] = {0, 0, 0};
|
||||
CoordinateTransformations::velocityEcfToEci(velSatE, posSatE, velSatI, &timeAbsolute);
|
||||
VectorOperations<double>::cross(xAxisIX, velSatI, zAxisIX);
|
||||
VectorOperations<double>::normalize(zAxisIX, zAxisIX, 3);
|
||||
|
||||
// y-Axis completes RHS
|
||||
double yAxis[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(zAxis, xAxis, yAxis);
|
||||
double yAxisIX[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(zAxisIX, xAxisIX, yAxisIX);
|
||||
|
||||
// join transformation matrix
|
||||
double dcmTgt[3][3] = {{xAxis[0], yAxis[0], zAxis[0]},
|
||||
{xAxis[1], yAxis[1], zAxis[1]},
|
||||
{xAxis[2], yAxis[2], zAxis[2]}};
|
||||
QuaternionOperations::fromDcm(dcmTgt, targetQuat);
|
||||
double dcmIX[3][3] = {{xAxisIX[0], yAxisIX[0], zAxisIX[0]},
|
||||
{xAxisIX[1], yAxisIX[1], zAxisIX[1]},
|
||||
{xAxisIX[2], yAxisIX[2], zAxisIX[2]}};
|
||||
QuaternionOperations::fromDcm(dcmIX, targetQuat);
|
||||
|
||||
int8_t timeElapsedMax = acsParameters->nadirModeControllerParameters.timeElapsedMax;
|
||||
targetRotationRate(timeElapsedMax, now, targetQuat, refSatRate);
|
||||
targetRotationRate(timeDelta, targetQuat, refSatRate);
|
||||
}
|
||||
|
||||
void Guidance::targetRotationRate(const double timeDelta, double quatIX[4], double *refSatRate) {
|
||||
if (VectorOperations<double>::norm(quatIXprev, 4) == 0) {
|
||||
std::memcpy(quatIXprev, quatIX, sizeof(quatIXprev));
|
||||
}
|
||||
if (timeDelta != 0.0) {
|
||||
QuaternionOperations::rotationFromQuaternions(quatIX, quatIXprev, timeDelta, refSatRate);
|
||||
VectorOperations<double>::mulScalar(refSatRate, -1, refSatRate, 3);
|
||||
} else {
|
||||
std::memcpy(refSatRate, ZERO_VEC3, 3 * sizeof(double));
|
||||
}
|
||||
std::memcpy(quatIXprev, quatIX, sizeof(quatIXprev));
|
||||
}
|
||||
|
||||
void Guidance::limitReferenceRotation(const double xAxisIX[3], double quatIX[4]) {
|
||||
if ((VectorOperations<double>::norm(quatIXprev, 4) == 0) or
|
||||
(VectorOperations<double>::norm(xAxisIXprev, 3) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QuaternionOperations::preventSignJump(quatIX, quatIXprev);
|
||||
|
||||
// check required rotation and return if below limit
|
||||
double quatXprevX[4] = {0, 0, 0, 0}, quatXprevI[4] = {0, 0, 0, 0};
|
||||
QuaternionOperations::inverse(quatIXprev, quatXprevI);
|
||||
QuaternionOperations::multiply(quatIX, quatXprevI, quatXprevX);
|
||||
QuaternionOperations::normalize(quatXprevX);
|
||||
double phiMax = acsParameters->gsTargetModeControllerParameters.rotRateLimit *
|
||||
acsParameters->onBoardParams.sampleTime;
|
||||
if (2 * std::acos(quatXprevX[3]) < phiMax) {
|
||||
return;
|
||||
}
|
||||
|
||||
// x-axis always needs full rotation
|
||||
double phiX = 0, phiXvec[3] = {0, 0, 0};
|
||||
phiX = std::acos(VectorOperations<double>::dot(xAxisIXprev, xAxisIX));
|
||||
VectorOperations<double>::cross(xAxisIXprev, xAxisIX, phiXvec);
|
||||
VectorOperations<double>::normalize(phiXvec, phiXvec, 3);
|
||||
|
||||
double quatXprevXtilde[4] = {0, 0, 0, 0}, quatIXtilde[4] = {0, 0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(phiXvec, -std::sin(phiX / 2.), phiXvec, 3);
|
||||
std::memcpy(quatXprevXtilde, phiXvec, sizeof(phiXvec));
|
||||
quatXprevXtilde[3] = cos(phiX / 2.);
|
||||
QuaternionOperations::normalize(quatXprevXtilde);
|
||||
QuaternionOperations::multiply(quatXprevXtilde, quatIXprev, quatIXtilde);
|
||||
|
||||
// use the residual rotation up to the maximum
|
||||
double quatXXtilde[4] = {0, 0, 0, 0}, quatXI[4] = {0, 0, 0, 0};
|
||||
QuaternionOperations::inverse(quatIX, quatXI);
|
||||
QuaternionOperations::multiply(quatIXtilde, quatXI, quatXXtilde);
|
||||
|
||||
double phiResidual = 0, phiResidualVec[3] = {0, 0, 0};
|
||||
if ((phiX * phiX) > (phiMax * phiMax)) {
|
||||
phiResidual = 0;
|
||||
} else {
|
||||
phiResidual = std::sqrt((phiMax * phiMax) - (phiX * phiX));
|
||||
}
|
||||
std::memcpy(phiResidualVec, quatXXtilde, sizeof(phiResidualVec));
|
||||
VectorOperations<double>::normalize(phiResidualVec, phiResidualVec, 3);
|
||||
|
||||
double quatXhatXTilde[4] = {0, 0, 0, 0}, quatXTildeXhat[4] = {0, 0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(phiResidualVec, std::sin(phiResidual / 2.), phiResidualVec,
|
||||
3);
|
||||
std::memcpy(quatXhatXTilde, phiResidualVec, sizeof(phiResidualVec));
|
||||
quatXhatXTilde[3] = std::cos(phiResidual / 2.);
|
||||
QuaternionOperations::normalize(quatXhatXTilde);
|
||||
|
||||
// calculate final quaternion
|
||||
QuaternionOperations::inverse(quatXhatXTilde, quatXTildeXhat);
|
||||
QuaternionOperations::multiply(quatXTildeXhat, quatIXtilde, quatIX);
|
||||
QuaternionOperations::normalize(quatIX);
|
||||
}
|
||||
|
||||
void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
||||
double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3],
|
||||
double errorQuat[4], double errorSatRotRate[3], double &errorAngle) {
|
||||
// First calculate error quaternion between current and target orientation
|
||||
QuaternionOperations::multiply(currentQuat, targetQuat, errorQuat);
|
||||
// Last calculate add rotation from reference quaternion
|
||||
QuaternionOperations::multiply(refQuat, errorQuat, errorQuat);
|
||||
// First calculate error quaternion between current and target orientation without reference
|
||||
// quaternion
|
||||
double errorQuatWoRef[4] = {0, 0, 0, 0};
|
||||
QuaternionOperations::multiply(currentQuat, targetQuat, errorQuatWoRef);
|
||||
// Then add rotation from reference quaternion
|
||||
QuaternionOperations::multiply(refQuat, errorQuatWoRef, errorQuat);
|
||||
// Keep scalar part of quaternion positive
|
||||
if (errorQuat[3] < 0) {
|
||||
VectorOperations<double>::mulScalar(errorQuat, -1, errorQuat, 4);
|
||||
@ -425,7 +315,11 @@ void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], do
|
||||
errorAngle = QuaternionOperations::getAngle(errorQuat, true);
|
||||
|
||||
// Calculate error satellite rotational rate
|
||||
// First combine the target and reference satellite rotational rates
|
||||
// Convert target rotational rate into body RF
|
||||
double targetSatRotRateB[3] = {0, 0, 0};
|
||||
QuaternionOperations::multiplyVector(currentQuat, targetSatRotRate, targetSatRotRateB);
|
||||
VectorOperations<double>::copy(targetSatRotRateB, targetSatRotRate, 3);
|
||||
// Combine the target and reference satellite rotational rates
|
||||
double combinedRefSatRotRate[3] = {0, 0, 0};
|
||||
VectorOperations<double>::add(targetSatRotRate, refSatRotRate, combinedRefSatRotRate, 3);
|
||||
// Then subtract the combined required satellite rotational rates from the actual rate
|
||||
@ -435,91 +329,48 @@ void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], do
|
||||
void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
||||
double targetSatRotRate[3], double errorQuat[4],
|
||||
double errorSatRotRate[3], double &errorAngle) {
|
||||
// First calculate error quaternion between current and target orientation
|
||||
QuaternionOperations::multiply(currentQuat, targetQuat, errorQuat);
|
||||
// Keep scalar part of quaternion positive
|
||||
if (errorQuat[3] < 0) {
|
||||
VectorOperations<double>::mulScalar(errorQuat, -1, errorQuat, 4);
|
||||
}
|
||||
// Calculate error angle
|
||||
errorAngle = QuaternionOperations::getAngle(errorQuat, true);
|
||||
|
||||
// Calculate error satellite rotational rate
|
||||
VectorOperations<double>::subtract(currentSatRotRate, targetSatRotRate, errorSatRotRate, 3);
|
||||
}
|
||||
|
||||
void Guidance::targetRotationRate(int8_t timeElapsedMax, timeval now, double quatInertialTarget[4],
|
||||
double *refSatRate) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of target rotation rate
|
||||
//-------------------------------------------------------------------------------------
|
||||
double timeElapsed = now.tv_sec + now.tv_usec * 1e-6 -
|
||||
(timeSavedQuaternion.tv_sec + timeSavedQuaternion.tv_usec * 1e-6);
|
||||
if (VectorOperations<double>::norm(savedQuaternion, 4) == 0) {
|
||||
std::memcpy(savedQuaternion, quatInertialTarget, sizeof(savedQuaternion));
|
||||
}
|
||||
if (timeElapsed < timeElapsedMax) {
|
||||
double q[4] = {0, 0, 0, 0}, qS[4] = {0, 0, 0, 0};
|
||||
QuaternionOperations::inverse(quatInertialTarget, q);
|
||||
QuaternionOperations::inverse(savedQuaternion, qS);
|
||||
double qDiff[4] = {0, 0, 0, 0};
|
||||
VectorOperations<double>::subtract(q, qS, qDiff, 4);
|
||||
VectorOperations<double>::mulScalar(qDiff, 1 / timeElapsed, qDiff, 4);
|
||||
|
||||
double tgtQuatVec[3] = {q[0], q[1], q[2]};
|
||||
double qDiffVec[3] = {qDiff[0], qDiff[1], qDiff[2]};
|
||||
double sum1[3] = {0, 0, 0}, sum2[3] = {0, 0, 0}, sum3[3] = {0, 0, 0}, sum[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(tgtQuatVec, qDiffVec, sum1);
|
||||
VectorOperations<double>::mulScalar(tgtQuatVec, qDiff[3], sum2, 3);
|
||||
VectorOperations<double>::mulScalar(qDiffVec, q[3], sum3, 3);
|
||||
VectorOperations<double>::add(sum1, sum2, sum, 3);
|
||||
VectorOperations<double>::subtract(sum, sum3, sum, 3);
|
||||
double omegaRefNew[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(sum, -2, omegaRefNew, 3);
|
||||
|
||||
VectorOperations<double>::mulScalar(omegaRefNew, 2, refSatRate, 3);
|
||||
VectorOperations<double>::subtract(refSatRate, omegaRefSaved, refSatRate, 3);
|
||||
omegaRefSaved[0] = omegaRefNew[0];
|
||||
omegaRefSaved[1] = omegaRefNew[1];
|
||||
omegaRefSaved[2] = omegaRefNew[2];
|
||||
} else {
|
||||
refSatRate[0] = 0;
|
||||
refSatRate[1] = 0;
|
||||
refSatRate[2] = 0;
|
||||
}
|
||||
|
||||
timeSavedQuaternion = now;
|
||||
savedQuaternion[0] = quatInertialTarget[0];
|
||||
savedQuaternion[1] = quatInertialTarget[1];
|
||||
savedQuaternion[2] = quatInertialTarget[2];
|
||||
savedQuaternion[3] = quatInertialTarget[3];
|
||||
double refQuat[4] = {0, 0, 0, 1}, refSatRotRate[3] = {0, 0, 0};
|
||||
comparePtg(currentQuat, currentSatRotRate, targetQuat, targetSatRotRate, refQuat, refSatRotRate,
|
||||
errorQuat, errorSatRotRate, errorAngle);
|
||||
}
|
||||
|
||||
ReturnValue_t Guidance::getDistributionMatrixRw(ACS::SensorValues *sensorValues,
|
||||
double *rwPseudoInv) {
|
||||
bool rw1valid = (sensorValues->rw1Set.state.value && sensorValues->rw1Set.state.isValid());
|
||||
bool rw2valid = (sensorValues->rw2Set.state.value && sensorValues->rw2Set.state.isValid());
|
||||
bool rw3valid = (sensorValues->rw3Set.state.value && sensorValues->rw3Set.state.isValid());
|
||||
bool rw4valid = (sensorValues->rw4Set.state.value && sensorValues->rw4Set.state.isValid());
|
||||
double *rwPseudoInv, acsctrl::RwAvail *rwAvail) {
|
||||
rwAvail->rw1avail = (sensorValues->rw1Set.state.value and sensorValues->rw1Set.state.isValid());
|
||||
rwAvail->rw2avail = (sensorValues->rw2Set.state.value and sensorValues->rw2Set.state.isValid());
|
||||
rwAvail->rw3avail = (sensorValues->rw3Set.state.value and sensorValues->rw3Set.state.isValid());
|
||||
rwAvail->rw4avail = (sensorValues->rw4Set.state.value and sensorValues->rw4Set.state.isValid());
|
||||
|
||||
if (rw1valid && rw2valid && rw3valid && rw4valid) {
|
||||
if (rwAvail->rw1avail and rwAvail->rw2avail and rwAvail->rw3avail and rwAvail->rw4avail) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.pseudoInverse, 12 * sizeof(double));
|
||||
return returnvalue::OK;
|
||||
} else if (!rw1valid && rw2valid && rw3valid && rw4valid) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.without1, 12 * sizeof(double));
|
||||
return returnvalue::OK;
|
||||
} else if (rw1valid && !rw2valid && rw3valid && rw4valid) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.without2, 12 * sizeof(double));
|
||||
return returnvalue::OK;
|
||||
} else if (rw1valid && rw2valid && !rw3valid && rw4valid) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.without3, 12 * sizeof(double));
|
||||
return returnvalue::OK;
|
||||
} else if (rw1valid && rw2valid && rw3valid && !rw4valid) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.without4, 12 * sizeof(double));
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
return returnvalue::FAILED;
|
||||
} else if (not rwAvail->rw1avail and rwAvail->rw2avail and rwAvail->rw3avail and
|
||||
rwAvail->rw4avail) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.pseudoInverseWithoutRW1,
|
||||
12 * sizeof(double));
|
||||
return acsctrl::SINGLE_RW_UNAVAILABLE;
|
||||
} else if (rwAvail->rw1avail and not rwAvail->rw2avail and rwAvail->rw3avail and
|
||||
rwAvail->rw4avail) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.pseudoInverseWithoutRW2,
|
||||
12 * sizeof(double));
|
||||
return acsctrl::SINGLE_RW_UNAVAILABLE;
|
||||
} else if (rwAvail->rw1avail and rwAvail->rw2avail and not rwAvail->rw3avail and
|
||||
rwAvail->rw4avail) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.pseudoInverseWithoutRW3,
|
||||
12 * sizeof(double));
|
||||
return acsctrl::SINGLE_RW_UNAVAILABLE;
|
||||
} else if (rwAvail->rw1avail and rwAvail->rw2avail and rwAvail->rw3avail and
|
||||
not rwAvail->rw4avail) {
|
||||
std::memcpy(rwPseudoInv, acsParameters->rwMatrices.pseudoInverseWithoutRW4,
|
||||
12 * sizeof(double));
|
||||
return acsctrl::SINGLE_RW_UNAVAILABLE;
|
||||
}
|
||||
return acsctrl::MULTIPLE_RW_UNAVAILABLE;
|
||||
}
|
||||
|
||||
void Guidance::resetValues() {
|
||||
std::memcpy(quatIXprev, ZERO_VEC4, sizeof(quatIXprev));
|
||||
std::memcpy(xAxisIXprev, ZERO_VEC3, sizeof(xAxisIXprev));
|
||||
}
|
||||
|
||||
void Guidance::getTargetParamsSafe(double sunTargetSafe[3]) {
|
||||
|
@ -1,11 +1,18 @@
|
||||
#ifndef GUIDANCE_H_
|
||||
#define GUIDANCE_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <fsfw/coordinates/CoordinateTransformations.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
#include "../controllerdefinitions/AcsCtrlDefinitions.h"
|
||||
#include "AcsParameters.h"
|
||||
#include "SensorValues.h"
|
||||
#include <cmath>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
class Guidance {
|
||||
public:
|
||||
@ -14,33 +21,22 @@ class Guidance {
|
||||
|
||||
void getTargetParamsSafe(double sunTargetSafe[3]);
|
||||
ReturnValue_t solarArrayDeploymentComplete();
|
||||
void resetValues();
|
||||
|
||||
// Function to get the target quaternion and reference rotation rate from gps position and
|
||||
// position of the ground station
|
||||
void targetQuatPtgSingleAxis(timeval now, double posSatE[3], double velSatE[3], double sunDirI[3],
|
||||
double refDirB[3], double quatBI[4], double targetQuat[4],
|
||||
double targetSatRotRate[3]);
|
||||
void targetQuatPtgThreeAxes(timeval now, double posSatE[3], double velSatE[3], double quatIX[4],
|
||||
double targetSatRotRate[3]);
|
||||
void targetQuatPtgGs(timeval now, double posSatE[3], double sunDirI[3], double quatIX[4],
|
||||
double targetSatRotRate[3]);
|
||||
void targetQuatPtgIdle(timeval timeAbsolute, const double timeDelta, const double sunDirI[3],
|
||||
const double posSatF[4], double targetQuat[4], double targetSatRotRate[3]);
|
||||
void targetQuatPtgTarget(timeval timeAbsolute, const double timeDelta, const double posSatF[3],
|
||||
const double velSatE[3], double quatIX[4], double targetSatRotRate[3]);
|
||||
void targetQuatPtgGs(timeval timeAbsolute, const double timeDelta, const double posSatF[3],
|
||||
const double sunDirI[3], double quatIX[4], double targetSatRotRate[3]);
|
||||
void targetQuatPtgNadir(timeval timeAbsolute, const double timeDelta, const double posSatF[3],
|
||||
const double velSatF[3], double targetQuat[4], double refSatRate[3]);
|
||||
|
||||
// Function to get the target quaternion and reference rotation rate for sun pointing after ground
|
||||
// station
|
||||
void targetQuatPtgSun(timeval now, double sunDirI[3], double targetQuat[4],
|
||||
double targetSatRotRate[3]);
|
||||
void targetRotationRate(const double timeDelta, double quatInertialTarget[4],
|
||||
double *targetSatRotRate);
|
||||
|
||||
// Function to get the target quaternion and refence rotation rate from gps position for Nadir
|
||||
// pointing
|
||||
void targetQuatPtgNadirSingleAxis(timeval now, double posSatE[3], double quatBI[4],
|
||||
double targetQuat[4], double refDirB[3], double refSatRate[3]);
|
||||
void targetQuatPtgNadirThreeAxes(timeval now, double posSatE[3], double velSatE[3],
|
||||
double targetQuat[4], double refSatRate[3]);
|
||||
void limitReferenceRotation(const double xAxisIX[3], double quatIX[4]);
|
||||
|
||||
// @note: Calculates the error quaternion between the current orientation and the target
|
||||
// quaternion, considering a reference quaternion. Additionally the difference between the actual
|
||||
// and a desired satellite rotational rate is calculated, again considering a reference rotational
|
||||
// rate. Lastly gives back the error angle of the error quaternion.
|
||||
void comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4],
|
||||
double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3],
|
||||
double errorQuat[4], double errorSatRotRate[3], double &errorAngle);
|
||||
@ -48,20 +44,18 @@ class Guidance {
|
||||
double targetSatRotRate[3], double errorQuat[4], double errorSatRotRate[3],
|
||||
double &errorAngle);
|
||||
|
||||
void targetRotationRate(int8_t timeElapsedMax, timeval now, double quatInertialTarget[4],
|
||||
double *targetSatRotRate);
|
||||
|
||||
// @note: will give back the pseudoinverse matrix for the reaction wheel depending on the valid
|
||||
// reation wheel maybe can be done in "commanding.h"
|
||||
ReturnValue_t getDistributionMatrixRw(ACS::SensorValues *sensorValues, double *rwPseudoInv);
|
||||
ReturnValue_t getDistributionMatrixRw(ACS::SensorValues *sensorValues, double *rwPseudoInv,
|
||||
acsctrl::RwAvail *rwAvail);
|
||||
|
||||
private:
|
||||
const AcsParameters *acsParameters;
|
||||
|
||||
static constexpr double ZERO_VEC3[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC4[4] = {0, 0, 0, 0};
|
||||
|
||||
bool strBlindAvoidFlag = false;
|
||||
timeval timeSavedQuaternion;
|
||||
double savedQuaternion[4] = {0, 0, 0, 0};
|
||||
double omegaRefSaved[3] = {0, 0, 0};
|
||||
double quatIXprev[4] = {0, 0, 0, 0};
|
||||
double xAxisIXprev[3] = {0, 0, 0};
|
||||
|
||||
static constexpr char SD_0_SKEWED_PTG_FILE[] = "/mnt/sd0/conf/acsDeploymentConfirm";
|
||||
static constexpr char SD_1_SKEWED_PTG_FILE[] = "/mnt/sd1/conf/acsDeploymentConfirm";
|
||||
|
@ -1,19 +1,5 @@
|
||||
#include "Igrf13Model.h"
|
||||
|
||||
#include <fsfw/src/fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "util/MathOperations.h"
|
||||
|
||||
using namespace Math;
|
||||
|
||||
Igrf13Model::Igrf13Model() {}
|
||||
Igrf13Model::~Igrf13Model() {}
|
||||
|
||||
@ -23,7 +9,7 @@ void Igrf13Model::magFieldComp(const double longitude, const double gcLatitude,
|
||||
double magFieldModel[3] = {0, 0, 0};
|
||||
double phi = longitude, theta = gcLatitude; // geocentric
|
||||
/* Here is the co-latitude needed*/
|
||||
theta -= 90 * PI / 180;
|
||||
theta -= 90. * M_PI / 180.;
|
||||
theta *= (-1);
|
||||
|
||||
double rE = 6371200.0; // radius earth [m]
|
||||
@ -83,13 +69,14 @@ void Igrf13Model::magFieldComp(const double longitude, const double gcLatitude,
|
||||
magFieldModel[1] *= -1;
|
||||
magFieldModel[2] *= (-1 / sin(theta));
|
||||
|
||||
double JD2000 = MathOperations<double>::convertUnixToJD2000(timeOfMagMeasurement);
|
||||
double JD2000 = 0;
|
||||
Clock::convertTimevalToJD2000(timeOfMagMeasurement, &JD2000);
|
||||
double UT1 = JD2000 / 36525.;
|
||||
|
||||
double gst =
|
||||
280.46061837 + 360.98564736629 * JD2000 + 0.0003875 * pow(UT1, 2) - 2.6e-8 * pow(UT1, 3);
|
||||
gst = std::fmod(gst, 360.);
|
||||
gst *= PI / 180.;
|
||||
gst *= M_PI / 180.;
|
||||
double lst = gst + longitude; // local sidereal time [rad]
|
||||
|
||||
magFieldModelInertial[0] =
|
||||
@ -107,7 +94,8 @@ void Igrf13Model::magFieldComp(const double longitude, const double gcLatitude,
|
||||
|
||||
void Igrf13Model::updateCoeffGH(timeval timeOfMagMeasurement) {
|
||||
double JD2000Igrf = (2458850.0 - 2451545); // Begin of IGRF-13 (2020-01-01,00:00:00) in JD2000
|
||||
double JD2000 = MathOperations<double>::convertUnixToJD2000(timeOfMagMeasurement);
|
||||
double JD2000 = 0;
|
||||
Clock::convertTimevalToJD2000(timeOfMagMeasurement, &JD2000);
|
||||
double days = ceil(JD2000 - JD2000Igrf);
|
||||
for (int i = 0; i <= igrfOrder; i++) {
|
||||
for (int j = 0; j <= (igrfOrder - 1); j++) {
|
||||
|
@ -16,10 +16,11 @@
|
||||
#ifndef IGRF13MODEL_H_
|
||||
#define IGRF13MODEL_H_
|
||||
|
||||
#include <fsfw/parameters/HasParametersIF.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/src/fsfw/timemanager/Clock.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,16 @@
|
||||
#ifndef MULTIPLICATIVEKALMANFILTER_H_
|
||||
#define MULTIPLICATIVEKALMANFILTER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../controllerdefinitions/AcsCtrlDefinitions.h"
|
||||
#include "AcsParameters.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include <common/config/eive/resultClassIds.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
class MultiplicativeKalmanFilter {
|
||||
/* @brief: This class handles the calculation of an estimated quaternion and the gyro bias by
|
||||
/* @brief: This class handles the calculation of an estimated quaternion and the gyroscope bias by
|
||||
* means of the spacecraft attitude sensors
|
||||
*
|
||||
* @note: A description of the used algorithms can be found in the bachelor thesis of Robin
|
||||
@ -18,56 +20,26 @@ class MultiplicativeKalmanFilter {
|
||||
public:
|
||||
/* @brief: Constructor
|
||||
*/
|
||||
MultiplicativeKalmanFilter();
|
||||
MultiplicativeKalmanFilter(AcsParameters *acsParameters);
|
||||
virtual ~MultiplicativeKalmanFilter();
|
||||
|
||||
ReturnValue_t reset(acsctrl::MekfData *mekfData);
|
||||
ReturnValue_t reset(acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
|
||||
/* @brief: init() - This function initializes the Kalman Filter and will provide the first
|
||||
* quaternion through the QUEST algorithm
|
||||
* @param: magneticField_ magnetic field vector in the body frame
|
||||
* sunDir_ sun direction vector in the body frame
|
||||
* sunDirJ sun direction vector in the ECI frame
|
||||
* magFieldJ magnetic field vector in the ECI frame
|
||||
*/
|
||||
ReturnValue_t init(const double *magneticField_, const bool validMagField_, const double *sunDir_,
|
||||
const bool validSS, const double *sunDirJ, const bool validSSModel,
|
||||
const double *magFieldJ, const bool validMagModel, acsctrl::MekfData *mekfData,
|
||||
AcsParameters *acsParameters);
|
||||
ReturnValue_t init(const acsctrl::SusDataProcessed *susData,
|
||||
const acsctrl::MgmDataProcessed *mgmData,
|
||||
const acsctrl::GyrDataProcessed *gyrData,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
|
||||
/* @brief: mekfEst() - This function calculates the quaternion and gyro bias of the Kalman Filter
|
||||
* for the current step after the initalization
|
||||
* @param: quaternionSTR Star Tracker Quaternion between from body to ECI frame
|
||||
* rateGYRs_ Estimated satellite rotation rate from the
|
||||
* Gyroscopes [rad/s] magneticField_ magnetic field vector in the body frame sunDir_
|
||||
* sun direction vector in the body frame sunDirJ sun direction vector in the ECI
|
||||
* frame magFieldJ magnetic field vector in the ECI frame
|
||||
* outputQuat Stores the calculated quaternion
|
||||
* outputSatRate Stores the adjusted satellite rate
|
||||
* @return ReturnValue_t Feedback of this class, KALMAN_NO_GYR_MEAS if no satellite rate from
|
||||
* the sensors was provided, KALMAN_NO_MODEL if no sunDirJ or magFieldJ was given from the model
|
||||
* calculations, KALMAN_INVERSION_FAILED if the calculation of the Gain matrix was not possible,
|
||||
* RETURN_OK else
|
||||
*/
|
||||
ReturnValue_t mekfEst(const double *quaternionSTR, const bool validSTR_, const double *rateGYRs_,
|
||||
const bool validGYRs_, const double *magneticField_,
|
||||
const bool validMagField_, const double *sunDir_, const bool validSS,
|
||||
const double *sunDirJ, const bool validSSModel, const double *magFieldJ,
|
||||
const bool validMagModel, acsctrl::MekfData *mekfData,
|
||||
AcsParameters *acsParameters);
|
||||
ReturnValue_t mekfEst(const acsctrl::SusDataProcessed *susData,
|
||||
const acsctrl::MgmDataProcessed *mgmData,
|
||||
const acsctrl::GyrDataProcessed *gyrData, const double timeDelta,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
|
||||
enum MekfStatus : uint8_t {
|
||||
UNINITIALIZED = 0,
|
||||
NO_GYR_DATA = 1,
|
||||
NO_MODEL_VECTORS = 2,
|
||||
NO_SUS_MGM_STR_DATA = 3,
|
||||
COVARIANCE_INVERSION_FAILED = 4,
|
||||
NOT_FINITE = 5,
|
||||
INITIALIZED = 10,
|
||||
RUNNING = 11,
|
||||
};
|
||||
void updateStandardDeviations(const AcsParameters *acsParameters);
|
||||
|
||||
void setStrData(const double qX, const double qY, const double qZ, const double qW,
|
||||
const bool valid, const bool allowStr);
|
||||
|
||||
// resetting Mekf
|
||||
static constexpr uint8_t IF_MEKF_ID = CLASS_ID::ACS_MEKF;
|
||||
static constexpr ReturnValue_t MEKF_UNINITIALIZED = returnvalue::makeCode(IF_MEKF_ID, 2);
|
||||
static constexpr ReturnValue_t MEKF_NO_GYR_DATA = returnvalue::makeCode(IF_MEKF_ID, 3);
|
||||
@ -82,26 +54,93 @@ class MultiplicativeKalmanFilter {
|
||||
private:
|
||||
static constexpr double ZERO_VEC3[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC4[4] = {0, 0, 0, 0};
|
||||
|
||||
/*Parameters*/
|
||||
double quaternion_STR_SB[4];
|
||||
|
||||
/*States*/
|
||||
double initialQuaternion[4] = {0, 0, 0, 1}; /*after reset?QUEST*/
|
||||
double initialCovarianceMatrix[6][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
||||
static constexpr double ZERO_MAT66[6][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}};
|
||||
double propagatedQuaternion[4]; /*Filter Quaternion for next step*/
|
||||
uint8_t sensorsAvail = 0;
|
||||
static constexpr double UNIT_QUAT[4] = {0, 0, 0, 1};
|
||||
static constexpr double EYE3[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
|
||||
static constexpr double EYE6[6][6] = {{1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1}};
|
||||
|
||||
/*Outputs*/
|
||||
double quatBJ[4]; /* Output Quaternion */
|
||||
double biasGYR[3]; /*Between measured and estimated sat Rate*/
|
||||
/*Parameter INIT*/
|
||||
/*Functions*/
|
||||
void updateDataSetWithoutData(acsctrl::MekfData *mekfData, MekfStatus mekfStatus);
|
||||
void updateDataSet(acsctrl::MekfData *mekfData, MekfStatus mekfStatus, double quat[4],
|
||||
double satRotRate[3]);
|
||||
enum MekfStatus : uint8_t {
|
||||
UNINITIALIZED = 0,
|
||||
NO_GYR_DATA = 1,
|
||||
NO_MODEL_VECTORS = 2,
|
||||
NO_SUS_MGM_STR_DATA = 3,
|
||||
COVARIANCE_INVERSION_FAILED = 4,
|
||||
NOT_FINITE = 5,
|
||||
INITIALIZED = 10,
|
||||
RUNNING = 11,
|
||||
};
|
||||
|
||||
enum SensorAvailability : uint8_t {
|
||||
NONE = 0,
|
||||
SUS_MGM_STR = 1,
|
||||
SUS_MGM = 2,
|
||||
SUS_STR = 3,
|
||||
MGM_STR = 4,
|
||||
SUS = 5,
|
||||
MGM = 6,
|
||||
STR = 7,
|
||||
};
|
||||
|
||||
MekfStatus mekfStatus = MekfStatus::UNINITIALIZED;
|
||||
|
||||
struct StrData {
|
||||
struct StrQuat {
|
||||
double value[4] = {0, 0, 0, 0};
|
||||
bool valid = false;
|
||||
} strQuat;
|
||||
} strData;
|
||||
|
||||
// Standard Deviations
|
||||
double sigmaSus = 0;
|
||||
double sigmaMgm = 0;
|
||||
double sigmaStr = 0;
|
||||
double sigmaGyr = 0;
|
||||
// sigmaV
|
||||
double sigmaGyrArw = 0;
|
||||
// sigmaU
|
||||
double sigmaGyrBs = 0;
|
||||
|
||||
// Covariance Matrices
|
||||
double covSus[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double covMgm[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double covStr[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
|
||||
double covAposteriori[6][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}};
|
||||
|
||||
// Sensor Availability
|
||||
SensorAvailability sensorsAvailable = SensorAvailability::NONE;
|
||||
uint8_t matrixDimensionFactor = 0;
|
||||
|
||||
// Estimated States
|
||||
double estimatedQuaternionBI[4] = {0, 0, 0, 1};
|
||||
double estimatedBiasGyr[3] = {0, 0, 0};
|
||||
double estimatedRotRate[3] = {0, 0, 0};
|
||||
double estimatedCovarianceMatrix[6][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}};
|
||||
|
||||
// Functions
|
||||
ReturnValue_t checkAvailableSensors(const acsctrl::SusDataProcessed *susData,
|
||||
const acsctrl::MgmDataProcessed *mgmData,
|
||||
const acsctrl::GyrDataProcessed *gyrData,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
|
||||
void kfUpdate(const acsctrl::SusDataProcessed *susData, const acsctrl::MgmDataProcessed *mgmData,
|
||||
double *measSensMatrix, double *measCovMatrix, double *measVec, double *measEstVec);
|
||||
ReturnValue_t kfGain(double *measSensMatrix, double *measCovMatrix, double *kalmanGain,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
void kfCovAposteriori(double *kalmanGain, double *measSensMatrix);
|
||||
void kfStateAposteriori(double *kalmanGain, double *measVec, double *estVec);
|
||||
void kfPropagate(const acsctrl::GyrDataProcessed *gyrData, const double timeDiff);
|
||||
|
||||
ReturnValue_t kfFiniteCheck(acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
|
||||
void updateDataSetWithoutData(acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
void updateDataSet(acsctrl::AttitudeEstimationData *attitudeEstimationData);
|
||||
};
|
||||
|
||||
#endif /* ACS_MULTIPLICATIVEKALMANFILTER_H_ */
|
||||
|
@ -1,47 +1,33 @@
|
||||
#include "Navigation.h"
|
||||
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "util/CholeskyDecomposition.h"
|
||||
#include "util/MathOperations.h"
|
||||
|
||||
Navigation::Navigation() {}
|
||||
Navigation::Navigation(AcsParameters *acsParameters) : multiplicativeKalmanFilter(acsParameters) {}
|
||||
|
||||
Navigation::~Navigation() {}
|
||||
|
||||
ReturnValue_t Navigation::useMekf(ACS::SensorValues *sensorValues,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::SusDataProcessed *susDataProcessed,
|
||||
acsctrl::MekfData *mekfData, AcsParameters *acsParameters) {
|
||||
double quatIB[4] = {sensorValues->strSet.caliQx.value, sensorValues->strSet.caliQy.value,
|
||||
sensorValues->strSet.caliQz.value, sensorValues->strSet.caliQw.value};
|
||||
bool quatIBValid = sensorValues->strSet.isTrustWorthy.value;
|
||||
ReturnValue_t Navigation::useMekf(const ACS::SensorValues *sensorValues,
|
||||
const acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
const acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
const acsctrl::SusDataProcessed *susDataProcessed,
|
||||
const double timeDelta,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData,
|
||||
const bool allowStr) {
|
||||
multiplicativeKalmanFilter.setStrData(
|
||||
sensorValues->strSet.caliQx.value, sensorValues->strSet.caliQy.value,
|
||||
sensorValues->strSet.caliQz.value, sensorValues->strSet.caliQw.value,
|
||||
sensorValues->strSet.caliQx.isValid(), allowStr);
|
||||
|
||||
if (mekfStatus == MultiplicativeKalmanFilter::MEKF_UNINITIALIZED) {
|
||||
mekfStatus = multiplicativeKalmanFilter.init(
|
||||
mgmDataProcessed->mgmVecTot.value, mgmDataProcessed->mgmVecTot.isValid(),
|
||||
susDataProcessed->susVecTot.value, susDataProcessed->susVecTot.isValid(),
|
||||
susDataProcessed->sunIjkModel.value, susDataProcessed->sunIjkModel.isValid(),
|
||||
mgmDataProcessed->magIgrfModel.value, mgmDataProcessed->magIgrfModel.isValid(), mekfData,
|
||||
acsParameters);
|
||||
mekfStatus = multiplicativeKalmanFilter.init(susDataProcessed, mgmDataProcessed,
|
||||
gyrDataProcessed, attitudeEstimationData);
|
||||
return mekfStatus;
|
||||
} else {
|
||||
mekfStatus = multiplicativeKalmanFilter.mekfEst(
|
||||
quatIB, quatIBValid, gyrDataProcessed->gyrVecTot.value,
|
||||
gyrDataProcessed->gyrVecTot.isValid(), mgmDataProcessed->mgmVecTot.value,
|
||||
mgmDataProcessed->mgmVecTot.isValid(), susDataProcessed->susVecTot.value,
|
||||
susDataProcessed->susVecTot.isValid(), susDataProcessed->sunIjkModel.value,
|
||||
susDataProcessed->sunIjkModel.isValid(), mgmDataProcessed->magIgrfModel.value,
|
||||
mgmDataProcessed->magIgrfModel.isValid(), mekfData, acsParameters);
|
||||
susDataProcessed, mgmDataProcessed, gyrDataProcessed, timeDelta, attitudeEstimationData);
|
||||
return mekfStatus;
|
||||
}
|
||||
}
|
||||
|
||||
void Navigation::resetMekf(acsctrl::MekfData *mekfData) {
|
||||
void Navigation::resetMekf(acsctrl::AttitudeEstimationData *mekfData) {
|
||||
mekfStatus = multiplicativeKalmanFilter.reset(mekfData);
|
||||
}
|
||||
|
||||
@ -54,7 +40,7 @@ ReturnValue_t Navigation::useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDat
|
||||
{
|
||||
PoolReadGuard pg(gpsDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
gpsDataProcessed->source = acs::GpsSource::SPG4;
|
||||
gpsDataProcessed->source = acs::gps::Source::SPG4;
|
||||
gpsDataProcessed->source.setValid(true);
|
||||
std::memcpy(gpsDataProcessed->gpsPosition.value, position, 3 * sizeof(double));
|
||||
gpsDataProcessed->gpsPosition.setValid(true);
|
||||
@ -66,7 +52,7 @@ ReturnValue_t Navigation::useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDat
|
||||
{
|
||||
PoolReadGuard pg(gpsDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
gpsDataProcessed->source = acs::GpsSource::NONE;
|
||||
gpsDataProcessed->source = acs::gps::Source::NONE;
|
||||
gpsDataProcessed->source.setValid(true);
|
||||
std::memcpy(gpsDataProcessed->gpsPosition.value, position, 3 * sizeof(double));
|
||||
gpsDataProcessed->gpsPosition.setValid(false);
|
||||
@ -81,3 +67,7 @@ ReturnValue_t Navigation::useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDat
|
||||
ReturnValue_t Navigation::updateTle(const uint8_t *line1, const uint8_t *line2) {
|
||||
return sgp4Propagator.initialize(line1, line2);
|
||||
}
|
||||
|
||||
void Navigation::updateMekfStandardDeviations(const AcsParameters *acsParameters) {
|
||||
multiplicativeKalmanFilter.updateStandardDeviations(acsParameters);
|
||||
}
|
||||
|
@ -5,24 +5,25 @@
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
|
||||
#include <mission/controller/acs/SensorProcessing.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
class Navigation {
|
||||
public:
|
||||
Navigation();
|
||||
Navigation(AcsParameters *acsParameters);
|
||||
virtual ~Navigation();
|
||||
|
||||
ReturnValue_t useMekf(ACS::SensorValues *sensorValues,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::SusDataProcessed *susDataProcessed, acsctrl::MekfData *mekfData,
|
||||
AcsParameters *acsParameters);
|
||||
void resetMekf(acsctrl::MekfData *mekfData);
|
||||
ReturnValue_t useMekf(const ACS::SensorValues *sensorValues,
|
||||
const acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
const acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
const acsctrl::SusDataProcessed *susDataProcessed, const double timeDelta,
|
||||
acsctrl::AttitudeEstimationData *attitudeEstimationData,
|
||||
const bool allowStr);
|
||||
void resetMekf(acsctrl::AttitudeEstimationData *mekfData);
|
||||
|
||||
ReturnValue_t useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDataProcessed);
|
||||
ReturnValue_t updateTle(const uint8_t *line1, const uint8_t *line2);
|
||||
void updateMekfStandardDeviations(const AcsParameters *acsParameters);
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ SensorProcessing::~SensorProcessing() {}
|
||||
void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const float *mgm1Value,
|
||||
bool mgm1valid, const float *mgm2Value, bool mgm2valid,
|
||||
const float *mgm3Value, bool mgm3valid, const float *mgm4Value,
|
||||
bool mgm4valid, timeval timeOfMgmMeasurement,
|
||||
bool mgm4valid, timeval timeAbsolute, double timeDelta,
|
||||
const AcsParameters::MgmHandlingParameters *mgmParameters,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed) {
|
||||
@ -15,14 +15,14 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
// ------------------------------------------------
|
||||
double magIgrfModel[3] = {0.0, 0.0, 0.0};
|
||||
bool gpsValid = false;
|
||||
if (gpsDataProcessed->source.value != acs::GpsSource::NONE) {
|
||||
if (gpsDataProcessed->source.value != acs::gps::Source::NONE) {
|
||||
// There seems to be a bug here, which causes the model vector to drift until infinity, if the
|
||||
// model class is not initialized new every time. Works for now, but should be investigated.
|
||||
Igrf13Model igrf13;
|
||||
igrf13.schmidtNormalization();
|
||||
igrf13.updateCoeffGH(timeOfMgmMeasurement);
|
||||
// maybe put a condition here, to only update after a full day, this
|
||||
// class function has around 700 steps to perform
|
||||
igrf13.updateCoeffGH(timeAbsolute);
|
||||
igrf13.magFieldComp(gpsDataProcessed->gdLongitude.value, gpsDataProcessed->gcLatitude.value,
|
||||
gpsDataProcessed->altitude.value, timeOfMgmMeasurement, magIgrfModel);
|
||||
gpsDataProcessed->altitude.value, timeAbsolute, magIgrfModel);
|
||||
gpsValid = true;
|
||||
}
|
||||
if (not mgm0valid and not mgm1valid and not mgm2valid and not mgm3valid and
|
||||
@ -129,14 +129,12 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
//-----------------------Mgm Rate Computation ---------------------------------------------------
|
||||
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
bool mgmVecTotDerivativeValid = false;
|
||||
double timeDiff = timevalOperations::toDouble(timeOfMgmMeasurement - timeOfSavedMagFieldEst);
|
||||
if (timeOfSavedMagFieldEst.tv_sec != 0 and timeDiff > 0 and
|
||||
VectorOperations<double>::norm(savedMgmVecTot, 3) != 0) {
|
||||
if (timeDelta > 0 and VectorOperations<double>::norm(savedMgmVecTot, 3) != 0) {
|
||||
VectorOperations<double>::subtract(mgmVecTot, savedMgmVecTot, mgmVecTotDerivative, 3);
|
||||
VectorOperations<double>::mulScalar(mgmVecTotDerivative, 1. / timeDiff, mgmVecTotDerivative, 3);
|
||||
VectorOperations<double>::mulScalar(mgmVecTotDerivative, 1. / timeDelta, mgmVecTotDerivative,
|
||||
3);
|
||||
mgmVecTotDerivativeValid = true;
|
||||
}
|
||||
timeOfSavedMagFieldEst = timeOfMgmMeasurement;
|
||||
std::memcpy(savedMgmVecTot, mgmVecTot, sizeof(savedMgmVecTot));
|
||||
|
||||
if (VectorOperations<double>::norm(mgmVecTotDerivative, 3) != 0 and
|
||||
@ -177,11 +175,13 @@ void SensorProcessing::processSus(
|
||||
const uint16_t *sus6Value, bool sus6valid, const uint16_t *sus7Value, bool sus7valid,
|
||||
const uint16_t *sus8Value, bool sus8valid, const uint16_t *sus9Value, bool sus9valid,
|
||||
const uint16_t *sus10Value, bool sus10valid, const uint16_t *sus11Value, bool sus11valid,
|
||||
timeval timeOfSusMeasurement, const AcsParameters::SusHandlingParameters *susParameters,
|
||||
timeval timeAbsolute, double timeDelta,
|
||||
const AcsParameters::SusHandlingParameters *susParameters,
|
||||
const AcsParameters::SunModelParameters *sunModelParameters,
|
||||
acsctrl::SusDataProcessed *susDataProcessed) {
|
||||
/* -------- Sun Model Direction (IJK frame) ------- */
|
||||
double JD2000 = MathOperations<double>::convertUnixToJD2000(timeOfSusMeasurement);
|
||||
double JD2000 = 0;
|
||||
Clock::convertTimevalToJD2000(timeAbsolute, &JD2000);
|
||||
|
||||
// Julean Centuries
|
||||
double sunIjkModel[3] = {0.0, 0.0, 0.0};
|
||||
@ -199,6 +199,7 @@ void SensorProcessing::processSus(
|
||||
sunIjkModel[0] = cos(eclipticLongitude);
|
||||
sunIjkModel[1] = sin(eclipticLongitude) * cos(epsilon);
|
||||
sunIjkModel[2] = sin(eclipticLongitude) * sin(epsilon);
|
||||
VectorOperations<double>::normalize(sunIjkModel, sunIjkModel, 3);
|
||||
|
||||
uint64_t susBrightness[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
if (sus0valid) {
|
||||
@ -354,11 +355,10 @@ void SensorProcessing::processSus(
|
||||
|
||||
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
bool susVecTotDerivativeValid = false;
|
||||
double timeDiff = timevalOperations::toDouble(timeOfSusMeasurement - timeOfSavedSusDirEst);
|
||||
if (timeOfSavedSusDirEst.tv_sec != 0 and timeDiff > 0 and
|
||||
VectorOperations<double>::norm(savedSusVecTot, 3) != 0) {
|
||||
if (timeDelta > 0 and VectorOperations<double>::norm(savedSusVecTot, 3) != 0) {
|
||||
VectorOperations<double>::subtract(susVecTot, savedSusVecTot, susVecTotDerivative, 3);
|
||||
VectorOperations<double>::mulScalar(susVecTotDerivative, 1. / timeDiff, susVecTotDerivative, 3);
|
||||
VectorOperations<double>::mulScalar(susVecTotDerivative, 1. / timeDelta, susVecTotDerivative,
|
||||
3);
|
||||
susVecTotDerivativeValid = true;
|
||||
}
|
||||
std::memcpy(savedSusVecTot, susVecTot, sizeof(savedSusVecTot));
|
||||
@ -367,7 +367,6 @@ void SensorProcessing::processSus(
|
||||
lowPassFilter(susVecTotDerivative, susDataProcessed->susVecTotDerivative.value,
|
||||
susParameters->susRateFilterWeight);
|
||||
}
|
||||
timeOfSavedSusDirEst = timeOfSusMeasurement;
|
||||
{
|
||||
PoolReadGuard pg(susDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
@ -414,7 +413,7 @@ void SensorProcessing::processGyr(
|
||||
const double gyr2axXvalue, bool gyr2axXvalid, const double gyr2axYvalue, bool gyr2axYvalid,
|
||||
const double gyr2axZvalue, bool gyr2axZvalid, const double gyr3axXvalue, bool gyr3axXvalid,
|
||||
const double gyr3axYvalue, bool gyr3axYvalid, const double gyr3axZvalue, bool gyr3axZvalid,
|
||||
timeval timeOfGyrMeasurement, const AcsParameters::GyrHandlingParameters *gyrParameters,
|
||||
const AcsParameters::GyrHandlingParameters *gyrParameters,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed) {
|
||||
bool gyr0valid = (gyr0axXvalid && gyr0axYvalid && gyr0axZvalid);
|
||||
bool gyr1valid = (gyr1axXvalid && gyr1axYvalid && gyr1axZvalid);
|
||||
@ -521,18 +520,18 @@ void SensorProcessing::processGyr(
|
||||
}
|
||||
|
||||
void SensorProcessing::processGps(const double gpsLatitude, const double gpsLongitude,
|
||||
const double gpsAltitude, const double gpsUnixSeconds,
|
||||
const double gpsAltitude, const double timeDelta,
|
||||
const bool validGps,
|
||||
const AcsParameters::GpsParameters *gpsParameters,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed) {
|
||||
// init variables
|
||||
double gdLongitude = 0, gdLatitude = 0, gcLatitude = 0, altitude = 0, posSatE[3] = {0, 0, 0},
|
||||
gpsVelocityE[3] = {0, 0, 0};
|
||||
uint8_t gpsSource = acs::GpsSource::NONE;
|
||||
uint8_t gpsSource = acs::gps::Source::NONE;
|
||||
// We do not trust the GPS and therefore it shall die here if SPG4 is running
|
||||
if (gpsDataProcessed->source.value == acs::GpsSource::SPG4 and gpsParameters->useSpg4) {
|
||||
MathOperations<double>::latLongAltFromCartesian(gpsDataProcessed->gpsPosition.value, gdLatitude,
|
||||
gdLongitude, altitude);
|
||||
if (gpsDataProcessed->source.value == acs::gps::Source::SPG4 and gpsParameters->useSpg4) {
|
||||
CoordinateTransformations::latLongAltFromCartesian(gpsDataProcessed->gpsPosition.value,
|
||||
gdLatitude, gdLongitude, altitude);
|
||||
double factor = 1 - pow(ECCENTRICITY_WGS84, 2);
|
||||
gcLatitude = atan(factor * tan(gdLatitude));
|
||||
{
|
||||
@ -562,22 +561,18 @@ void SensorProcessing::processGps(const double gpsLatitude, const double gpsLong
|
||||
|
||||
// Calculation of the satellite velocity in earth fixed frame
|
||||
double deltaDistance[3] = {0, 0, 0};
|
||||
MathOperations<double>::cartesianFromLatLongAlt(latitudeRad, gdLongitude, altitude, posSatE);
|
||||
if (validSavedPosSatE and
|
||||
(gpsUnixSeconds - timeOfSavedPosSatE) < (gpsParameters->timeDiffVelocityMax) and
|
||||
(gpsUnixSeconds - timeOfSavedPosSatE) > 0) {
|
||||
CoordinateTransformations::cartesianFromLatLongAlt(latitudeRad, gdLongitude, altitude, posSatE);
|
||||
if (validSavedPosSatE and timeDelta < (gpsParameters->timeDiffVelocityMax) and timeDelta > 0) {
|
||||
VectorOperations<double>::subtract(posSatE, savedPosSatE, deltaDistance, 3);
|
||||
double timeDiffGpsMeas = gpsUnixSeconds - timeOfSavedPosSatE;
|
||||
VectorOperations<double>::mulScalar(deltaDistance, 1. / timeDiffGpsMeas, gpsVelocityE, 3);
|
||||
VectorOperations<double>::mulScalar(deltaDistance, 1. / timeDelta, gpsVelocityE, 3);
|
||||
}
|
||||
savedPosSatE[0] = posSatE[0];
|
||||
savedPosSatE[1] = posSatE[1];
|
||||
savedPosSatE[2] = posSatE[2];
|
||||
|
||||
timeOfSavedPosSatE = gpsUnixSeconds;
|
||||
validSavedPosSatE = true;
|
||||
|
||||
gpsSource = acs::GpsSource::GPS;
|
||||
gpsSource = acs::gps::Source::GPS;
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(gpsDataProcessed);
|
||||
@ -594,13 +589,15 @@ void SensorProcessing::processGps(const double gpsLatitude, const double gpsLong
|
||||
}
|
||||
}
|
||||
|
||||
void SensorProcessing::process(timeval now, ACS::SensorValues *sensorValues,
|
||||
void SensorProcessing::process(timeval timeAbsolute, double timeDelta,
|
||||
ACS::SensorValues *sensorValues,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::SusDataProcessed *susDataProcessed,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed,
|
||||
const AcsParameters *acsParameters) {
|
||||
sensorValues->update();
|
||||
|
||||
processGps(
|
||||
sensorValues->gpsSet.latitude.value, sensorValues->gpsSet.longitude.value,
|
||||
sensorValues->gpsSet.altitude.value, sensorValues->gpsSet.unixSeconds.value,
|
||||
@ -617,7 +614,8 @@ void SensorProcessing::process(timeval now, ACS::SensorValues *sensorValues,
|
||||
sensorValues->mgm3Rm3100Set.fieldStrengths.value,
|
||||
sensorValues->mgm3Rm3100Set.fieldStrengths.isValid(),
|
||||
sensorValues->imtqMgmSet.mtmRawNt.value, sensorValues->imtqMgmSet.mtmRawNt.isValid(),
|
||||
now, &acsParameters->mgmHandlingParameters, gpsDataProcessed, mgmDataProcessed);
|
||||
timeAbsolute, timeDelta, &acsParameters->mgmHandlingParameters, gpsDataProcessed,
|
||||
mgmDataProcessed);
|
||||
|
||||
processSus(sensorValues->susSets[0].channels.value, sensorValues->susSets[0].channels.isValid(),
|
||||
sensorValues->susSets[1].channels.value, sensorValues->susSets[1].channels.isValid(),
|
||||
@ -631,8 +629,8 @@ void SensorProcessing::process(timeval now, ACS::SensorValues *sensorValues,
|
||||
sensorValues->susSets[9].channels.value, sensorValues->susSets[9].channels.isValid(),
|
||||
sensorValues->susSets[10].channels.value, sensorValues->susSets[10].channels.isValid(),
|
||||
sensorValues->susSets[11].channels.value, sensorValues->susSets[11].channels.isValid(),
|
||||
now, &acsParameters->susHandlingParameters, &acsParameters->sunModelParameters,
|
||||
susDataProcessed);
|
||||
timeAbsolute, timeDelta, &acsParameters->susHandlingParameters,
|
||||
&acsParameters->sunModelParameters, susDataProcessed);
|
||||
|
||||
processGyr(
|
||||
sensorValues->gyr0AdisSet.angVelocX.value, sensorValues->gyr0AdisSet.angVelocX.isValid(),
|
||||
@ -646,7 +644,7 @@ void SensorProcessing::process(timeval now, ACS::SensorValues *sensorValues,
|
||||
sensorValues->gyr2AdisSet.angVelocZ.value, sensorValues->gyr2AdisSet.angVelocZ.isValid(),
|
||||
sensorValues->gyr3L3gSet.angVelocX.value, sensorValues->gyr3L3gSet.angVelocX.isValid(),
|
||||
sensorValues->gyr3L3gSet.angVelocY.value, sensorValues->gyr3L3gSet.angVelocY.isValid(),
|
||||
sensorValues->gyr3L3gSet.angVelocZ.value, sensorValues->gyr3L3gSet.angVelocZ.isValid(), now,
|
||||
sensorValues->gyr3L3gSet.angVelocZ.value, sensorValues->gyr3L3gSet.angVelocZ.isValid(),
|
||||
&acsParameters->gyrHandlingParameters, gyrDataProcessed);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define SENSORPROCESSING_H_
|
||||
|
||||
#include <common/config/eive/resultClassIds.h>
|
||||
#include <fsfw/coordinates/CoordinateTransformations.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
@ -9,12 +10,12 @@
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw/timemanager/Clock.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/Igrf13Model.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <mission/controller/acs/SusConverter.h>
|
||||
#include <mission/controller/acs/util/MathOperations.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
#include <cmath>
|
||||
@ -24,22 +25,21 @@ class SensorProcessing {
|
||||
SensorProcessing();
|
||||
virtual ~SensorProcessing();
|
||||
|
||||
void process(timeval now, ACS::SensorValues *sensorValues,
|
||||
void process(timeval timeAbsolute, double timeDelta, ACS::SensorValues *sensorValues,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::SusDataProcessed *susDataProcessed,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed,
|
||||
const AcsParameters *acsParameters); // Will call protected functions
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed, const AcsParameters *acsParameters);
|
||||
|
||||
private:
|
||||
static constexpr float ZERO_VEC_F[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC_D[3] = {0, 0, 0};
|
||||
static constexpr double ECCENTRICITY_WGS84 = 0.0818195;
|
||||
|
||||
protected:
|
||||
// short description needed for every function
|
||||
void processMgm(const float *mgm0Value, bool mgm0valid, const float *mgm1Value, bool mgm1valid,
|
||||
const float *mgm2Value, bool mgm2valid, const float *mgm3Value, bool mgm3valid,
|
||||
const float *mgm4Value, bool mgm4valid, timeval timeOfMgmMeasurement,
|
||||
const float *mgm4Value, bool mgm4valid, timeval timeAbsolute, double timeDelta,
|
||||
const AcsParameters::MgmHandlingParameters *mgmParameters,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed);
|
||||
@ -52,7 +52,7 @@ class SensorProcessing {
|
||||
bool sus7valid, const uint16_t *sus8Value, bool sus8valid,
|
||||
const uint16_t *sus9Value, bool sus9valid, const uint16_t *sus10Value,
|
||||
bool sus10valid, const uint16_t *sus11Value, bool sus11valid,
|
||||
timeval timeOfSusMeasurement,
|
||||
timeval timeAbsolute, double timeDelta,
|
||||
const AcsParameters::SusHandlingParameters *susParameters,
|
||||
const AcsParameters::SunModelParameters *sunModelParameters,
|
||||
acsctrl::SusDataProcessed *susDataProcessed);
|
||||
@ -65,7 +65,6 @@ class SensorProcessing {
|
||||
bool gyr2axYvalid, const double gyr2axZvalue, bool gyr2axZvalid,
|
||||
const double gyr3axXvalue, bool gyr3axXvalid, const double gyr3axYvalue,
|
||||
bool gyr3axYvalid, const double gyr3axZvalue, bool gyr3axZvalid,
|
||||
timeval timeOfGyrMeasurement,
|
||||
const AcsParameters::GyrHandlingParameters *gyrParameters,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed);
|
||||
|
||||
@ -77,13 +76,9 @@ class SensorProcessing {
|
||||
void lowPassFilter(double *newValue, double *oldValue, const double weight);
|
||||
|
||||
double savedMgmVecTot[3] = {0.0, 0.0, 0.0};
|
||||
timeval timeOfSavedMagFieldEst;
|
||||
double savedSusVecTot[3] = {0.0, 0.0, 0.0};
|
||||
timeval timeOfSavedSusDirEst;
|
||||
bool validMagField = false;
|
||||
|
||||
double savedPosSatE[3] = {0.0, 0.0, 0.0};
|
||||
double timeOfSavedPosSatE = 0.0;
|
||||
bool validSavedPosSatE = false;
|
||||
|
||||
SusConverter susConverter;
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h>
|
||||
#include <fsfw_hal/devicehandlers/MgmRM3100Handler.h>
|
||||
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
|
||||
#include <mission/acs/archive/GPSDefinitions.h>
|
||||
#include <linux/acs/GPSDefinitions.h>
|
||||
#include <mission/acs/gyroAdisHelpers.h>
|
||||
#include <mission/acs/imtqHelpers.h>
|
||||
#include <mission/acs/rwHelpers.h>
|
||||
|
@ -7,18 +7,18 @@ Detumble::Detumble() {}
|
||||
|
||||
Detumble::~Detumble() {}
|
||||
|
||||
acs::SafeModeStrategy Detumble::detumbleStrategy(const bool magFieldValid,
|
||||
acs::ControlModeStrategy Detumble::detumbleStrategy(const bool magFieldValid,
|
||||
const bool satRotRateValid,
|
||||
const bool magFieldRateValid,
|
||||
const bool useFullDetumbleLaw) {
|
||||
if (not magFieldValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
return acs::ControlModeStrategy::CTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
} else if (satRotRateValid and useFullDetumbleLaw) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_DETUMBLE_FULL;
|
||||
return acs::ControlModeStrategy::SAFECTRL_DETUMBLE_FULL;
|
||||
} else if (magFieldRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_DETUMBLE_DETERIORATED;
|
||||
return acs::ControlModeStrategy::SAFECTRL_DETUMBLE_DETERIORATED;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
return acs::ControlModeStrategy::CTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ class Detumble {
|
||||
Detumble();
|
||||
virtual ~Detumble();
|
||||
|
||||
acs::SafeModeStrategy detumbleStrategy(const bool magFieldValid, const bool satRotRateValid,
|
||||
acs::ControlModeStrategy detumbleStrategy(const bool magFieldValid, const bool satRotRateValid,
|
||||
const bool magFieldRateValid,
|
||||
const bool useFullDetumbleLaw);
|
||||
|
||||
|
@ -1,15 +1,24 @@
|
||||
#include "PtgCtrl.h"
|
||||
|
||||
#include <fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/globalfunctions/sign.h>
|
||||
|
||||
PtgCtrl::PtgCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameters_; }
|
||||
|
||||
PtgCtrl::~PtgCtrl() {}
|
||||
|
||||
acs::ControlModeStrategy PtgCtrl::pointingCtrlStrategy(
|
||||
const bool magFieldValid, const bool mekfValid, const bool strValid, const bool questValid,
|
||||
const bool fusedRateValid, const uint8_t rotRateSource, const uint8_t mekfEnabled) {
|
||||
if (not magFieldValid) {
|
||||
return acs::ControlModeStrategy::CTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
} else if (strValid and fusedRateValid and rotRateSource > acs::rotrate::Source::SUSMGM) {
|
||||
return acs::ControlModeStrategy::PTGCTRL_STR;
|
||||
} else if (mekfEnabled and mekfValid) {
|
||||
return acs::ControlModeStrategy::PTGCTRL_MEKF;
|
||||
} else if (questValid and fusedRateValid and rotRateSource > acs::rotrate::Source::SUSMGM) {
|
||||
return acs::ControlModeStrategy::PTGCTRL_QUEST;
|
||||
}
|
||||
return acs::ControlModeStrategy::CTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
|
||||
void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
const double *errorQuat, const double *deltaRate, const double *rwPseudoInv,
|
||||
double *torqueRws) {
|
||||
@ -24,7 +33,7 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters
|
||||
double qError[3] = {errorQuat[0], errorQuat[1], errorQuat[2]};
|
||||
|
||||
double cInt = 2 * om * zeta;
|
||||
double kInt = 2 * pow(om, 2);
|
||||
double kInt = 2 * om * om;
|
||||
|
||||
double qErrorLaw[3] = {0, 0, 0};
|
||||
|
||||
@ -53,9 +62,9 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters
|
||||
|
||||
// Inverse of gainMatrix
|
||||
double gainMatrixInverse[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
gainMatrixInverse[0][0] = 1 / gainMatrix[0][0];
|
||||
gainMatrixInverse[1][1] = 1 / gainMatrix[1][1];
|
||||
gainMatrixInverse[2][2] = 1 / gainMatrix[2][2];
|
||||
gainMatrixInverse[0][0] = 1. / gainMatrix[0][0];
|
||||
gainMatrixInverse[1][1] = 1. / gainMatrix[1][1];
|
||||
gainMatrixInverse[2][2] = 1. / gainMatrix[2][2];
|
||||
|
||||
double pMatrix[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MatrixOperations<double>::multiply(
|
||||
@ -96,9 +105,13 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters
|
||||
VectorOperations<double>::mulScalar(torqueRws, -1, torqueRws, 4);
|
||||
}
|
||||
|
||||
void PtgCtrl::ptgNullspace(AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
void PtgCtrl::ptgNullspace(const bool allRwAvabilable,
|
||||
AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
const int32_t speedRw0, const int32_t speedRw1, const int32_t speedRw2,
|
||||
const int32_t speedRw3, double *rwTrqNs) {
|
||||
if (not allRwAvabilable) {
|
||||
return;
|
||||
}
|
||||
// concentrate RW speeds as vector and convert to double
|
||||
double speedRws[4] = {static_cast<double>(speedRw0), static_cast<double>(speedRw1),
|
||||
static_cast<double>(speedRw2), static_cast<double>(speedRw3)};
|
||||
@ -127,9 +140,10 @@ void PtgCtrl::ptgNullspace(AcsParameters::PointingLawParameters *pointingLawPara
|
||||
4);
|
||||
}
|
||||
|
||||
void PtgCtrl::ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
void PtgCtrl::ptgDesaturation(const bool allRwAvailable, const acsctrl::RwAvail *rwAvail,
|
||||
AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
const double *magFieldB, const bool magFieldBValid,
|
||||
const double *satRate, const int32_t speedRw0, const int32_t speedRw1,
|
||||
const int32_t speedRw0, const int32_t speedRw1,
|
||||
const int32_t speedRw2, const int32_t speedRw3, double *mgtDpDes) {
|
||||
if (not magFieldBValid or not pointingLawParameters->desatOn) {
|
||||
return;
|
||||
@ -143,17 +157,24 @@ void PtgCtrl::ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawP
|
||||
double magFieldBT[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
|
||||
// calculate angular momentum of the satellite
|
||||
double angMomentumSat[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrixDeployed), satRate,
|
||||
angMomentumSat, 3, 3, 1);
|
||||
|
||||
// calculate angular momentum of the reaction wheels with respect to the nullspace RW speed
|
||||
// relocate RW speed zero to nullspace RW speed
|
||||
double refSpeedRws[4] = {0, 0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(acsParameters->rwMatrices.nullspaceVector,
|
||||
pointingLawParameters->nullspaceSpeed, refSpeedRws, 4);
|
||||
if (not allRwAvailable) {
|
||||
if (not rwAvail->rw1avail) {
|
||||
refSpeedRws[0] = 0.0;
|
||||
} else if (not rwAvail->rw2avail) {
|
||||
refSpeedRws[1] = 0.0;
|
||||
} else if (not rwAvail->rw3avail) {
|
||||
refSpeedRws[2] = 0.0;
|
||||
} else if (not rwAvail->rw4avail) {
|
||||
refSpeedRws[3] = 0.0;
|
||||
}
|
||||
}
|
||||
VectorOperations<double>::subtract(speedRws, refSpeedRws, speedRws, 4);
|
||||
|
||||
// convert speed from 10 RPM to 1 RPM
|
||||
VectorOperations<double>::mulScalar(speedRws, 1e-1, speedRws, 4);
|
||||
// convert to rad/s
|
||||
@ -169,16 +190,12 @@ void PtgCtrl::ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawP
|
||||
|
||||
// calculate total angular momentum
|
||||
double angMomentumTotal[3] = {0, 0, 0};
|
||||
VectorOperations<double>::add(angMomentumSat, angMomentumRw, angMomentumTotal, 3);
|
||||
|
||||
// calculating momentum error
|
||||
double deltaAngMomentum[3] = {0, 0, 0};
|
||||
VectorOperations<double>::subtract(angMomentumTotal, pointingLawParameters->desatMomentumRef,
|
||||
deltaAngMomentum, 3);
|
||||
VectorOperations<double>::subtract(angMomentumRw, pointingLawParameters->desatMomentumRef,
|
||||
angMomentumTotal, 3);
|
||||
|
||||
// resulting magnetic dipole command
|
||||
double crossAngMomentumMagField[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(deltaAngMomentum, magFieldBT, crossAngMomentumMagField);
|
||||
VectorOperations<double>::cross(angMomentumTotal, magFieldBT, crossAngMomentumMagField);
|
||||
double factor =
|
||||
pointingLawParameters->deSatGainFactor / VectorOperations<double>::norm(magFieldBT, 3);
|
||||
VectorOperations<double>::mulScalar(crossAngMomentumMagField, factor, mgtDpDes, 3);
|
||||
@ -202,9 +219,13 @@ void PtgCtrl::rwAntistiction(ACS::SensorValues *sensorValues, int32_t *rwCmdSpee
|
||||
rwCmdSpeeds[i] = acsParameters->rwHandlingParameters.stictionSpeed;
|
||||
} else if (rwCmdSpeeds[i] < currRwSpeed[i]) {
|
||||
rwCmdSpeeds[i] = -acsParameters->rwHandlingParameters.stictionSpeed;
|
||||
} else {
|
||||
rwCmdSpeeds[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rwCmdSpeeds[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,21 @@
|
||||
#ifndef PTGCTRL_H_
|
||||
#define PTGCTRL_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/globalfunctions/sign.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <stdio.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class PtgCtrl {
|
||||
/*
|
||||
* @brief: This class handles the pointing control mechanism. Calculation of an commanded
|
||||
* torque for the reaction wheels, and magnetic Field strength for magnetorques for desaturation
|
||||
* torque for the reaction wheels, and magnetic Field strength for magnetorquer for desaturation
|
||||
*
|
||||
* @note: A description of the used algorithms can be found in
|
||||
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_Studenten/Marquardt_Robin&openfile=896110
|
||||
@ -21,22 +27,30 @@ class PtgCtrl {
|
||||
PtgCtrl(AcsParameters *acsParameters_);
|
||||
virtual ~PtgCtrl();
|
||||
|
||||
acs::ControlModeStrategy pointingCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool strValid, const bool questValid,
|
||||
const bool fusedRateValid,
|
||||
const uint8_t rotRateSource,
|
||||
const uint8_t mekfEnabled);
|
||||
|
||||
/* @brief: Calculates the needed torque for the pointing control mechanism
|
||||
*/
|
||||
void ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters, const double *qError,
|
||||
const double *deltaRate, const double *rwPseudoInv, double *torqueRws);
|
||||
|
||||
void ptgNullspace(AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
void ptgNullspace(const bool allRwAvabilable,
|
||||
AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
const int32_t speedRw0, const int32_t speedRw1, const int32_t speedRw2,
|
||||
const int32_t speedRw3, double *rwTrqNs);
|
||||
|
||||
void ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
const double *magFieldB, const bool magFieldBValid, const double *satRate,
|
||||
const int32_t speedRw0, const int32_t speedRw1, const int32_t speedRw2,
|
||||
const int32_t speedRw3, double *mgtDpDes);
|
||||
void ptgDesaturation(const bool allRwAvabilable, const acsctrl::RwAvail *rwAvail,
|
||||
AcsParameters::PointingLawParameters *pointingLawParameters,
|
||||
const double *magFieldB, const bool magFieldBValid, const int32_t speedRw0,
|
||||
const int32_t speedRw1, const int32_t speedRw2, const int32_t speedRw3,
|
||||
double *mgtDpDes);
|
||||
|
||||
/* @brief: Commands the stiction torque in case wheel speed is to low
|
||||
* torqueCommand modified torque after antistiction
|
||||
* torqueCommand modified torque after anti-stiction
|
||||
*/
|
||||
void rwAntistiction(ACS::SensorValues *sensorValues, int32_t *rwCmdSpeed);
|
||||
|
||||
|
@ -9,40 +9,38 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter
|
||||
|
||||
SafeCtrl::~SafeCtrl() {}
|
||||
|
||||
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const bool fusedRateTotalValid,
|
||||
const uint8_t mekfEnabled,
|
||||
const uint8_t gyrEnabled,
|
||||
const uint8_t dampingEnabled) {
|
||||
acs::ControlModeStrategy SafeCtrl::safeCtrlStrategy(
|
||||
const bool magFieldValid, const bool mekfValid, const bool satRotRateValid,
|
||||
const bool sunDirValid, const bool fusedRateTotalValid, const uint8_t mekfEnabled,
|
||||
const uint8_t gyrEnabled, const uint8_t dampingEnabled) {
|
||||
if (not magFieldValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
return acs::ControlModeStrategy::CTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
} else if (mekfEnabled and mekfValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_MEKF;
|
||||
return acs::ControlModeStrategy::SAFECTRL_MEKF;
|
||||
} else if (sunDirValid) {
|
||||
if (gyrEnabled and satRotRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_GYR;
|
||||
return acs::ControlModeStrategy::SAFECTRL_GYR;
|
||||
} else if (not gyrEnabled and fusedRateTotalValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_SUSMGM;
|
||||
return acs::ControlModeStrategy::SAFECTRL_SUSMGM;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
return acs::ControlModeStrategy::CTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
} else if (not sunDirValid) {
|
||||
if (dampingEnabled) {
|
||||
if (gyrEnabled and satRotRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR;
|
||||
return acs::ControlModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR;
|
||||
} else if (not gyrEnabled and satRotRateValid and fusedRateTotalValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM;
|
||||
return acs::ControlModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
return acs::ControlModeStrategy::CTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
} else if (not dampingEnabled and satRotRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
|
||||
return acs::ControlModeStrategy::SAFECTRL_ECLIPSE_IDELING;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
return acs::ControlModeStrategy::CTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
return acs::ControlModeStrategy::CTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,11 @@ class SafeCtrl {
|
||||
SafeCtrl(AcsParameters *acsParameters_);
|
||||
virtual ~SafeCtrl();
|
||||
|
||||
acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
acs::ControlModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const bool fusedRateTotalValid, const uint8_t mekfEnabled,
|
||||
const uint8_t gyrEnabled, const uint8_t dampingEnabled);
|
||||
const bool fusedRateTotalValid,
|
||||
const uint8_t mekfEnabled, const uint8_t gyrEnabled,
|
||||
const uint8_t dampingEnabled);
|
||||
|
||||
void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI,
|
||||
const double *quatBI, const double *sunDirRefB, double *magMomB,
|
||||
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* TinyEKF: Extended Kalman Filter for embedded processors
|
||||
*
|
||||
* Copyright (C) 2015 Simon D. Levy
|
||||
*
|
||||
* MIT License
|
||||
*/
|
||||
#ifndef CHOLESKYDECOMPOSITION_H_
|
||||
#define CHOLESKYDECOMPOSITION_H_
|
||||
#include <math.h>
|
||||
// typedef unsigned int uint8_t;
|
||||
|
||||
template <typename T1, typename T2 = T1, typename T3 = T2>
|
||||
class CholeskyDecomposition {
|
||||
public:
|
||||
static int invertCholesky(T1 *matrix, T2 *result, T3 *tempMatrix, const uint8_t dimension) {
|
||||
// https://github.com/simondlevy/TinyEKF/blob/master/tiny_ekf.c
|
||||
return cholsl(matrix, result, tempMatrix, dimension);
|
||||
}
|
||||
|
||||
private:
|
||||
// https://github.com/simondlevy/TinyEKF/blob/master/tiny_ekf.c
|
||||
static uint8_t choldc1(double *a, double *p, uint8_t n) {
|
||||
int8_t i, j, k;
|
||||
double sum;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (j = i; j < n; j++) {
|
||||
sum = a[i * n + j];
|
||||
for (k = i - 1; k >= 0; k--) {
|
||||
sum -= a[i * n + k] * a[j * n + k];
|
||||
}
|
||||
if (i == j) {
|
||||
if (sum <= 0) {
|
||||
return 1; /* error */
|
||||
}
|
||||
p[i] = sqrt(sum);
|
||||
} else {
|
||||
a[j * n + i] = sum / p[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
// https://github.com/simondlevy/TinyEKF/blob/master/tiny_ekf.c
|
||||
static uint8_t choldcsl(double *A, double *a, double *p, uint8_t n) {
|
||||
uint8_t i, j, k;
|
||||
double sum;
|
||||
for (i = 0; i < n; i++)
|
||||
for (j = 0; j < n; j++) a[i * n + j] = A[i * n + j];
|
||||
if (choldc1(a, p, n)) return 1;
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i * n + i] = 1 / p[i];
|
||||
for (j = i + 1; j < n; j++) {
|
||||
sum = 0;
|
||||
for (k = i; k < j; k++) {
|
||||
sum -= a[j * n + k] * a[k * n + i];
|
||||
}
|
||||
a[j * n + i] = sum / p[j];
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
// https://github.com/simondlevy/TinyEKF/blob/master/tiny_ekf.c
|
||||
static uint8_t cholsl(double *A, double *a, double *p, uint8_t n) {
|
||||
uint8_t i, j, k;
|
||||
if (choldcsl(A, a, p, n)) return 1;
|
||||
for (i = 0; i < n; i++) {
|
||||
for (j = i + 1; j < n; j++) {
|
||||
a[i * n + j] = 0.0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i * n + i] *= a[i * n + i];
|
||||
for (k = i + 1; k < n; k++) {
|
||||
a[i * n + i] += a[k * n + i] * a[k * n + i];
|
||||
}
|
||||
for (j = i + 1; j < n; j++) {
|
||||
for (k = j; k < n; k++) {
|
||||
a[i * n + j] += a[k * n + i] * a[k * n + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
for (j = 0; j < i; j++) {
|
||||
a[i * n + j] = a[j * n + i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* success */
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* CONTRIB_MATH_CHOLESKYDECOMPOSITION_H_ */
|
@ -1,468 +0,0 @@
|
||||
#ifndef MATH_MATHOPERATIONS_H_
|
||||
#define MATH_MATHOPERATIONS_H_
|
||||
|
||||
#include <fsfw/src/fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/sign.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
template <typename T1, typename T2 = T1>
|
||||
class MathOperations {
|
||||
public:
|
||||
static void skewMatrix(const T1 vector[], T2 *result) {
|
||||
// Input Dimension [3], Output [3][3]
|
||||
result[0] = 0;
|
||||
result[1] = -vector[2];
|
||||
result[2] = vector[1];
|
||||
result[3] = vector[2];
|
||||
result[4] = 0;
|
||||
result[5] = -vector[0];
|
||||
result[6] = -vector[1];
|
||||
result[7] = vector[0];
|
||||
result[8] = 0;
|
||||
}
|
||||
static void vecTransposeVecMatrix(const T1 vector1[], const T1 transposeVector2[], T2 *result,
|
||||
uint8_t size = 3) {
|
||||
// Looks like MatrixOpertions::multiply is able to do the same thing
|
||||
for (uint8_t resultColumn = 0; resultColumn < size; resultColumn++) {
|
||||
for (uint8_t resultRow = 0; resultRow < size; resultRow++) {
|
||||
result[resultColumn + size * resultRow] =
|
||||
vector1[resultRow] * transposeVector2[resultColumn];
|
||||
}
|
||||
}
|
||||
/*matrixSun[i][j] = sunEstB[i] * sunEstB[j];
|
||||
matrixMag[i][j] = magEstB[i] * magEstB[j];
|
||||
matrixSunMag[i][j] = sunEstB[i] * magEstB[j];
|
||||
matrixMagSun[i][j] = magEstB[i] * sunEstB[j];*/
|
||||
}
|
||||
|
||||
static void selectionSort(const T1 *matrix, T1 *result, uint8_t rowSize, uint8_t colSize) {
|
||||
int min_idx;
|
||||
T1 temp;
|
||||
memcpy(result, matrix, rowSize * colSize * sizeof(*result));
|
||||
// One by one move boundary of unsorted subarray
|
||||
for (int k = 0; k < rowSize; k++) {
|
||||
for (int i = 0; i < colSize - 1; i++) {
|
||||
// Find the minimum element in unsorted array
|
||||
min_idx = i;
|
||||
for (int j = i + 1; j < colSize; j++) {
|
||||
if (result[j + k * colSize] < result[min_idx + k * colSize]) {
|
||||
min_idx = j;
|
||||
}
|
||||
}
|
||||
// Swap the found minimum element with the first element
|
||||
temp = result[i + k * colSize];
|
||||
result[i + k * colSize] = result[min_idx + k * colSize];
|
||||
result[min_idx + k * colSize] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void convertDateToJD2000(const T1 time, T2 julianDate) {
|
||||
// time = { Y, M, D, h, m,s}
|
||||
// time in sec and microsec -> The Epoch (unixtime)
|
||||
julianDate = 1721013.5 + 367 * time[0] - floor(7 / 4 * (time[0] + (time[1] + 9) / 12)) +
|
||||
floor(275 * time[1] / 9) + time[2] +
|
||||
(60 * time[3] + time[4] + (time(5) / 60)) / 1440;
|
||||
}
|
||||
|
||||
static T1 convertUnixToJD2000(timeval time) {
|
||||
// time = {{s},{us}}
|
||||
T1 julianDate2000;
|
||||
julianDate2000 = (time.tv_sec / 86400.0) + 2440587.5 - 2451545;
|
||||
return julianDate2000;
|
||||
}
|
||||
|
||||
static void dcmFromQuat(const T1 vector[], T1 *outputDcm) {
|
||||
// convention q = [qx,qy,qz, qw]
|
||||
outputDcm[0] = pow(vector[0], 2) - pow(vector[1], 2) - pow(vector[2], 2) + pow(vector[3], 2);
|
||||
outputDcm[1] = 2 * (vector[0] * vector[1] + vector[2] * vector[3]);
|
||||
outputDcm[2] = 2 * (vector[0] * vector[2] - vector[1] * vector[3]);
|
||||
|
||||
outputDcm[3] = 2 * (vector[1] * vector[0] - vector[2] * vector[3]);
|
||||
outputDcm[4] = -pow(vector[0], 2) + pow(vector[1], 2) - pow(vector[2], 2) + pow(vector[3], 2);
|
||||
outputDcm[5] = 2 * (vector[1] * vector[2] + vector[0] * vector[3]);
|
||||
|
||||
outputDcm[6] = 2 * (vector[2] * vector[0] + vector[1] * vector[3]);
|
||||
outputDcm[7] = 2 * (vector[2] * vector[1] - vector[0] * vector[3]);
|
||||
outputDcm[8] = -pow(vector[0], 2) - pow(vector[1], 2) + pow(vector[2], 2) + pow(vector[3], 2);
|
||||
}
|
||||
|
||||
static void cartesianFromLatLongAlt(const T1 lat, const T1 longi, const T1 alt,
|
||||
T2 *cartesianOutput) {
|
||||
/* @brief: cartesianFromLatLongAlt() - calculates cartesian coordinates in ECEF from latitude,
|
||||
* longitude and altitude
|
||||
* @param: lat geodetic latitude [rad]
|
||||
* longi longitude [rad]
|
||||
* alt altitude [m]
|
||||
* cartesianOutput Cartesian Coordinates in ECEF (3x1)
|
||||
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.34ff
|
||||
* Landis Markley and John L. Crassidis*/
|
||||
double radiusPolar = 6356752.314;
|
||||
double radiusEqua = 6378137;
|
||||
|
||||
double eccentricity = sqrt(1 - pow(radiusPolar, 2) / pow(radiusEqua, 2));
|
||||
double auxRadius = radiusEqua / sqrt(1 - pow(eccentricity, 2) * pow(sin(lat), 2));
|
||||
|
||||
cartesianOutput[0] = (auxRadius + alt) * cos(lat) * cos(longi);
|
||||
cartesianOutput[1] = (auxRadius + alt) * cos(lat) * sin(longi);
|
||||
cartesianOutput[2] = ((1 - pow(eccentricity, 2)) * auxRadius + alt) * sin(lat);
|
||||
}
|
||||
|
||||
static void latLongAltFromCartesian(const T1 *vector, T1 &latitude, T1 &longitude, T1 &altitude) {
|
||||
/* @brief: latLongAltFromCartesian() - calculates latitude, longitude and altitude from
|
||||
* cartesian coordinates in ECEF
|
||||
* @param: x x-value of position vector [m]
|
||||
* y y-value of position vector [m]
|
||||
* z z-value of position vector [m]
|
||||
* latitude geodetic latitude [rad]
|
||||
* longitude longitude [rad]
|
||||
* altitude altitude [m]
|
||||
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.35 f
|
||||
* Landis Markley and John L. Crassidis*/
|
||||
// From World Geodetic System the Earth Radii
|
||||
double a = 6378137.0; // semimajor axis [m]
|
||||
double b = 6356752.3142; // semiminor axis [m]
|
||||
|
||||
// Calculation
|
||||
double e2 = 1 - pow(b, 2) / pow(a, 2);
|
||||
double epsilon2 = pow(a, 2) / pow(b, 2) - 1;
|
||||
double rho = sqrt(pow(vector[0], 2) + pow(vector[1], 2));
|
||||
double p = std::abs(vector[2]) / epsilon2;
|
||||
double s = pow(rho, 2) / (e2 * epsilon2);
|
||||
double q = pow(p, 2) - pow(b, 2) + s;
|
||||
double u = p / sqrt(q);
|
||||
double v = pow(b, 2) * pow(u, 2) / q;
|
||||
double P = 27 * v * s / q;
|
||||
double Q = pow(sqrt(P + 1) + sqrt(P), 2. / 3.);
|
||||
double t = (1 + Q + 1 / Q) / 6;
|
||||
double c = sqrt(pow(u, 2) - 1 + 2 * t);
|
||||
double w = (c - u) / 2;
|
||||
double d =
|
||||
sign(vector[2]) * sqrt(q) * (w + sqrt(sqrt(pow(t, 2) + v) - u * w - t / 2 - 1. / 4.));
|
||||
double N = a * sqrt(1 + epsilon2 * pow(d, 2) / pow(b, 2));
|
||||
latitude = asin((epsilon2 + 1) * d / N);
|
||||
altitude = rho * cos(latitude) + vector[2] * sin(latitude) - pow(a, 2) / N;
|
||||
longitude = atan2(vector[1], vector[0]);
|
||||
}
|
||||
|
||||
static void dcmEJ(timeval time, T1 *outputDcmEJ, T1 *outputDotDcmEJ) {
|
||||
/* @brief: dcmEJ() - calculates the transformation matrix between ECEF and ECI frame
|
||||
* @param: time Current time
|
||||
* outputDcmEJ Transformation matrix from ECI (J) to ECEF (E) [3][3]
|
||||
* outputDotDcmEJ Derivative of transformation matrix [3][3]
|
||||
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.32ff
|
||||
* Landis Markley and John L. Crassidis*/
|
||||
double JD2000Floor = 0;
|
||||
double JD2000 = convertUnixToJD2000(time);
|
||||
// Getting Julian Century from Day start : JD (Y,M,D,0,0,0)
|
||||
JD2000Floor = floor(JD2000);
|
||||
if ((JD2000 - JD2000Floor) < 0.5) {
|
||||
JD2000Floor -= 0.5;
|
||||
} else {
|
||||
JD2000Floor += 0.5;
|
||||
}
|
||||
|
||||
double JC2000 = JD2000Floor / 36525;
|
||||
double sec = (JD2000 - JD2000Floor) * 86400;
|
||||
double gmst = 0; // greenwich mean sidereal time
|
||||
gmst = 24110.54841 + 8640184.812866 * JC2000 + 0.093104 * pow(JC2000, 2) -
|
||||
0.0000062 * pow(JC2000, 3) + 1.002737909350795 * sec;
|
||||
double rest = gmst / 86400;
|
||||
double FloorRest = floor(rest);
|
||||
double secOfDay = rest - FloorRest;
|
||||
secOfDay *= 86400;
|
||||
gmst = secOfDay / 240 * M_PI / 180;
|
||||
|
||||
outputDcmEJ[0] = cos(gmst);
|
||||
outputDcmEJ[1] = sin(gmst);
|
||||
outputDcmEJ[2] = 0;
|
||||
outputDcmEJ[3] = -sin(gmst);
|
||||
outputDcmEJ[4] = cos(gmst);
|
||||
outputDcmEJ[5] = 0;
|
||||
outputDcmEJ[6] = 0;
|
||||
outputDcmEJ[7] = 0;
|
||||
outputDcmEJ[8] = 1;
|
||||
|
||||
// Derivative of dmcEJ WITHOUT PRECISSION AND NUTATION
|
||||
double dcmEJCalc[3][3] = {{outputDcmEJ[0], outputDcmEJ[1], outputDcmEJ[2]},
|
||||
{outputDcmEJ[3], outputDcmEJ[4], outputDcmEJ[5]},
|
||||
{outputDcmEJ[6], outputDcmEJ[7], outputDcmEJ[8]}};
|
||||
double dcmDot[3][3] = {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0}};
|
||||
double omegaEarth = 0.000072921158553;
|
||||
double dotDcmEJ[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MatrixOperations<double>::multiply(*dcmDot, *dcmEJCalc, *dotDcmEJ, 3, 3, 3);
|
||||
MatrixOperations<double>::multiplyScalar(*dotDcmEJ, omegaEarth, outputDotDcmEJ, 3, 3);
|
||||
}
|
||||
|
||||
/* @brief: ecfToEciWithNutPre() - calculates the transformation matrix between ECEF and ECI frame
|
||||
* give also the back the derivative of this matrix
|
||||
* @param: unixTime Current time in Unix format
|
||||
* outputDcmEJ Transformation matrix from ECI (J) to ECEF (E) [3][3]
|
||||
* outputDotDcmEJ Derivative of transformation matrix [3][3]
|
||||
* @source: Entwicklung einer Simulationsumgebung und robuster Algorithmen für das Lage- und
|
||||
Orbitkontrollsystem der Kleinsatelliten Flying Laptop und PERSEUS, P.244ff
|
||||
* Oliver Zeile
|
||||
*
|
||||
https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_Studenten/Marquardt_Robin&openfile=896110*/
|
||||
static void ecfToEciWithNutPre(timeval unixTime, T1 *outputDcmEJ, T1 *outputDotDcmEJ) {
|
||||
// TT = UTC/Unix + 32.184s (TAI Difference) + 27 (Leap Seconds in UTC since 1972) + 10
|
||||
//(initial Offset) International Atomic Time (TAI)
|
||||
|
||||
double JD2000UTC1 = convertUnixToJD2000(unixTime);
|
||||
|
||||
// Julian Date / century from TT
|
||||
timeval terestrialTime = unixTime;
|
||||
terestrialTime.tv_sec = unixTime.tv_sec + 32.184 + 37;
|
||||
double JD2000TT = convertUnixToJD2000(terestrialTime);
|
||||
double JC2000TT = JD2000TT / 36525;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of Transformation from earth rotation Theta
|
||||
//-------------------------------------------------------------------------------------
|
||||
double theta[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
// Earth Rotation angle
|
||||
double era = 0;
|
||||
era = 2 * M_PI * (0.779057273264 + 1.00273781191135448 * JD2000UTC1);
|
||||
// Greenwich Mean Sidereal Time
|
||||
double gmst2000 = 0.014506 + 4612.15739966 * JC2000TT + 1.39667721 * pow(JC2000TT, 2) -
|
||||
0.00009344 * pow(JC2000TT, 3) + 0.00001882 * pow(JC2000TT, 4);
|
||||
double arcsecFactor = 1 * M_PI / (180 * 3600);
|
||||
gmst2000 *= arcsecFactor;
|
||||
gmst2000 += era;
|
||||
|
||||
theta[0][0] = cos(gmst2000);
|
||||
theta[0][1] = sin(gmst2000);
|
||||
theta[0][2] = 0;
|
||||
theta[1][0] = -sin(gmst2000);
|
||||
theta[1][1] = cos(gmst2000);
|
||||
theta[1][2] = 0;
|
||||
theta[2][0] = 0;
|
||||
theta[2][1] = 0;
|
||||
theta[2][2] = 1;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of Transformation from earth Precession P
|
||||
//-------------------------------------------------------------------------------------
|
||||
double precession[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
|
||||
double zeta = 2306.2181 * JC2000TT + 0.30188 * pow(JC2000TT, 2) + 0.017998 * pow(JC2000TT, 3);
|
||||
double theta2 = 2004.3109 * JC2000TT - 0.42665 * pow(JC2000TT, 2) - 0.041833 * pow(JC2000TT, 3);
|
||||
double ze = zeta + 0.79280 * pow(JC2000TT, 2) + 0.000205 * pow(JC2000TT, 3);
|
||||
|
||||
zeta *= arcsecFactor;
|
||||
theta2 *= arcsecFactor;
|
||||
ze *= arcsecFactor;
|
||||
|
||||
precession[0][0] = -sin(ze) * sin(zeta) + cos(ze) * cos(theta2) * cos(zeta);
|
||||
precession[1][0] = cos(ze) * sin(zeta) + sin(ze) * cos(theta2) * cos(zeta);
|
||||
precession[2][0] = sin(theta2) * cos(zeta);
|
||||
precession[0][1] = -sin(ze) * cos(zeta) - cos(ze) * cos(theta2) * sin(zeta);
|
||||
precession[1][1] = cos(ze) * cos(zeta) - sin(ze) * cos(theta2) * sin(zeta);
|
||||
precession[2][1] = -sin(theta2) * sin(zeta);
|
||||
precession[0][2] = -cos(ze) * sin(theta2);
|
||||
precession[1][2] = -sin(ze) * sin(theta2);
|
||||
precession[2][2] = cos(theta2);
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of Transformation from earth Nutation N
|
||||
//-------------------------------------------------------------------------------------
|
||||
double nutation[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
// lunar asc node
|
||||
double Om = 125 * 3600 + 2 * 60 + 40.28 - (1934 * 3600 + 8 * 60 + 10.539) * JC2000TT +
|
||||
7.455 * pow(JC2000TT, 2) + 0.008 * pow(JC2000TT, 3);
|
||||
Om *= arcsecFactor;
|
||||
// delta psi approx
|
||||
double dp = -17.2 * arcsecFactor * sin(Om);
|
||||
|
||||
// delta eps approx
|
||||
double de = 9.203 * arcsecFactor * cos(Om);
|
||||
|
||||
// % true obliquity of the ecliptic eps p.71 (simplified)
|
||||
double e = 23.43929111 * M_PI / 180 - 46.8150 / 3600 * JC2000TT * M_PI / 180;
|
||||
|
||||
nutation[0][0] = cos(dp);
|
||||
nutation[1][0] = cos(e + de) * sin(dp);
|
||||
nutation[2][0] = sin(e + de) * sin(dp);
|
||||
nutation[0][1] = -cos(e) * sin(dp);
|
||||
nutation[1][1] = cos(e) * cos(e + de) * cos(dp) + sin(e) * sin(e + de);
|
||||
nutation[2][1] = cos(e) * sin(e + de) * cos(dp) - sin(e) * cos(e + de);
|
||||
nutation[0][2] = -sin(e) * sin(dp);
|
||||
nutation[1][2] = sin(e) * cos(e + de) * cos(dp) - cos(e) * sin(e + de);
|
||||
nutation[2][2] = sin(e) * sin(e + de) * cos(dp) + cos(e) * cos(e + de);
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of Derivative of rotation matrix from earth
|
||||
//-------------------------------------------------------------------------------------
|
||||
double thetaDot[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
double dotMatrix[3][3] = {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0}};
|
||||
double omegaEarth = 0.000072921158553;
|
||||
MatrixOperations<double>::multiply(*dotMatrix, *theta, *thetaDot, 3, 3, 3);
|
||||
MatrixOperations<double>::multiplyScalar(*thetaDot, omegaEarth, *thetaDot, 3, 3);
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Calculation of transformation matrix and Derivative of transformation matrix
|
||||
//-------------------------------------------------------------------------------------
|
||||
double nutationPrecession[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MatrixOperations<double>::multiply(*nutation, *precession, *nutationPrecession, 3, 3, 3);
|
||||
MatrixOperations<double>::multiply(*nutationPrecession, *theta, outputDcmEJ, 3, 3, 3);
|
||||
|
||||
MatrixOperations<double>::multiply(*nutationPrecession, *thetaDot, outputDotDcmEJ, 3, 3, 3);
|
||||
}
|
||||
static void inverseMatrixDimThree(const T1 *matrix, T1 *output) {
|
||||
int i, j;
|
||||
double determinant = 0;
|
||||
double mat[3][3] = {{matrix[0], matrix[1], matrix[2]},
|
||||
{matrix[3], matrix[4], matrix[5]},
|
||||
{matrix[6], matrix[7], matrix[8]}};
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
determinant = determinant + (mat[0][i] * (mat[1][(i + 1) % 3] * mat[2][(i + 2) % 3] -
|
||||
mat[1][(i + 2) % 3] * mat[2][(i + 1) % 3]));
|
||||
}
|
||||
// cout<<"\n\ndeterminant: "<<determinant;
|
||||
// cout<<"\n\nInverse of matrix is: \n";
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
output[i * 3 + j] = ((mat[(j + 1) % 3][(i + 1) % 3] * mat[(j + 2) % 3][(i + 2) % 3]) -
|
||||
(mat[(j + 1) % 3][(i + 2) % 3] * mat[(j + 2) % 3][(i + 1) % 3])) /
|
||||
determinant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float matrixDeterminant(const T1 *inputMatrix, uint8_t size) {
|
||||
/* do not use this. takes 300ms */
|
||||
float det = 0;
|
||||
T1 matrix[size][size], submatrix[size - 1][size - 1];
|
||||
for (uint8_t row = 0; row < size; row++) {
|
||||
for (uint8_t col = 0; col < size; col++) {
|
||||
matrix[row][col] = inputMatrix[row * size + col];
|
||||
}
|
||||
}
|
||||
if (size == 2)
|
||||
return ((matrix[0][0] * matrix[1][1]) - (matrix[1][0] * matrix[0][1]));
|
||||
else {
|
||||
for (uint8_t col = 0; col < size; col++) {
|
||||
int subRow = 0;
|
||||
for (uint8_t rowIndex = 1; rowIndex < size; rowIndex++) {
|
||||
int subCol = 0;
|
||||
for (uint8_t colIndex = 0; colIndex < size; colIndex++) {
|
||||
if (colIndex == col) continue;
|
||||
submatrix[subRow][subCol] = matrix[rowIndex][colIndex];
|
||||
subCol++;
|
||||
}
|
||||
subRow++;
|
||||
}
|
||||
det += (pow(-1, col) * matrix[0][col] *
|
||||
MathOperations<T1>::matrixDeterminant(*submatrix, size - 1));
|
||||
}
|
||||
}
|
||||
return det;
|
||||
}
|
||||
|
||||
static int inverseMatrix(const T1 *inputMatrix, T1 *inverse, uint8_t size) {
|
||||
// Stopwatch stopwatch;
|
||||
T1 matrix[size][size], identity[size][size];
|
||||
// reformat array to matrix
|
||||
for (uint8_t row = 0; row < size; row++) {
|
||||
for (uint8_t col = 0; col < size; col++) {
|
||||
matrix[row][col] = inputMatrix[row * size + col];
|
||||
}
|
||||
}
|
||||
// init identity matrix
|
||||
std::memset(identity, 0.0, sizeof(identity));
|
||||
for (uint8_t diag = 0; diag < size; diag++) {
|
||||
identity[diag][diag] = 1;
|
||||
}
|
||||
// gauss-jordan algo
|
||||
// sort matrix such as no diag entry shall be 0
|
||||
for (uint8_t row = 0; row < size; row++) {
|
||||
if (matrix[row][row] == 0.0) {
|
||||
bool swaped = false;
|
||||
uint8_t rowIndex = 0;
|
||||
while ((rowIndex < size) && !swaped) {
|
||||
if ((matrix[rowIndex][row] != 0.0) && (matrix[row][rowIndex] != 0.0)) {
|
||||
for (uint8_t colIndex = 0; colIndex < size; colIndex++) {
|
||||
std::swap(matrix[row][colIndex], matrix[rowIndex][colIndex]);
|
||||
std::swap(identity[row][colIndex], identity[rowIndex][colIndex]);
|
||||
}
|
||||
swaped = true;
|
||||
}
|
||||
rowIndex++;
|
||||
}
|
||||
if (!swaped) {
|
||||
return 1; // matrix not invertible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int row = 0; row < size; row++) {
|
||||
if (matrix[row][row] == 0.0) {
|
||||
uint8_t rowIndex;
|
||||
if (row == 0) {
|
||||
rowIndex = size - 1;
|
||||
} else {
|
||||
rowIndex = row - 1;
|
||||
}
|
||||
for (uint8_t colIndex = 0; colIndex < size; colIndex++) {
|
||||
std::swap(matrix[row][colIndex], matrix[rowIndex][colIndex]);
|
||||
std::swap(identity[row][colIndex], identity[rowIndex][colIndex]);
|
||||
}
|
||||
row--;
|
||||
if (row < 0) {
|
||||
return 1; // Matrix is not invertible
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove non diag elements in matrix (jordan)
|
||||
for (int row = 0; row < size; row++) {
|
||||
for (int rowIndex = 0; rowIndex < size; rowIndex++) {
|
||||
if (row != rowIndex) {
|
||||
double ratio = matrix[rowIndex][row] / matrix[row][row];
|
||||
for (int colIndex = 0; colIndex < size; colIndex++) {
|
||||
matrix[rowIndex][colIndex] -= ratio * matrix[row][colIndex];
|
||||
identity[rowIndex][colIndex] -= ratio * identity[row][colIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// normalize rows in matrix (gauss)
|
||||
for (int row = 0; row < size; row++) {
|
||||
for (int col = 0; col < size; col++) {
|
||||
identity[row][col] = identity[row][col] / matrix[row][row];
|
||||
}
|
||||
}
|
||||
std::memcpy(inverse, identity, sizeof(identity));
|
||||
return 0; // successful inversion
|
||||
}
|
||||
|
||||
static bool checkVectorIsFinite(const T1 *inputVector, uint8_t size) {
|
||||
for (uint8_t i = 0; i < size; i++) {
|
||||
if (not isfinite(inputVector[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool checkMatrixIsFinite(const T1 *inputMatrix, uint8_t rows, uint8_t cols) {
|
||||
for (uint8_t col = 0; col < cols; col++) {
|
||||
for (uint8_t row = 0; row < rows; row++) {
|
||||
if (not isfinite(inputMatrix[row * cols + cols])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ACS_MATH_MATHOPERATIONS_H_ */
|
@ -1,6 +1,7 @@
|
||||
#ifndef MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_
|
||||
#define MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_
|
||||
|
||||
#include <common/config/eive/resultClassIds.h>
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/datapoollocal/localPoolDefinitions.h>
|
||||
|
||||
@ -8,6 +9,25 @@
|
||||
|
||||
namespace acsctrl {
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_CTRL;
|
||||
//! [EXPORT] : [COMMENT] File deletion failed and at least one file is still existent.
|
||||
static constexpr ReturnValue_t FILE_DELETION_FAILED = MAKE_RETURN_CODE(0xA0);
|
||||
//! [EXPORT] : [COMMENT] Writing the TLE to the file has failed.
|
||||
static constexpr ReturnValue_t WRITE_FILE_FAILED = MAKE_RETURN_CODE(0xA1);
|
||||
//! [EXPORT] : [COMMENT] Reading the TLE to the file has failed.
|
||||
static constexpr ReturnValue_t READ_FILE_FAILED = MAKE_RETURN_CODE(0xA2);
|
||||
//! [EXPORT] : [COMMENT] A single RW has failed.
|
||||
static constexpr ReturnValue_t SINGLE_RW_UNAVAILABLE = MAKE_RETURN_CODE(0xA3);
|
||||
//! [EXPORT] : [COMMENT] Multiple RWs have failed.
|
||||
static constexpr ReturnValue_t MULTIPLE_RW_UNAVAILABLE = MAKE_RETURN_CODE(0xA4);
|
||||
|
||||
struct RwAvail {
|
||||
bool rw1avail = false;
|
||||
bool rw2avail = false;
|
||||
bool rw3avail = false;
|
||||
bool rw4avail = false;
|
||||
};
|
||||
|
||||
enum SetIds : uint32_t {
|
||||
MGM_SENSOR_DATA,
|
||||
MGM_PROCESSED_DATA,
|
||||
@ -20,6 +40,7 @@ enum SetIds : uint32_t {
|
||||
CTRL_VAL_DATA,
|
||||
ACTUATOR_CMD_DATA,
|
||||
FUSED_ROTATION_RATE_DATA,
|
||||
FUSED_ROTATION_RATE_SOURCES_DATA,
|
||||
TLE_SET,
|
||||
};
|
||||
|
||||
@ -96,6 +117,7 @@ enum PoolIds : lp_id_t {
|
||||
SAT_ROT_RATE_MEKF,
|
||||
QUAT_MEKF,
|
||||
MEKF_STATUS,
|
||||
QUAT_QUEST,
|
||||
// Ctrl Values
|
||||
SAFE_STRAT,
|
||||
TGT_QUAT,
|
||||
@ -107,12 +129,15 @@ enum PoolIds : lp_id_t {
|
||||
RW_TARGET_SPEED,
|
||||
MTQ_TARGET_DIPOLE,
|
||||
// Fused Rotation Rate
|
||||
ROT_RATE_ORTHOGONAL,
|
||||
ROT_RATE_PARALLEL,
|
||||
ROT_RATE_TOTAL,
|
||||
// TLE
|
||||
TLE_LINE_1,
|
||||
TLE_LINE_2,
|
||||
ROT_RATE_TOT_SUSMGM,
|
||||
ROT_RATE_TOT_SOURCE,
|
||||
ROT_RATE_SOURCE,
|
||||
// Fused Rotation Rate Sources
|
||||
ROT_RATE_ORTHOGONAL_SUSMGM,
|
||||
ROT_RATE_PARALLEL_SUSMGM,
|
||||
ROT_RATE_TOTAL_SUSMGM,
|
||||
ROT_RATE_TOTAL_QUEST,
|
||||
ROT_RATE_TOTAL_STR,
|
||||
};
|
||||
|
||||
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
|
||||
@ -122,11 +147,11 @@ static constexpr uint8_t SUS_SET_PROCESSED_ENTRIES = 15;
|
||||
static constexpr uint8_t GYR_SET_RAW_ENTRIES = 4;
|
||||
static constexpr uint8_t GYR_SET_PROCESSED_ENTRIES = 5;
|
||||
static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 6;
|
||||
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t ATTITUDE_ESTIMATION_SET_ENTRIES = 4;
|
||||
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
|
||||
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t FUSED_ROT_RATE_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t TLE_SET_ENTRIES = 2;
|
||||
static constexpr uint8_t FUSED_ROT_RATE_SOURCES_SET_ENTRIES = 5;
|
||||
|
||||
/**
|
||||
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
|
||||
@ -250,13 +275,14 @@ class GpsDataProcessed : public StaticLocalDataSet<GPS_SET_PROCESSED_ENTRIES> {
|
||||
private:
|
||||
};
|
||||
|
||||
class MekfData : public StaticLocalDataSet<MEKF_SET_ENTRIES> {
|
||||
class AttitudeEstimationData : public StaticLocalDataSet<ATTITUDE_ESTIMATION_SET_ENTRIES> {
|
||||
public:
|
||||
MekfData(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, MEKF_DATA) {}
|
||||
AttitudeEstimationData(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, MEKF_DATA) {}
|
||||
|
||||
lp_vec_t<double, 4> quatMekf = lp_vec_t<double, 4>(sid.objectId, QUAT_MEKF, this);
|
||||
lp_vec_t<double, 3> satRotRateMekf = lp_vec_t<double, 3>(sid.objectId, SAT_ROT_RATE_MEKF, this);
|
||||
lp_var_t<uint8_t> mekfStatus = lp_var_t<uint8_t>(sid.objectId, MEKF_STATUS, this);
|
||||
lp_vec_t<double, 4> quatQuest = lp_vec_t<double, 4>(sid.objectId, QUAT_MEKF, this);
|
||||
|
||||
private:
|
||||
};
|
||||
@ -291,20 +317,29 @@ class FusedRotRateData : public StaticLocalDataSet<FUSED_ROT_RATE_SET_ENTRIES> {
|
||||
FusedRotRateData(HasLocalDataPoolIF* hkOwner)
|
||||
: StaticLocalDataSet(hkOwner, FUSED_ROTATION_RATE_DATA) {}
|
||||
|
||||
lp_vec_t<double, 3> rotRateOrthogonal =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_ORTHOGONAL, this);
|
||||
lp_vec_t<double, 3> rotRateParallel = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_PARALLEL, this);
|
||||
lp_vec_t<double, 3> rotRateTotal = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL, this);
|
||||
lp_vec_t<double, 3> rotRateTotalSusMgm =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOT_SUSMGM, this);
|
||||
lp_vec_t<double, 3> rotRateTotalSource =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOT_SOURCE, this);
|
||||
lp_var_t<uint8_t> rotRateSource = lp_var_t<uint8_t>(sid.objectId, ROT_RATE_SOURCE, this);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class TleData : public StaticLocalDataSet<TLE_SET_ENTRIES> {
|
||||
class FusedRotRateSourcesData : public StaticLocalDataSet<FUSED_ROT_RATE_SOURCES_SET_ENTRIES> {
|
||||
public:
|
||||
TleData(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, TLE_SET) {}
|
||||
FusedRotRateSourcesData(HasLocalDataPoolIF* hkOwner)
|
||||
: StaticLocalDataSet(hkOwner, FUSED_ROTATION_RATE_SOURCES_DATA) {}
|
||||
|
||||
lp_vec_t<uint8_t, 69> line1 = lp_vec_t<uint8_t, 69>(sid.objectId, TLE_LINE_1, this);
|
||||
lp_vec_t<uint8_t, 69> line2 = lp_vec_t<uint8_t, 69>(sid.objectId, TLE_LINE_1, this);
|
||||
lp_vec_t<double, 3> rotRateOrthogonalSusMgm =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_ORTHOGONAL_SUSMGM, this);
|
||||
lp_vec_t<double, 3> rotRateParallelSusMgm =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_PARALLEL_SUSMGM, this);
|
||||
lp_vec_t<double, 3> rotRateTotalSusMgm =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL_SUSMGM, this);
|
||||
lp_vec_t<double, 3> rotRateTotalQuest =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL_QUEST, this);
|
||||
lp_vec_t<double, 3> rotRateTotalStr = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL_STR, this);
|
||||
|
||||
private:
|
||||
};
|
||||
|
@ -250,20 +250,30 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
||||
pus::PUS_SERVICE_2, 3, 10);
|
||||
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, config::EIVE_PUS_APID,
|
||||
pus::PUS_SERVICE_3, config::HK_SERVICE_QUEUE_DEPTH, 16);
|
||||
new Service5EventReporting(
|
||||
PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING, config::EIVE_PUS_APID, pus::PUS_SERVICE_5),
|
||||
80, 160);
|
||||
|
||||
auto psbParamsService5 =
|
||||
PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING, config::EIVE_PUS_APID, pus::PUS_SERVICE_5);
|
||||
psbParamsService5.requestQueueDepth = 50;
|
||||
psbParamsService5.maxPacketsPerCycle = 50;
|
||||
new Service5EventReporting(psbParamsService5, 80, 160);
|
||||
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, config::EIVE_PUS_APID,
|
||||
pus::PUS_SERVICE_8, config::ACTION_SERVICE_QUEUE_DEPTH, 16, 60);
|
||||
new Service9TimeManagement(
|
||||
PsbParams(objects::PUS_SERVICE_9_TIME_MGMT, config::EIVE_PUS_APID, pus::PUS_SERVICE_9));
|
||||
|
||||
new Service11TelecommandScheduling<common::OBSW_MAX_SCHEDULED_TCS>(
|
||||
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, config::EIVE_PUS_APID, pus::PUS_SERVICE_11),
|
||||
auto psbParamsService11 =
|
||||
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, config::EIVE_PUS_APID, pus::PUS_SERVICE_11);
|
||||
psbParamsService11.requestQueueDepth = 100;
|
||||
psbParamsService11.maxPacketsPerCycle = 100;
|
||||
new Service11TelecommandScheduling<common::OBSW_MAX_SCHEDULED_TCS>(psbParamsService11,
|
||||
ccsdsDistrib);
|
||||
|
||||
new Service15TmStorage(objects::PUS_SERVICE_15_TM_STORAGE, config::EIVE_PUS_APID, 10);
|
||||
new Service17Test(
|
||||
PsbParams(objects::PUS_SERVICE_17_TEST, config::EIVE_PUS_APID, pus::PUS_SERVICE_17));
|
||||
auto psbParamsService17 =
|
||||
PsbParams(objects::PUS_SERVICE_17_TEST, config::EIVE_PUS_APID, pus::PUS_SERVICE_17);
|
||||
psbParamsService17.requestQueueDepth = 50;
|
||||
psbParamsService17.maxPacketsPerCycle = 50;
|
||||
new Service17Test(psbParamsService17);
|
||||
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, config::EIVE_PUS_APID,
|
||||
pus::PUS_SERVICE_20);
|
||||
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, config::EIVE_PUS_APID,
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "OBSWConfig.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "eive/objects.h"
|
||||
#include "linux/payload/FreshMpsocHandler.h"
|
||||
#include "linux/payload/FreshSupvHandler.h"
|
||||
|
||||
#ifndef RPI_TEST_ADIS16507
|
||||
@ -617,17 +618,21 @@ ReturnValue_t pst::pstPayload(FixedTimeslotTaskIF *thisSequence) {
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0,
|
||||
FreshSupvHandler::OpCode::DEFAULT_OPERATION);
|
||||
// Two COM TM steps, which might cover telemetry which takes a bit longer to be sent.
|
||||
// Parse TM with a bit of delay. Two COM steps which might cover telemetry wehich takes a bit
|
||||
// longer to send
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.1,
|
||||
FreshSupvHandler::OpCode::PARSE_TM);
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2,
|
||||
FreshSupvHandler::OpCode::PARSE_TM);
|
||||
// Parse TM with a bit of delay. Two COM steps which might cover telemetry wehich takes a bit
|
||||
// longer to send
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.2,
|
||||
FreshMpsocHandler::OpCode::PARSE_TM);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.4,
|
||||
FreshMpsocHandler::OpCode::PARSE_TM);
|
||||
|
||||
thisSequence->addSlot(objects::SCEX, length * 0.6, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SCEX, length * 0.6, DeviceHandlerIF::SEND_WRITE);
|
||||
|
@ -65,8 +65,8 @@ ReturnValue_t PcduHandler::performOperation(uint8_t counter) {
|
||||
ReturnValue_t PcduHandler::initialize() {
|
||||
ReturnValue_t result;
|
||||
|
||||
IPCStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (IPCStore == nullptr) {
|
||||
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == nullptr) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
@ -162,10 +162,13 @@ void PcduHandler::updateHkTableDataset(store_address_t storeId, LocalPoolDataSet
|
||||
sizeof(CCSDSTime::CDS_short), dataset);
|
||||
const uint8_t* packet_ptr = nullptr;
|
||||
size_t size = 0;
|
||||
result = IPCStore->getData(storeId, &packet_ptr, &size);
|
||||
result = ipcStore->getData(storeId, &packet_ptr, &size);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PCDUHandler::updateHkTableDataset: Failed to get data from IPCStore."
|
||||
<< std::endl;
|
||||
sif::error << "PCDUHandler::updateHkTableDataset: Failed to get data from IPC store, result 0x"
|
||||
<< std::hex << std::setw(4) << std::setfill('0') << result << std::dec
|
||||
<< std::setfill(' ') << std::endl;
|
||||
result = ipcStore->deleteData(storeId);
|
||||
return;
|
||||
}
|
||||
result = packetUpdate.deSerialize(&packet_ptr, &size, SerializeIF::Endianness::MACHINE);
|
||||
if (result != returnvalue::OK) {
|
||||
@ -173,7 +176,7 @@ void PcduHandler::updateHkTableDataset(store_address_t storeId, LocalPoolDataSet
|
||||
"in hk table dataset"
|
||||
<< std::endl;
|
||||
}
|
||||
result = IPCStore->deleteData(storeId);
|
||||
result = ipcStore->deleteData(storeId);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PCDUHandler::updateHkTableDataset: Failed to delete data in IPCStore"
|
||||
<< std::endl;
|
||||
@ -396,7 +399,7 @@ ReturnValue_t PcduHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onO
|
||||
setParamMessage.serialize(&commandPtr, &serializedLength, maxSize, SerializeIF::Endianness::BIG);
|
||||
|
||||
store_address_t storeAddress;
|
||||
result = IPCStore->addData(&storeAddress, command, sizeof(command));
|
||||
result = ipcStore->addData(&storeAddress, command, sizeof(command));
|
||||
|
||||
CommandMessage message;
|
||||
ActionMessage::setCommand(&message, GOMSPACE::PARAM_SET, storeAddress);
|
||||
|
@ -94,7 +94,7 @@ class PcduHandler : public PowerSwitchIF,
|
||||
* Pointer to the IPCStore.
|
||||
* This caches the pointer received from the objectManager in the constructor.
|
||||
*/
|
||||
StorageManagerIF* IPCStore = nullptr;
|
||||
StorageManagerIF* ipcStore = nullptr;
|
||||
|
||||
/**
|
||||
* Message queue to communicate with other objetcs. Used for example to receive
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user