@@ -77,7 +77,6 @@ def __init__(self, idx, dof):
77
77
self .idx = idx
78
78
self .dof = dof
79
79
80
- # TODO: remove dof, all dofs are one here.
81
80
def BuildTangentStateIndex ():
82
81
tangent_state_index = {}
83
82
idx = 0
@@ -98,37 +97,80 @@ class MState(sf.Matrix):
98
97
class VMeas (sf .Matrix ):
99
98
SHAPE = (1 , State .storage_dim ())
100
99
101
- def get_Phi_G (dt : sf .Scalar ) -> T .Tuple [sf .Matrix , sf .Matrix ]:
100
+
101
+ def get_Phi (dt : sf .Scalar ) -> sf .Matrix :
102
+ n = State .storage_dim ()
103
+ Phi = sf .Matrix .zeros (State .storage_dim (), State .storage_dim ())
104
+
105
+ # Helper functions to set blocks in Phi matrix
106
+ def set_Phi_block (row_key , col_key , value ):
107
+ idx_row = tangent_idx [row_key ].idx
108
+ dof_row = tangent_idx [row_key ].dof
109
+ idx_col = tangent_idx [col_key ].idx
110
+ dof_col = tangent_idx [col_key ].dof
111
+ if isinstance (value , sf .Matrix ):
112
+ # Ensure the value matrix has the correct shape
113
+ assert value .shape == (dof_row , dof_col ), "Value matrix shape mismatch"
114
+ Phi [idx_row :idx_row + dof_row , idx_col :idx_col + dof_col ] = value
115
+ else :
116
+ # Scalar value; create a block matrix
117
+ block = value * sf .Matrix .eye (dof_row , dof_col )
118
+ Phi [idx_row :idx_row + dof_row , idx_col :idx_col + dof_col ] = block
119
+
120
+ # Set the diagonal elements of Phi to 1
121
+ for key in State .keys_recursive ():
122
+ idx = tangent_idx [key ].idx
123
+ dof = tangent_idx [key ].dof
124
+ for i in range (dof ):
125
+ Phi [idx + i , idx + i ] = 1
126
+
127
+ set_Phi_block ('pos_rel' , 'vel_uav' , - dt )
128
+
102
129
if moving :
103
- Phi = sf .Matrix ([
104
- [1 , - dt , 0 , 0.5 * dt * dt , dt ],
105
- [0 , 1 , 0 , 0 , 0 ],
106
- [0 , 0 , 1 , 0 , 0 ],
107
- [0 , 0 , 0 , 1 , 0 ],
108
- [0 , 0 , 0 , dt , 1 ],
109
- ])
110
- G = sf .Matrix ([[- 0.5 * dt * dt ], [dt ], [0 ], [0 ], [0 ]])
111
- else :
112
- Phi = sf .Matrix ([
113
- [1 , - dt , 0 ],
114
- [0 , 1 , 0 ],
115
- [0 , 0 , 1 ]
116
- ])
117
- G = sf .Matrix ([[- 0.5 * dt * dt ], [dt ], [0 ]])
118
- return Phi , G
130
+ # Update Phi with off-diagonal elements for the moving filter
131
+ set_Phi_block ('pos_rel' , 'acc_target' , 0.5 * dt * dt )
132
+ set_Phi_block ('pos_rel' , 'vel_target' , dt )
133
+ set_Phi_block ('vel_target' , 'acc_target' , dt )
134
+
135
+ return Phi
136
+
137
+
138
+ def get_G (dt : sf .Scalar ) -> sf .Matrix :
139
+ G = sf .Matrix .zeros (State .storage_dim (), 1 )
140
+
141
+ # Helper functions to set blocks in G matrix
142
+ def set_G_block (key , value ):
143
+ idx = tangent_idx [key ].idx
144
+ dof = tangent_idx [key ].dof
145
+ if isinstance (value , sf .Matrix ):
146
+ # Ensure the value vector has the correct shape
147
+ assert value .shape == (dof , 1 ), "Value vector shape mismatch"
148
+ G [idx :idx + dof , 0 ] = value
149
+ else :
150
+ # Scalar value; create a vector
151
+ block = sf .Matrix ([value ] * dof )
152
+ G [idx :idx + dof , 0 ] = block
153
+
154
+ # Update G with the process noise terms
155
+ set_G_block ('pos_rel' , - 0.5 * dt * dt )
156
+ set_G_block ('vel_uav' , dt )
157
+
158
+ return G
119
159
120
160
def predictState (dt : sf .Scalar , state : VState , acc : sf .Scalar ) -> VState :
121
- Phi , G = get_Phi_G (dt )
161
+ Phi = get_Phi (dt )
162
+ G = get_G (dt )
122
163
return Phi * state + G * acc
123
164
124
165
def syncState (dt : sf .Scalar , state : VState , acc : sf .Scalar ) -> VState :
125
- Phi , G = get_Phi_G (dt )
166
+ Phi = get_Phi (dt )
167
+ G = get_G (dt )
126
168
return Phi .inv () * (state - G * acc )
127
169
128
170
def predictCov (dt : sf .Scalar , input_var : sf .Scalar , bias_var : sf .Scalar , acc_var : sf .Scalar , covariance : MState ) -> MState :
129
- Phi , G = get_Phi_G (dt )
130
- n = State . storage_dim ( )
131
- Q = sf .Matrix .zeros (n , n )
171
+ Phi = get_Phi (dt )
172
+ G = get_G ( dt )
173
+ Q = sf .Matrix .zeros (State . storage_dim (), State . storage_dim () )
132
174
133
175
idx_bias = tangent_idx ['bias' ].idx
134
176
Q [idx_bias , idx_bias ] = bias_var
0 commit comments