Skip to content

Commit

Permalink
add links to post
Browse files Browse the repository at this point in the history
  • Loading branch information
RCmags committed Oct 7, 2024
1 parent e8dbe06 commit 8fdf798
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
I"�{"source"=>"/media/user/Storage-Fast/Research/code/github-website/src", "destination"=>"/media/user/Storage-Fast/Research/code/github-website/src/_site", "collections_dir"=>"collections", "cache_dir"=>".jekyll-cache", "plugins_dir"=>"_plugins", "layouts_dir"=>"_layouts", "data_dir"=>"_data", "includes_dir"=>"_includes", "collections"=>{"posts"=>{"output"=>true, "permalink"=>"/:categories/:year/:month/:day/:title:output_ext"}, "projects"=>{"output"=>true}, "blog"=>{"output"=>true}}, "safe"=>false, "include"=>[".htaccess"], "exclude"=>[".sass-cache", ".jekyll-cache", "gemfiles", "Gemfile", "Gemfile.lock", "node_modules", "vendor/bundle/", "vendor/cache/", "vendor/gems/", "vendor/ruby/"], "keep_files"=>[".git", ".svn"], "encoding"=>"utf-8", "markdown_ext"=>"markdown,mkdown,mkdn,mkd,md", "strict_front_matter"=>false, "show_drafts"=>nil, "limit_posts"=>0, "future"=>false, "unpublished"=>false, "whitelist"=>[], "plugins"=>["jekyll-feed", "jekyll-seo-tag", "jekyll-paginate"], "markdown"=>"kramdown", "highlighter"=>"rouge", "lsi"=>false, "excerpt_separator"=>"\n\n", "incremental"=>false, "detach"=>false, "port"=>"4000", "host"=>"127.0.0.1", "baseurl"=>nil, "show_dir_listing"=>false, "permalink"=>"date", "paginate_path"=>"/page:num/", "timezone"=>nil, "quiet"=>false, "verbose"=>false, "defaults"=>[], "liquid"=>{"error_mode"=>"warn", "strict_filters"=>false, "strict_variables"=>false}, "kramdown"=>{"auto_ids"=>true, "toc_levels"=>[1, 2, 3, 4, 5, 6], "entity_output"=>"as_char", "smart_quotes"=>"lsquo,rsquo,ldquo,rdquo", "input"=>"GFM", "hard_wrap"=>false, "guess_lang"=>true, "footnote_nr"=>1, "show_warnings"=>false}, "title"=>"RCmags", "author"=>"Mags", "email"=>"[email protected]", "description"=>"Projects and other things", "paginate"=>6, "github_username"=>"RCmags", "youtube_username"=>"XXXmags", "rcgroups_username_id"=>"189488", "google_analytics"=>true, "minima"=>{"date_format"=>"%-d %b, %Y"}, "livereload_port"=>35729, "serving"=>true, "watch"=>true, "url"=>"http://localhost:4000"}:ET
I"a{"source"=>"/media/user/Storage-Fast/Research/code/github-website/src", "destination"=>"/media/user/Storage-Fast/Research/code/github-website/src/_site", "collections_dir"=>"collections", "cache_dir"=>".jekyll-cache", "plugins_dir"=>"_plugins", "layouts_dir"=>"_layouts", "data_dir"=>"_data", "includes_dir"=>"_includes", "collections"=>{"posts"=>{"output"=>true, "permalink"=>"/:categories/:year/:month/:day/:title:output_ext"}, "projects"=>{"output"=>true}, "blog"=>{"output"=>true}}, "safe"=>false, "include"=>[".htaccess"], "exclude"=>[".sass-cache", ".jekyll-cache", "gemfiles", "Gemfile", "Gemfile.lock", "node_modules", "vendor/bundle/", "vendor/cache/", "vendor/gems/", "vendor/ruby/"], "keep_files"=>[".git", ".svn"], "encoding"=>"utf-8", "markdown_ext"=>"markdown,mkdown,mkdn,mkd,md", "strict_front_matter"=>false, "show_drafts"=>nil, "limit_posts"=>0, "future"=>false, "unpublished"=>false, "whitelist"=>[], "plugins"=>["jekyll-feed", "jekyll-seo-tag", "jekyll-paginate"], "markdown"=>"kramdown", "highlighter"=>"rouge", "lsi"=>false, "excerpt_separator"=>"\n\n", "incremental"=>false, "detach"=>false, "port"=>"4000", "host"=>"127.0.0.1", "baseurl"=>nil, "show_dir_listing"=>false, "permalink"=>"date", "paginate_path"=>"/page:num/", "timezone"=>nil, "quiet"=>false, "verbose"=>false, "defaults"=>[], "liquid"=>{"error_mode"=>"warn", "strict_filters"=>false, "strict_variables"=>false}, "kramdown"=>{"auto_ids"=>true, "toc_levels"=>[1, 2, 3, 4, 5, 6], "entity_output"=>"as_char", "smart_quotes"=>"lsquo,rsquo,ldquo,rdquo", "input"=>"GFM", "hard_wrap"=>false, "guess_lang"=>true, "footnote_nr"=>1, "show_warnings"=>false, "syntax_highlighter"=>"rouge", "syntax_highlighter_opts"=>{:default_lang=>"plaintext", :guess_lang=>true}, "coderay"=>{}}, "title"=>"RCmags", "author"=>"Mags", "email"=>"[email protected]", "description"=>"Projects and other things", "paginate"=>6, "github_username"=>"RCmags", "youtube_username"=>"XXXmags", "rcgroups_username_id"=>"189488", "google_analytics"=>true, "minima"=>{"date_format"=>"%-d %b, %Y"}, "livereload_port"=>35729, "serving"=>true, "watch"=>true, "url"=>"http://localhost:4000"}:ET
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ layout: post
title: "Datatypes for 3D vectors and quaternions"
---

