Skip to content

Commit ffb5d10

Browse files
committed
update images
1 parent bb9e234 commit ffb5d10

File tree

8 files changed

+7
-12
lines changed

8 files changed

+7
-12
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +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"=>"memoryofatrufestival@gmail.com", "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
1+
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"=>"memoryofatrufestival@gmail.com", "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

collections/projects/Robots/_posts/2020-05-10-autonomous_tracked_vehicle.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Arduinos are capable of many things, yet they are often berated as being underpo
2525

2626
In the case of an Arduino, these devices are often used to maintain the balance of small robots, or as the flight controller for remote-controlled aircraft. They serve this purpose very well but the Arduinos generally end up underutilized. We can extend their capabilities to the more complex task of [navigation](https://en.wikipedia.org/wiki/Navigation). It is one thing to merely keep a vehicle stable in space and quite another to precisely control its position and orientation. If we can accomplish precise state control then we can command the vehicle to follow a given _trajectory_, or move towards a given set of _coordinates_. These are much more complicated tasks that involve a higher level of abstraction and greatly depend on the nature of the vehicle in question. In the most general case, we must measure the [state](https://en.wikipedia.org/wiki/State_vector_(navigation)) of a body that can rotate and translate in three directions to accomplish these tasks.
2727

28-
![image](https://www.intmath.com/vectors/img/cosines.gif)
28+
![image](/img/tracked-robot/3d-triad.jpeg)
2929
<p align="center"><i>Under a <a href="https://en.wikipedia.org/wiki/Euclidean_space">Euclidean space</a>, we can rotate and translate</i></p>
3030

3131
We can further separate the problem of navigation into two sections: measuring the state of the body and precisely controlling said state. Once we can estimate what our vehicle is doing, we can take actions that affect its behavior. However, the nature of the vehicle in question greatly affects what we can alter. For example, in a car we can only change its forward and backward velocity and the direction it steers in. We cannot change its orientation with respect to gravity nor its side-to-side velocity. By comparison, there are variables that we can change (albeit with some restrictions) in a vehicle like a helicopter. This machine is capable of rotating about all axes and can translate in any direction, along with being able to rise and fall vertically.
@@ -35,7 +35,7 @@ We can further separate the problem of navigation into two sections: measuring t
3535

3636
Given the intercoupled nature between the type of control we can obtain from a vehicle and the way it works, the more general component of navigation is measuring the state. This alone is not a simple problem and will depend greatly on the type of sensors we have available. In absence of the direct measurement of a variable, we must infer the state through a model that depends on related information. An example of such an inference is the process of [dead reckoning](https://en.wikipedia.org/wiki/Dead_reckoning). In this situation, we use the _acceleration_ of a body to estimate its _velocity_. We have no direct knowledge of the velocity and therefore cannot determine whether it is _true_, but it is better than no information at all.
3737

38-
![image](http://avstop.com/ac/flighttrainghandbook/imageqa7.jpg)
38+
![image](/img/tracked-robot/airplane-speed.png)
3939

4040
It's not unusual for wheeled ground vehicles to estimate their position using the method of [odometry](http://web.mit.edu/6.186/2007/tutorials/odomtutorial/odomtutorial.pdf). This involves counting the number of rotations of the wheels to determine how far the vehicle has displaced laterally and how much it has rotated. By combining this information, it's possible to calculate the two-dimensional position of the vehicle by assuming it is moving across a flat plane. Since the actual position of the vehicle is never measured, this approach is a variant of dead reckoning that does not use velocity and time to determine position, but rather the assumption that a wheel in contact with a surface will not _slide_ across said surface but _roll_ over it. An ideal _rolling_ wheel will only move forward if it has rotated a certain amount. The principal advantage of this method is the simplicity of the required calculations and sensors. A set of __rotary encoders__ is enough to determine the rotation of the vehicle's wheels and no other sensors are needed.
4141

@@ -71,12 +71,7 @@ In my case, I became interested in the navigation part of this challenge as I kn
7171
{% include youtube.html id='bFDGPgXtK-U' %}
7272
<p align="center"><i>Honey bees can fly to distant flowers and then return to their hive</i></p>
7373

74-
This example from nature was very inspirational, as it meant that it was not unreasonable to use a limited device like an Arduino as a platform to develop a navigation system. Animals require far more effective navigation systems to locate food and survive, but the lunarbotics robot did not have such demands. It only needed to move towards a mining location and return to its original position.
75-
76-
![image](https://www.researchgate.net/profile/Volker-Willert/publication/315836890/figure/fig8/AS:667946330378257@1536262223879/Odometry-results-for-the-main-robot-after-waypoint-navigation-In-red-is-shown-the.png)
77-
<p align="center"><i>The robot would need to go back and forth across a circuit</i></p>
78-
79-
With this in mind, I felt confident that a small prototype based on an Arduino could be used to develop a navigation system that could be ported to the larger robot. Since the robot (which had already been manufactured) used [treads](https://en.wikipedia.org/wiki/Continuous_track) to move over sand, it meant the prototype had to use this type of locomotion to effectively capture the dynamics of the larger vehicle. Obviously, it would not capture all of the dynamics, but it would still be much better than using a wheeled platform whose behavior differs significantly from a tracked vehicle.
74+
This example from nature was very inspirational, as it meant that it was not unreasonable to use a limited device like an Arduino as a platform to develop a navigation system. Animals require far more effective navigation systems to locate food and survive, but the lunarbotics robot did not have such demands. It only needed to move towards a mining location and return to its original position. With this in mind, I felt confident that a small prototype based on an Arduino could be used to develop a navigation system that could be ported to the larger robot. Since the robot (which had already been manufactured) used [treads](https://en.wikipedia.org/wiki/Continuous_track) to move over sand, it meant the prototype had to use this type of locomotion to effectively capture the dynamics of the larger vehicle. Obviously, it would not capture all of the dynamics, but it would still be much better than using a wheeled platform whose behavior differs significantly from a tracked vehicle.
8075

8176
## Vehicle Dynamics
8277

@@ -116,12 +111,12 @@ One of the benefits of developing the double integration algorithm was the resul
116111

117112
At the center of this improved dynamic model is a mathematical model for [friction](https://en.wikipedia.org/wiki/Friction). Just by itself, modelling friction is a complicated topic, but if we consider a __simplified__ model of friction, we can obtain usable results without much computational effort. A simple approximation is [Coulomb friction](https://link.springer.com/chapter/10.1007/978-3-642-10803-7_10). It defines friction as a function of the normal force acting on a body and separates it into two effects: static friction and dynamic friction. The transition between these two states is discontinuous with respect to sliding velocity, so it is not well-suited for integration using numerical methods. To circumvent this issue, we can define an approximation to Coulomb friction that is continuous with sliding velocity. See: [Multi-Body Dynamics, B.3.1 Compliant Contact Models](https://underactuated.mit.edu/multibody.html).
118113

119-
![image](https://www.researchgate.net/profile/Madalina-Dumitriu/publication/301541503/figure/fig15/AS:668711967019037@1536444765908/Force-displacement-curve-a-Coulomb-friction-model-b-Coulomb-model-with-spring-in.ppm)
114+
![image](/img/tracked-robot/smooth-friction.png)
120115
<p align="center"><i>Friction can be approximated as a non-linear damping force</i></p>
121116

122117
The continuous friction model should ideally have a very large slope when the sliding velocity is very small. This will allow us to better approximate [static friction](http://hyperphysics.phy-astr.gsu.edu/hbase/frict2.html) as it will keep the sliding velocities in this range very small (when ideally there should not be any). However, the need for a large force-velocity slope means we are in the presence of a [stiff differential equation](https://en.wikipedia.org/wiki/Stiff_equation) which is numerically __unstable__. We must therefore use specialized numerical methods to solve for the velocity as a function of acceleration, as our friction model is very sensitive to minor changes in velocity.
123118

124-
![image](https://www.johndcook.com/stiff25.png)
119+
![image](/img/tracked-robot/stiff-response.jpg)
125120
<p align="center"><i>Some equations will cause a numerical solver to become unstable and diverge</i></p>
126121

127122
To circumvent the numerical instability, I wrote a model that worked in two distinct phases: one phase measured the net lateral acceleration felt by the tracks, and if this value exceeded an estimate for the static friction coefficient (which would rapidly decrease if the vehicle rotated), it would be assumed that the vehicle did move laterally (velocity set to zero). However, if the static friction limit was below the current acceleration of the vehicle, then the continuous friction model would be used to determine the velocity through an [explicit Runge-Kutta method](https://jonshiach.github.io/ODEs-book/_pages/2.0_ERKs.html). The coefficients of the method were carefully selected to be very stable for moderately stiff equations, meaning that while they would diverge if the equations were too stiff or if the __time step__ between each iteration was too small, they were more [stable](https://jonshiach.github.io/ODEs-book/_pages/4.0_Stability.html) than other choices of coefficients.
@@ -139,7 +134,7 @@ Optical flow sensors work by using a __camera__ to take pictures of their enviro
139134

140135
A common and inexpensive optical flow sensor is the __ADNS-3080__. It is conveniently is sold as an independant module that can be easily connected to Arduinos. It communicates through the [SPI protocol](https://www.circuitbasics.com/basics-of-the-spi-communication-protocol/) and there are a multitude of code examples that demonstrate how to do this. Unfortunately, when I purchased the modules there were no easily used libraries for this sensor. One had to write their own code to use the module, or modify a working example for their own particular use case. I disliked this approach, so I wrote a library that refactored some of the available working examples into a compact and easy-to-use interface. That way, I could connect multiple sensors to the Arduino without writing a lot of redundant code while avoiding any mistakes this could cause.
141136

142-
![image](/img/tracked-robot/adns3080.jpg)
137+
![image](/img/tracked-robot/adns3080.jpeg)
143138
<p align="center"><i>The ADNS-3080 is sold as a module</i></p>
144139

145140
See: <b><a href="https://github.com/RCmags/ADNS3080">ADNS-3080 Mouse Sensor Library</a></b>

img/tracked-robot/3d-triad.jpeg

61 KB
Loading

img/tracked-robot/adns3080.jpeg

166 KB
Loading

img/tracked-robot/adns3080.jpg

-23.3 KB
Binary file not shown.
110 KB
Loading
18.8 KB
Loading
88 KB
Loading

0 commit comments

Comments
 (0)