Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit 770cd3c

Browse files
RomanBapstpriseborough
authored andcommitted
added python script for terrain flow derivation (optical flow for terrain
height estimation) Signed-off-by: Roman <[email protected]>
1 parent c085d72 commit 770cd3c

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""
2+
3+
This script calculates the observation scalars (H matrix) for fusing optical flow
4+
measurements for terrain estimation.
5+
6+
@author: roman
7+
"""
8+
9+
from sympy import *
10+
11+
# q: quaternion describing rotation from frame 1 to frame 2
12+
# returns a rotation matrix derived form q which describes the same
13+
# rotation
14+
def quat2Rot(q):
15+
q0 = q[0]
16+
q1 = q[1]
17+
q2 = q[2]
18+
q3 = q[3]
19+
20+
Rot = Matrix([[q0**2 + q1**2 - q2**2 - q3**2, 2*(q1*q2 - q0*q3), 2*(q1*q3 + q0*q2)],
21+
[2*(q1*q2 + q0*q3), q0**2 - q1**2 + q2**2 - q3**2, 2*(q2*q3 - q0*q1)],
22+
[2*(q1*q3-q0*q2), 2*(q2*q3 + q0*q1), q0**2 - q1**2 - q2**2 + q3**2]])
23+
24+
return Rot
25+
26+
# take an expression calculated by the cse() method and write the expression
27+
# into a text file in C format
28+
def write_simplified(P_touple, filename, out_name):
29+
subs = P_touple[0]
30+
P = Matrix(P_touple[1])
31+
fd = open(filename, 'a')
32+
33+
is_vector = P.shape[0] == 1 or P.shape[1] == 1
34+
35+
# write sub expressions
36+
for index, item in enumerate(subs):
37+
fd.write('float ' + str(item[0]) + ' = ' + str(item[1]) + ';\n')
38+
39+
# write actual matrix values
40+
fd.write('\n')
41+
42+
if not is_vector:
43+
iterator = range(0,sqrt(len(P)), 1)
44+
for row in iterator:
45+
for column in iterator:
46+
fd.write(out_name + '(' + str(row) + ',' + str(column) + ') = ' + str(P[row, column]) + ';\n')
47+
else:
48+
iterator = range(0, len(P), 1)
49+
50+
for item in iterator:
51+
fd.write(out_name + '(' + str(item) + ') = ' + str(P[item]) + ';\n')
52+
53+
fd.write('\n\n')
54+
fd.close()
55+
56+
########## Symbolic variable definition #######################################
57+
58+
59+
# vehicle velocity
60+
v_x = Symbol("v_x", real=True) # vehicle body x velocity
61+
v_y = Symbol("v_y", real=True) # vehicle body y velocity
62+
63+
# unit quaternion describing vehicle attitude, qw is real part
64+
qw = Symbol("q0", real=True)
65+
qx = Symbol("q1", real=True)
66+
qy = Symbol("q2", real=True)
67+
qz = Symbol("q3", real=True)
68+
q_att = Matrix([qw, qx, qy, qz])
69+
70+
# terrain vertial position in local NED frame
71+
_terrain_vpos = Symbol("_terrain_vpos", real=True)
72+
73+
_terrain_var = Symbol("_terrain_var", real=True)
74+
75+
# vehicle vertical position in local NED frame
76+
pos_z = Symbol("z", real=True)
77+
78+
R_body_to_earth = quat2Rot(q_att)
79+
80+
# Optical flow around x axis
81+
flow_x = -v_y / (_terrain_vpos - pos_z) * R_body_to_earth[2,2]
82+
83+
# Calculate observation scalar
84+
H_x = Matrix([flow_x]).jacobian(Matrix([_terrain_vpos]))
85+
86+
H_x_simple = cse(H_x, symbols('t0:30'))
87+
88+
# Optical flow around y axis
89+
flow_y = v_x / (_terrain_vpos - pos_z) * R_body_to_earth[2,2]
90+
91+
# Calculate observation scalar
92+
H_y = Matrix([flow_y]).jacobian(Matrix([_terrain_vpos]))
93+
94+
H_y_simple = cse(H_y, symbols('t0:30'))
95+
96+
write_simplified(H_x_simple, "flow_x_observation.txt", "Hx")
97+
write_simplified(H_y_simple, "flow_y_observation.txt", "Hy")
98+

0 commit comments

Comments
 (0)