While developing an algorithm to perform sensor fusion between the gyroscope and accelerometer of an inertial measurement unit, I needed a way to execute basic vector operations and manipulate a quaternion to encode the gyroscope's heading. Although it was possible to hard-code these operations directly into the sensor fusion, it seemed prudent to separate this functionality in case it needed to be reused. This was especially relevant for spatial navigation, which requires manipulating vectors in different frames of reference.
While developing an algorithm to perform [sensor fusion](/projects/arduino libraries/2020/03/14/imu_sensor_fusion.html) between the gyroscope and accelerometer of an inertial measurement unit, I needed a way to execute basic [vector](https://es.wikipedia.org/wiki/Vector) operations and manipulate a [quaternion](https://en.wikipedia.org/wiki/Quaternion) to encode the gyroscope's heading. Although it was possible to hard-code these operations directly into the sensor fusion, it seemed prudent to separate this functionality in case it needed to be reused. This was especially relevant for spatial navigation, which requires manipulating vectors in different frames of reference.

To create data types for vectors and quaternions, I first needed to understand the operations they can perform. These operations, defined through mathematical notation, had to be converted into functions. By using operator overloading, I was able to employ these functions in a way that closely resembled mathematical notation. This is because an operation is simply a different way of writing a function that takes one or more parameters. This approach was applied to most of the operations possible for vectors and quaternions. For more information on vector and quaternion operations, see these links:
To create data types for vectors and quaternions, I first needed to understand the [operations](https://en.wikipedia.org/wiki/Operation_(mathematics)) they can perform. These operations, defined through mathematical notation, had to be converted into functions. By using [operator overloading](https://www.geeksforgeeks.org/operator-overloading-cpp/), I was able to employ these functions in a way that closely resembled mathematical notation. This is because an operation is simply a different way of writing a function that takes one or more parameters. This approach was applied to most of the operations possible for vectors and quaternions. For more information on vector and quaternion operations, see these links:

- [Quaternions and rotations](http://danceswithcode.net/engineeringnotes/quaternions/quaternions.html)
- [Quaternion operations](http://graphics.stanford.edu/courses/cs348a-17-winter/Papers/quaternion.pdf)
- [Vector operations](http://emweb.unl.edu/Math/mathweb/vectors/vectors.html)

<br>
For example, the addition of two vectors can be written as _V1 + V2_. The _+_ sign serves as shorthand for the function that takes two vectors and returns a new vector of their added values. When it came time to actually use these data types in code, it was straightforward because the corresponding operations could be written just as they would be in mathematical notation. This simplicity made the code easier to read, as operations reduced to a symbol rather than a function call.
For example, the addition of two vectors can be written as **V1 + V2**. The **+** sign serves as shorthand for the function that takes two vectors and returns a new vector of their added values. When it came time to actually use these data types in code, it was straightforward because the corresponding operations could be written just as they would be in mathematical notation. This simplicity made the code easier to read, as operations reduced to a symbol rather than a function call.

The library for 3D vectors and quaternions utilized two structs to define each data type. Both vectors and quaternions could perform basic operations such as addition, subtraction, multiplication, division, increment, decrement, and their analogs for multiplication and division. Vectors and quaternions were also compatible with each other through operations such as the vector dot product and cross product. Quaternions could be constructed as unit quaternions to represent rotations, allowing them to be directly used to rotate vectors. Additionally, both data types were made compatible with arrays, meaning that a length-3 array could be added, subtracted, etc., from a vector. This compatibility also extended to quaternions.
Inside the library, vectors and quaternions were declared as [structs](https://cplusplus.com/doc/tutorial/structures/) to define their [data types](https://en.wikipedia.org/wiki/Data_type). Both vectors and quaternions could perform basic operations such as _addition, subtraction, multiplication, division, increment, decrement_, and their analogs for _multiplication and division_. Vectors and quaternions were also compatible with each other through operations such as the vector [dot product](https://en.wikipedia.org/wiki/Dot_product) and [cross product](https://en.wikipedia.org/wiki/Cross_product). Quaternions could be constructed as unit quaternions to represent rotations, allowing them to be directly used to rotate vectors. Additionally, both data types were made compatible with [arrays](https://cplusplus.com/doc/tutorial/arrays/), meaning that a length-3 array could be added, subtracted, etc, from a vector. This compatibility also extended to quaternions.

![image](/img/imu-filter/vectors.jpg)
<p align="center"><i>3D Vectors represent magnitude and direction</i></p>

As the more primitive structure, vectors were the first data type to be defined. They consisted of an array with three components that could be manipulated to perform basic operations. Quaternions inherited from vectors by adding an additional scalar component to their structure. These four values, due to the mathematics of quaternions, allowed them to encode the rotations of vectors in three-dimensional space, enabling the quaternion data structure to act upon vectors through specific functions.
Vectors were the first data type to be defined as they were the more primitive structure. They consisted of an array with three components that could be manipulated to perform basic operations. Quaternions inherited from vectors by adding an additional scalar component to their structure. These four values, due to the mathematics of quaternions, allowed them to encode the [rotations of vectors](https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation) in three-dimensional space, enabling the quaternion data structure to act upon vectors through specific functions.

![image](/img/imu-filter/quaternion.png)
<p align="center"><i>4D Quaternions represent an axis of rotation and rotation angle</i></p>

Overall, I was very pleased with this project. I found it enriching because it taught me to view operations as functions and to see algebraic representations as translatable into code. It also helped me understand that what we do on paper is merely a representation of operations that are procedural, following an input-output pattern. All the intermediate steps we perform are just a way to keep track of these operations. This step-driven nature emphasizes that these operations are algorithmic, in that they following a precise series of steps to achieve an output. I feel this experience increased my mathematical maturity by providing a more nuanced perspective on math.
Overall, I was very pleased with this project. I found it enriching because it taught me to view operations as functions and to see algebraic representations as translatable into code. It also helped me understand that what we do on paper is merely a representation of operations that are procedural, following an _input-output_ pattern. All the intermediate steps we perform are just a way to keep track of these operations. This step-driven nature emphasizes that these operations are algorithmic, in that they following a precise series of steps to achieve an output. I feel this experience increased my [mathematical maturity](https://en.wikipedia.org/wiki/Mathematical_maturity) by providing a more nuanced perspective on math.

### GitHub Repository
The library can be downloaded from its GitHub repository or the Arduino library catalog. See the following link to access the repository: [VectorDatatype](https://github.com/RCmags/vector_datatype)
Expand Down

0 comments on commit 8fdf798

Please sign in to comment.