Skip to content

Commit 1610a09

Browse files
committed
added vector operations file
1 parent 0aec326 commit 1610a09

File tree

1 file changed

+236
-0
lines changed

1 file changed

+236
-0
lines changed

geometry/vectors_3d.c

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
/**
2+
* @file
3+
* @brief API Functions related to 3D vector operations.
4+
* @author Krishna Vedala
5+
*/
6+
7+
#include <stdio.h>
8+
#ifdef __arm__ // if compiling for ARM-Cortex processors
9+
#define LIBQUAT_ARM
10+
#include <arm_math.h>
11+
#else
12+
#include <math.h>
13+
#endif
14+
#include <assert.h>
15+
16+
#include "geometry_datatypes.h"
17+
18+
/**
19+
* @addtogroup vec_3d 3D Vector operations
20+
* @{
21+
*/
22+
23+
/**
24+
* Subtract one vector from another. @f[
25+
* \vec{c}=\vec{a}-\vec{b}=\left(a_x-b_x\right)\hat{i}+
26+
* \left(a_y-b_y\right)\hat{j}+\left(a_z-b_z\right)\hat{k}@f]
27+
* @param[in] a vector to subtract from
28+
* @param[in] b vector to subtract
29+
* @returns resultant vector
30+
*/
31+
vec_3d vector_sub(const vec_3d *a, const vec_3d *b)
32+
{
33+
vec_3d out;
34+
#ifdef LIBQUAT_ARM
35+
arm_sub_f32((float *)a, (float *)b, (float *)&out);
36+
#else
37+
out.x = a->x - b->x;
38+
out.y = a->y - b->y;
39+
out.z = a->z - b->z;
40+
#endif
41+
42+
return out;
43+
}
44+
45+
/**
46+
* Add one vector to another. @f[
47+
* \vec{c}=\vec{a}+\vec{b}=\left(a_x+b_x\right)\hat{i}+
48+
* \left(a_y+b_y\right)\hat{j}+\left(a_z+b_z\right)\hat{k}@f]
49+
* @param[in] a vector to add to
50+
* @param[in] b vector to add
51+
* @returns resultant vector
52+
*/
53+
vec_3d vector_add(const vec_3d *a, const vec_3d *b)
54+
{
55+
vec_3d out;
56+
#ifdef LIBQUAT_ARM
57+
arm_add_f32((float *)a, (float *)b, (float *)&out);
58+
#else
59+
out.x = a->x + b->x;
60+
out.y = a->y + b->y;
61+
out.z = a->z + b->z;
62+
#endif
63+
64+
return out;
65+
}
66+
67+
/**
68+
* Obtain the dot product of two 3D vectors.
69+
* @f[
70+
* \vec{a}\cdot\vec{b}=a_xb_x + a_yb_y + a_zb_z
71+
* @f]
72+
* @param[in] a first vector
73+
* @param[in] b second vector
74+
* @returns resulting dot product
75+
*/
76+
float dot_prod(const vec_3d *a, const vec_3d *b)
77+
{
78+
float dot;
79+
#ifdef LIBQUAT_ARM
80+
arm_dot_prod_f32((float *)a, (float *)b, &dot);
81+
#else
82+
dot = a->x * b->x;
83+
dot += a->y * b->y;
84+
dot += a->z * b->z;
85+
#endif
86+
87+
return dot;
88+
}
89+
90+
/**
91+
* Compute the vector product of two 3d vectors.
92+
* @f[\begin{align*}
93+
* \vec{a}\times\vec{b} &= \begin{vmatrix}
94+
* \hat{i} & \hat{j} & \hat{k}\\
95+
* a_x & a_y & a_z\\
96+
* b_x & b_y & b_z
97+
* \end{vmatrix}\\
98+
* &= \left(a_yb_z-b_ya_z\right)\hat{i} - \left(a_xb_z-b_xa_z\right)\hat{j}
99+
* + \left(a_xb_y-b_xa_y\right)\hat{k} \end{align*}
100+
* @f]
101+
* @param[in] a first vector @f$\vec{a}@f$
102+
* @param[in] b second vector @f$\vec{b}@f$
103+
* @returns resultant vector @f$\vec{o}=\vec{a}\times\vec{b}@f$
104+
*/
105+
vec_3d vector_prod(const vec_3d *a, const vec_3d *b)
106+
{
107+
vec_3d out; // better this way to avoid copying results to input
108+
// vectors themselves
109+
out.x = a->y * b->z - a->z * b->y;
110+
out.y = -a->x * b->z + a->z * b->x;
111+
out.z = a->x * b->y - a->y * b->x;
112+
113+
return out;
114+
}
115+
116+
/**
117+
* Print formatted vector on stdout.
118+
* @param[in] a vector to print
119+
* @param[in] name name of the vector
120+
* @returns string representation of vector
121+
*/
122+
const char *print_vector(const vec_3d *a, const char *name)
123+
{
124+
static char vec_str[100]; // static to ensure the string life extends the
125+
// life of function
126+
127+
snprintf(vec_str, 99, "vec(%s) = (%.3g)i + (%.3g)j + (%.3g)k\n", name, a->x,
128+
a->y, a->z);
129+
return vec_str;
130+
}
131+
132+
/**
133+
* Compute the norm a vector.
134+
* @f[\lVert\vec{a}\rVert = \sqrt{\vec{a}\cdot\vec{a}} @f]
135+
* @param[in] a input vector
136+
* @returns norm of the given vector
137+
*/
138+
float vector_norm(const vec_3d *a)
139+
{
140+
float n = dot_prod(a, a);
141+
#ifdef LIBQUAT_ARM
142+
arm_sqrt_f32(*n, n);
143+
#else
144+
n = sqrtf(n);
145+
#endif
146+
147+
return n;
148+
}
149+
150+
/**
151+
* Obtain unit vector in the same direction as given vector.
152+
* @f[\hat{a}=\frac{\vec{a}}{\lVert\vec{a}\rVert}@f]
153+
* @param[in] a input vector
154+
* @returns n unit vector in the direction of @f$\vec{a}@f$
155+
*/
156+
vec_3d unit_vec(const vec_3d *a)
157+
{
158+
vec_3d n = {0};
159+
160+
float norm = vector_norm(a);
161+
if (fabsf(norm) < EPSILON) // detect possible divide by 0
162+
return n;
163+
164+
if (norm != 1.F) // perform division only if needed
165+
{
166+
n.x = a->x / norm;
167+
n.y = a->y / norm;
168+
n.z = a->z / norm;
169+
}
170+
return n;
171+
}
172+
173+
/**
174+
* The cross product of vectors can be represented as a matrix
175+
* multiplication operation. This function obtains the `3x3` matrix
176+
* of the cross-product operator from the first vector.
177+
* @f[\begin{align*}
178+
* \left(\vec{a}\times\right)\vec{b} &= \tilde{A}_a\vec{b}\\
179+
* \tilde{A}_a &=
180+
* \begin{bmatrix}0&-a_z&a_y\\a_z&0&-a_x\\-a_y&a_x&0\end{bmatrix}
181+
* \end{align*}@f]
182+
* @param[in] a input vector
183+
* @returns the `3x3` matrix for the cross product operator
184+
* @f$\left(\vec{a}\times\right)@f$
185+
*/
186+
mat_3x3 get_cross_matrix(const vec_3d *a)
187+
{
188+
mat_3x3 A = {0., -a->z, a->y, a->z, 0., -a->x, -a->y, a->x, 0.};
189+
return A;
190+
}
191+
192+
/** @} */
193+
194+
/**
195+
* @brief Testing function
196+
* @returns `void`
197+
*/
198+
static void test()
199+
{
200+
vec_3d a = {1., 2., 3.};
201+
vec_3d b = {1., 1., 1.};
202+
float d;
203+
204+
// printf("%s", print_vector(&a, "a"));
205+
// printf("%s", print_vector(&b, "b"));
206+
207+
d = vector_norm(&a);
208+
// printf("|a| = %.4g\n", d);
209+
assert(fabs(d - 3.742) < 0.01);
210+
d = vector_norm(&b);
211+
// printf("|b| = %.4g\n", d);
212+
assert(fabs(d - 1.732) < 0.01);
213+
214+
d = dot_prod(&a, &b);
215+
// printf("Dot product: %f\n", d);
216+
assert(fabs(d - 6.f) < 0.01);
217+
218+
vec_3d c = vector_prod(&a, &b);
219+
// printf("Vector product ");
220+
// printf("%s", print_vector(&c, "c"));
221+
assert(fabs(c.x - (-1)) < 0.01);
222+
assert(fabs(c.y - (2)) < 0.01);
223+
assert(fabs(c.z - (-1)) < 0.01);
224+
}
225+
226+
/**
227+
* @brief Main function
228+
*
229+
* @return 0 on exit
230+
*/
231+
int main(void)
232+
{
233+
test();
234+
235+
return 0;
236+
}

0 commit comments

Comments
 (0)