├── hugo ├── themes │ └── onedly │ │ ├── VERSION │ │ ├── .gitignore │ │ ├── exampleSite │ │ ├── content │ │ │ ├── imprint-gdpr │ │ │ │ ├── _index.md │ │ │ │ ├── gdpr.md │ │ │ │ └── imprint.md │ │ │ └── post │ │ │ │ ├── _index.md │ │ │ │ ├── project.md │ │ │ │ ├── conclusion.md │ │ │ │ ├── images.md │ │ │ │ ├── about.md │ │ │ │ ├── emoji-support.md │ │ │ │ ├── coding.md │ │ │ │ └── math-typesetting.mmark │ │ └── config.toml │ │ ├── images │ │ ├── tn.png │ │ └── screenshot.png │ │ ├── archetypes │ │ └── default.md │ │ ├── layouts │ │ ├── _default │ │ │ ├── list.html │ │ │ └── single.html │ │ ├── index.html │ │ └── partials │ │ │ ├── social_sharing.html │ │ │ ├── header.html │ │ │ ├── js.html │ │ │ ├── template.css │ │ │ ├── main.html │ │ │ ├── footer.html │ │ │ ├── nav.html │ │ │ ├── head.html │ │ │ ├── share-links.html │ │ │ └── social.html │ │ ├── static │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ └── glyphicons-halflings-regular.woff │ │ ├── css │ │ │ └── landing-page.css │ │ └── js │ │ │ └── jquery.easing.min.js │ │ ├── theme.toml │ │ ├── LICENSE.md │ │ └── README.md ├── static │ └── images │ │ ├── unity1.png │ │ └── unity2.png ├── .gitmodules ├── archetypes │ └── default.md ├── content │ └── post │ │ ├── _index.md │ │ ├── contact.md │ │ ├── core.md │ │ ├── about.md │ │ └── wrappers.md └── config.toml ├── src ├── spacetime │ ├── mod.rs │ └── robot.rs ├── utils_rust │ ├── mod.rs │ ├── file_utils.rs │ └── transformations.rs ├── groove │ ├── mod.rs │ ├── groove.rs │ ├── vars.rs │ ├── env_collision.rs │ └── objective_master.rs ├── lib.rs ├── bin │ └── relaxed_ik_bin.rs ├── relaxed_ik.rs ├── relaxed_ik_web.rs └── relaxed_ik_wrapper.rs ├── docs ├── images │ ├── unity1.png │ └── unity2.png ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── articles │ └── index.html ├── blog │ └── index.html ├── docs │ └── index.html ├── posts │ └── index.html ├── sections │ └── index.html ├── tags │ └── index.xml ├── categories │ └── index.xml ├── sitemap.xml ├── index.xml ├── post │ ├── index.xml │ ├── faq │ │ └── index.html │ ├── contact │ │ └── index.html │ ├── core │ │ └── index.html │ ├── about │ │ └── index.html │ └── wrappers │ │ └── index.html ├── css │ └── landing-page.css └── js │ └── jquery.easing.min.js ├── configs ├── example_settings │ ├── ur5.yaml │ ├── ur5e.yaml │ ├── panda.yaml │ ├── spot_arm.yaml │ ├── sawyer.yaml │ ├── fetch.yaml │ ├── jaco.yaml │ ├── mobile_spot_arm.yaml │ └── baxter.yaml ├── settings.yaml └── urdfs │ ├── spot_arm.urdf │ └── mobile_spot_arm.urdf ├── .gitignore ├── LICENSE ├── Cargo.toml ├── wrappers └── python_wrapper.py └── README.md /hugo/themes/onedly/VERSION: -------------------------------------------------------------------------------- 1 | 1.0 2 | -------------------------------------------------------------------------------- /hugo/themes/onedly/.gitignore: -------------------------------------------------------------------------------- 1 | public/ 2 | -------------------------------------------------------------------------------- /src/spacetime/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod robot; 2 | pub mod arm; -------------------------------------------------------------------------------- /src/utils_rust/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod transformations; 2 | pub mod file_utils; -------------------------------------------------------------------------------- /docs/images/unity1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/docs/images/unity1.png -------------------------------------------------------------------------------- /docs/images/unity2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/docs/images/unity2.png -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/imprint-gdpr/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | author = "Hugo Authors" 3 | +++ 4 | 5 | -------------------------------------------------------------------------------- /hugo/static/images/unity1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/hugo/static/images/unity1.png -------------------------------------------------------------------------------- /hugo/static/images/unity2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/hugo/static/images/unity2.png -------------------------------------------------------------------------------- /hugo/themes/onedly/images/tn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/hugo/themes/onedly/images/tn.png -------------------------------------------------------------------------------- /hugo/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "themes/onedly"] 2 | path = themes/onedly 3 | url = https://github.com/cdeck3r/OneDly-Theme.git 4 | -------------------------------------------------------------------------------- /hugo/themes/onedly/archetypes/default.md: -------------------------------------------------------------------------------- 1 | +++ 2 | Description = "" 3 | Keywords = [] 4 | Tags = [] 5 | Categories = [] 6 | +++ 7 | -------------------------------------------------------------------------------- /hugo/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /hugo/themes/onedly/images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/hugo/themes/onedly/images/screenshot.png -------------------------------------------------------------------------------- /docs/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/docs/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /docs/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/docs/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /docs/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/docs/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /hugo/content/post/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | aliases = ["posts","articles","blog","sections","docs"] 3 | title = "Sections" 4 | author = "Hugo Authors" 5 | +++ -------------------------------------------------------------------------------- /src/groove/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod objective; 2 | pub mod groove; 3 | pub mod vars; 4 | pub mod gradient; 5 | pub mod objective_master; 6 | // pub mod env_collision; -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod utils_rust; 2 | pub mod spacetime; 3 | pub mod groove; 4 | pub mod relaxed_ik; 5 | pub mod relaxed_ik_wrapper; 6 | pub mod relaxed_ik_web; -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | aliases = ["posts","articles","blog","sections","docs"] 3 | title = "Sections" 4 | author = "Hugo Authors" 5 | +++ -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/_default/list.html: -------------------------------------------------------------------------------- 1 | {{ partial "head.html" . }} 2 | {{ partial "header.html" . }} 3 | {{ partial "main.html" . }} 4 | {{ partial "footer.html" . }} 5 | -------------------------------------------------------------------------------- /hugo/themes/onedly/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/hugo/themes/onedly/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /hugo/themes/onedly/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/hugo/themes/onedly/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /hugo/themes/onedly/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwgraphics/relaxed_ik_core/HEAD/hugo/themes/onedly/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /configs/example_settings/ur5.yaml: -------------------------------------------------------------------------------- 1 | urdf: ur5.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - base_link 5 | ee_links: 6 | - tool0 7 | starting_config: [3.14, -1.95, -1.2, -3.14, -1.57, -1.57] 8 | obstacles: -------------------------------------------------------------------------------- /configs/example_settings/ur5e.yaml: -------------------------------------------------------------------------------- 1 | urdf: ur5e.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - base_link 5 | ee_links: 6 | - tool0 7 | starting_config: [3.14, -1.95, -1.2, -3.14, -1.57, -1.57] 8 | obstacles: -------------------------------------------------------------------------------- /configs/settings.yaml: -------------------------------------------------------------------------------- 1 | urdf: sawyer.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - base_link 5 | ee_links: 6 | - right_hand 7 | starting_config: [ 0.0, 0.0, -1.5708, 1.5708, 0.0, -1.5708, 0.0 ] 8 | obstacles: -------------------------------------------------------------------------------- /configs/example_settings/panda.yaml: -------------------------------------------------------------------------------- 1 | urdf: panda.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - world 5 | ee_links: 6 | - panda_hand 7 | starting_config: [ 0.0, 0.0, 0.0, -1.5708, 0.0, 1.5708, 0.0 ] 8 | obstacles: -------------------------------------------------------------------------------- /configs/example_settings/spot_arm.yaml: -------------------------------------------------------------------------------- 1 | urdf: spot_arm.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - body 5 | ee_links: 6 | - tool_tip 7 | starting_config: [ 0.0, -1.10, 2.00, 0.0, -0.90, 0.0 ] 8 | obstacles: -------------------------------------------------------------------------------- /configs/example_settings/sawyer.yaml: -------------------------------------------------------------------------------- 1 | urdf: sawyer.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - base_link 5 | ee_links: 6 | - right_hand 7 | starting_config: [ 0.0, 0.0, -1.5708, 1.5708, 0.0, -1.5708, 0.0 ] 8 | obstacles: -------------------------------------------------------------------------------- /configs/example_settings/fetch.yaml: -------------------------------------------------------------------------------- 1 | urdf: fetch.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - torso_lift_link 5 | ee_links: 6 | - gripper_link 7 | starting_config: [ 0.0, 0.0, -1.5708, 1.5708, 0.0, -1.5708, 0.0 ] 8 | obstacles: -------------------------------------------------------------------------------- /configs/example_settings/jaco.yaml: -------------------------------------------------------------------------------- 1 | urdf: jaco.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - j2s7s300_link_base 5 | ee_links: 6 | - j2s7s300_link_7 7 | starting_config: [ 0.0, 0.0, -1.5708, 1.5708, 0.0, -1.5708, 0.0 ] 8 | obstacles: -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | /post/ -------------------------------------------------------------------------------- /docs/blog/index.html: -------------------------------------------------------------------------------- 1 | /post/ -------------------------------------------------------------------------------- /docs/docs/index.html: -------------------------------------------------------------------------------- 1 | /post/ -------------------------------------------------------------------------------- /docs/posts/index.html: -------------------------------------------------------------------------------- 1 | /post/ -------------------------------------------------------------------------------- /docs/sections/index.html: -------------------------------------------------------------------------------- 1 | /post/ -------------------------------------------------------------------------------- /configs/example_settings/mobile_spot_arm.yaml: -------------------------------------------------------------------------------- 1 | urdf: mobile_spot_arm.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - world 5 | ee_links: 6 | - tool_tip 7 | starting_config: [ 0.0, 0.0, 0.0, -1.10, 2.00, 0.0, -0.90, 0.0 ] 8 | obstacles: -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/index.html: -------------------------------------------------------------------------------- 1 | {{ partial "head.html" . }} 2 | {{ partial "nav.html" . }} 3 | {{ partial "header.html" . }} 4 | {{ partial "main.html" . }} 5 | {{ partial "social_sharing.html" . }} 6 | {{ partial "footer.html" . }} 7 | -------------------------------------------------------------------------------- /hugo/content/post/contact.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Contact" 3 | description = "Contact" 4 | date = "2019-08-07" 5 | author = "" 6 | sec = 5 7 | +++ 8 | 9 | If you have any comments or questions on any of this, or if you encounter any bugs in the wrappers of the solver, feel free to post an issue or email me directly at rakita@cs.wisc.edu. -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/social_sharing.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |
6 |
    7 | {{ partial "share-links" . }} 8 |
9 |
10 |
11 | 12 |
13 | -------------------------------------------------------------------------------- /src/utils_rust/file_utils.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 3 | use std::io::prelude::*; 4 | use std::fs::read_dir; 5 | use path_slash::PathBufExt; 6 | 7 | pub fn get_path_to_src() -> String { 8 | let path = env::current_dir().unwrap(); 9 | let s = path.to_slash().unwrap(); 10 | let s1 = String::from(s); 11 | let path_to_src = s1 + "/"; 12 | path_to_src 13 | } -------------------------------------------------------------------------------- /configs/example_settings/baxter.yaml: -------------------------------------------------------------------------------- 1 | urdf: baxter.urdf 2 | link_radius: 0.05 3 | base_links: 4 | - torso 5 | - torso 6 | ee_links: 7 | - right_hand 8 | - left_hand 9 | starting_config: [0.0, -0.0003125999999995521, 1.5704593245206757, 0.8793927999999999, 0.0, -6.462112780614149e-05, 0.0, 0.0, -0.0003125999999995521, -1.5704593245206757, 0.8793927999999999, 0.0, -6.462112780614149e-05, 0.0] 10 | obstacles: -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/imprint-gdpr/gdpr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "General Data Protection Regulation (GDPR)" 3 | description = "General Data Protection Regulation (GDPR)" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | +++ 7 | 8 | GDPR information are highly specific to the site. You may use a generator, e.g. 9 | [Datenschutz-Generator](https://datenschutz-generator.de/datenschutzerklaerung/) 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | # Generated by Cargo 3 | # will have compiled files and executables 4 | /target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | wrappers/__pycache__/ 14 | 15 | # webassembly files 16 | /pkg/ -------------------------------------------------------------------------------- /docs/tags/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tags on Relaxed IK 5 | /tags/ 6 | Recent content in Tags on Relaxed IK 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/categories/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Categories on Relaxed IK 5 | /categories/ 6 | Recent content in Categories on Relaxed IK 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/_default/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "head.html" . }} 2 | {{ partial "nav.html" . }} 3 | 4 |
5 |
6 | 7 |
8 | 9 |
10 |
11 |
12 |
13 |

{{ .Title }}

14 | {{ .Content }} 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 | {{ partial "footer.html" . }} 23 | -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/header.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 |
8 | 9 |
10 |

{{ .Site.Title }}

11 |

{{ .Site.Params.description }}

12 |
13 | 14 |
    15 | {{ partial "social" . }} 16 |
17 |
18 |
19 |
20 |
21 | 22 |
23 | 24 |
25 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/project.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Project Definition" 3 | description = "Goals, objectives and approach" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | sec = 2 7 | +++ 8 | 9 | This section defines concisely the basic project frame. 10 | 11 | ### Goal 12 | 13 | Improve my CV by adding new state-of-the-art development skills. 14 | 15 | ### Approach & Objectives 16 | 17 | * To be able to setup a Raspi from scratch 18 | * To be able to develop a simple command line software 19 | * To enable a software to automatically restart after shutdown / power off 20 | * To enable resilience by monitoring and restarting software processes remotely 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /hugo/themes/onedly/theme.toml: -------------------------------------------------------------------------------- 1 | name = "OneDly Project" 2 | license = "MIT" 3 | licenselink = "https://github.com/cdeck3r/OneDly-Theme/blob/master/LICENSE.md" 4 | description = "Theme for documenting One-Day-Only (OneDly) projects." 5 | homepage = "https://github.com/cdeck3r/OneDly-Theme" 6 | tags = ["documentation", "landing page", "opensource", "single page"] 7 | features = ["github", "images" ] 8 | min_version= "0.48" 9 | 10 | [author] 11 | name = "Christian Decker" 12 | 13 | # If porting an existing theme 14 | [original] 15 | author = "Omar Abdelhafith" 16 | homepage = "https://github.com/nsomar/github-project-landing-page" 17 | repo = "https://github.com/nsomar/github-project-landing-page" 18 | 19 | -------------------------------------------------------------------------------- /src/bin/relaxed_ik_bin.rs: -------------------------------------------------------------------------------- 1 | extern crate relaxed_ik_lib; 2 | use relaxed_ik_lib::relaxed_ik; 3 | use nalgebra::{Vector3, UnitQuaternion, Quaternion}; 4 | 5 | use std::{io, thread, time}; 6 | use crate::relaxed_ik_lib::utils_rust::file_utils::{*}; 7 | 8 | fn main() { 9 | // initilize relaxed ik 10 | let path_to_src = get_path_to_src(); 11 | let default_path_to_setting = path_to_src + "configs/settings.yaml"; 12 | let mut relaxed_ik = relaxed_ik::RelaxedIK::load_settings(default_path_to_setting.as_str()); 13 | 14 | for i in 0..10{ 15 | for j in 0..relaxed_ik.vars.robot.num_chains { 16 | // gradually move along the y axis 17 | relaxed_ik.vars.goal_positions[j] += Vector3::new(0.0, 0.01, 0.0); 18 | } 19 | let x = relaxed_ik.solve(); 20 | println!("Joint solutions: {:?}", x); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ if isset .Site.Params "googleAnalytics" }} 11 | 12 | 13 | 23 | 24 | {{ end }} 25 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | /post/about/ 6 | 2019-08-07T00:00:00+00:00 7 | 8 | /post/contact/ 9 | 2019-08-07T00:00:00+00:00 10 | 11 | /post/core/ 12 | 2019-08-07T00:00:00+00:00 13 | 14 | / 15 | 2019-08-07T00:00:00+00:00 16 | 17 | /post/ 18 | 2019-08-07T00:00:00+00:00 19 | 20 | /post/wrappers/ 21 | 2019-08-07T00:00:00+00:00 22 | 23 | /categories/ 24 | 25 | /tags/ 26 | 27 | 28 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/conclusion.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Conclusion" 3 | description = "Summary, conclusion and next steps" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | sec = 7 7 | +++ 8 | 9 | This section concludes the project. 10 | 11 | ### Summary 12 | 13 | The list below displays the achieved objectives: 14 | 15 | * [x] To be able to setup a Raspi from scratch 16 | * [x] To be able to develop a simple command line software 17 | * [x] To enable a software to automatically restart after shutdown / power off 18 | * [ ] To enable resilience by monitoring and restarting software processes remotely 19 | 20 | ### Conclusion 21 | 22 | I successfully acquired new development skills for raspi computers. They provide a valuable contribution to my CV. 23 | 24 | ### Next Steps 25 | 26 | There are other embedded systems. Will approach them as my next programming plattform. 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/template.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | border-color: {{ .Site.Params.first_border_color }}; 3 | } 4 | 5 | .content-section-a, 6 | footer, 7 | .navbar { 8 | background-color: {{ .Site.Params.first_color }}; 9 | color: {{ .Site.Params.first_text_color }}; 10 | } 11 | 12 | .navbar a:link, 13 | .navbar-default .navbar-nav>li>a { 14 | color: {{ .Site.Params.header_link_color }}; 15 | } 16 | 17 | .navbar a:hover, 18 | .navbar-default .navbar-nav>li>a:hover { 19 | color: {{ .Site.Params.header_link_hover_color }}; 20 | } 21 | 22 | .content-section-b { 23 | background-color: {{ .Site.Params.second_color }}; 24 | color: {{ .Site.Params.second_text_color }}; 25 | } 26 | 27 | body { 28 | color: {{ .Site.Params.header_text_color }}; 29 | } 30 | 31 | .header-container h1, 32 | .header-container h2, 33 | .header-container h3, 34 | .header-container h4 { 35 | color: {{ .Site.Params.header_text_color }}; 36 | } 37 | -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/main.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | {{ range $index, $element := where (.Site.RegularPages.ByParam "sec") "Section" "in" .Site.Params.mainSections }} 5 | {{ if modBool $index 2 }} 6 |
7 | {{ else }} 8 |
9 | {{ end }} 10 | 11 |
12 | 13 |
14 |
15 | 18 |

{{ .Title }}

19 | {{ replace .Content "" "
" | safeHTML }} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {{ end }} 28 | 29 | 30 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/images.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Section" 3 | description = "Some doc using images" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | sec = 4 7 | +++ 8 | 9 | _Source: content taken from [hugoBasicExample](https://github.com/gohugoio/hugoBasicExample). File: `rich-content.md`_ 10 | 11 | Hugo ships with several [Built-in Shortcodes](https://gohugo.io/content-management/shortcodes/#use-hugo-s-built-in-shortcodes) for rich content, along with a [Privacy Config](https://gohugo.io/about/hugo-and-gdpr/) and a set of Simple Shortcodes that enable static and no-JS versions of various social media embeds. 12 | 13 | --- 14 | 15 | ## Instagram Simple Shortcode 16 | 17 | {{< instagram_simple BGvuInzyFAe hidecaption >}} 18 | 19 |
20 | 21 | --- 22 | 23 | ## YouTube Privacy Enhanced Shortcode 24 | 25 | {{< youtube ZJthWmvUzzc >}} 26 | 27 |
28 | 29 | --- 30 | 31 | ## Twitter Simple Shortcode 32 | 33 | {{< twitter_simple 1085870671291310081 >}} 34 | 35 |
36 | 37 | --- 38 | 39 | ## Vimeo Simple Shortcode 40 | 41 | {{< vimeo_simple 48912912 >}} 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 UW Graphics Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /hugo/themes/onedly/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Christian Decker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "relaxed_ik_core" 3 | version = "0.1.0" 4 | authors = ["djrakita ", "yepw "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | nalgebra = {version = "0.30", features = ["serde-serialize"]} 11 | yaml-rust = "0.4" 12 | optimization_engine = { version = "0.7.7", features = ["wasm"] } 13 | ndarray = "0.13.0" 14 | num = "0.2.0" 15 | time = "0.1" 16 | rand = "0.7.2" 17 | parry3d-f64 = "0.8.0" 18 | path-slash = "0.1.2" 19 | lazy_static = "1.4.0" 20 | csv = "1.1.6" 21 | chrono = "0.4.19" 22 | serde = { version = "1.0.136", features = ["derive"] } 23 | dirs = "4.0.0" 24 | urdf-rs = "0.6.7" 25 | k = "0.29" 26 | 27 | # Below are for webassembly 28 | wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } 29 | serde-wasm-bindgen = "0.4" 30 | js-sys = "0.3" 31 | serde_json = "1.0" 32 | console_error_panic_hook = "0.1" 33 | 34 | [dependencies.web-sys] 35 | version = "0.3" 36 | features = [ 37 | "console", 38 | ] 39 | 40 | [profile.dev] 41 | opt-level = 3 42 | 43 | [profile.release] 44 | opt-level = 3 45 | 46 | [lib] 47 | name = "relaxed_ik_lib" 48 | path = "src/lib.rs" 49 | crate-type = ["rlib", "cdylib"] 50 | # path = "src/relaxed_ik_web.rs" 51 | # crate-type = ["cdylib"] 52 | -------------------------------------------------------------------------------- /src/utils_rust/transformations.rs: -------------------------------------------------------------------------------- 1 | use nalgebra::{Vector3, UnitQuaternion, Quaternion, Vector4}; 2 | 3 | pub fn quaternion_log(q: UnitQuaternion) -> Vector3 { 4 | let mut out_vec: Vector3 = Vector3::new(q.i, q.j, q.k); 5 | if q.w.abs() < 1.0 { 6 | let a = q.w.acos(); 7 | let sina = a.sin(); 8 | if sina.abs() >= 0.005 { 9 | let c = a / sina; 10 | out_vec *= c; 11 | } 12 | } 13 | out_vec 14 | } 15 | 16 | pub fn quaternion_exp(v: Vector3) -> UnitQuaternion { 17 | let mut qv: Vector4 = Vector4::new(1.0, v[0], v[1], v[2]); 18 | let a = qv.norm(); 19 | let sina = a.sin(); 20 | if sina.abs() >= 0.005 { 21 | let c = sina/a; 22 | qv *= c; 23 | } 24 | UnitQuaternion::from_quaternion(Quaternion::new(a.cos(), qv[1], qv[2], qv[3])) 25 | } 26 | 27 | pub fn quaternion_disp(q: UnitQuaternion, q_prime: UnitQuaternion) -> Vector3 { 28 | quaternion_log( q.inverse()*q_prime ) 29 | } 30 | 31 | pub fn quaternion_dispQ(q: UnitQuaternion, q_prime: UnitQuaternion) -> UnitQuaternion { 32 | q.inverse()*q_prime 33 | } 34 | 35 | pub fn angle_between_quaternion(q: UnitQuaternion, q_prime: UnitQuaternion) -> f64 { 36 | quaternion_disp(q, q_prime).norm() * 2.0 37 | } 38 | 39 | pub fn quaternion_from_angleaxis(angle: f64, axis: Vector3) -> UnitQuaternion { 40 | let a = angle * 2.0; 41 | let axis_len = axis.norm(); 42 | quaternion_exp( axis * (a / axis_len)) 43 | } 44 | 45 | -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/footer.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 23 | 27 |
28 | 37 |
38 |
39 |
40 | {{ partial "js.html" . }} 41 | 42 | 43 | -------------------------------------------------------------------------------- /hugo/content/post/core.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Core" 3 | description = "Core" 4 | date = "2019-08-07" 5 | author = "" 6 | sec = 2 7 | +++ 8 | 9 | The core part of RelaxedIK and CollisionIK is at [RelaxedIK Core](https://github.com/uwgraphics/relaxed_ik_core). The core contains a Rust implementation of RelaxedIK and CollisionIK with both a library crate and a binary crate. The library crate includes all the kinematics libraries of RelaxedIK, while the binary crate is desgined for the purpose of testing. Since the core is not designed to be run independently in general (although it is runnable), please refer to the Wrappers section and READMEs in those wrapper repos for more information on how to run RelaxedIK or CollisionIK. 10 | 11 | To introduce relaxed_ik_core, let's first talk about the previous iteration of RelaxedIK at [relaxed_ik](https://github.com/uwgraphics/relaxed_ik/tree/dev). There are three parts in this repo: the Rust library of RelaxedIK, a ROS wrapper around it, and a preprocessing toolkit for robot config files needed for RelaxedIK. To make it more convenient to extend RelaxedIK and build all kinds of wrappers around it, we extract the Rust library from that repo to be relaxed_ik_core. Also, to ease the process of setting up a robot arm with RelaxedIK, we decide to exclude the preprocessing toolkit (which is accessible in [relaxed_ik](https://github.com/uwgraphics/relaxed_ik/tree/dev)) from relaxed_ik_core and instead provide all of the pre-generated config files for some mostly used robot manipulators. The list of available robots include baxter, hubo, iiwa7, jaco7, panda, sawyer, ur5, and yumi. Please refer to the READMEs in those repos if you intend to work with a robot not in this list. -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/nav.html: -------------------------------------------------------------------------------- 1 | 2 | 38 | -------------------------------------------------------------------------------- /hugo/content/post/about.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "About" 3 | description = "Project description" 4 | date = "2019-08-07" 5 | author = "" 6 | sec = 1 7 | +++ 8 | 9 | Welcome to RelaxedIK! We implement the methods discussed in our paper [*RelaxedIK: Real-time Synthesis of Accurate and Feasible Robot Arm Motion*](http://www.roboticsproceedings.org/rss14/p43.html) and [*CollisionIK: A Per-Instant Pose Optimization Method for Generating Robot Motions with Environment Collision Avoidance*](https://arxiv.org/abs/2102.13187). 10 | 11 | - Video of presentation at RSS 2018 (RelaxedIK part starts around 12:00): https://youtu.be/bih5e9MHc88?t=737 12 | - Video explaining RelaxedIK: https://youtu.be/AhsQFJzB8WQ 13 | - Video explaining CollisionIK: [Working on it...] 14 | 15 | RelaxedIK is an inverse kinematics (IK) solver designed for robot platforms such that the conversion between Cartesian end-effector pose goals (such as "move the robot's right arm end-effector to position X, while maintaining an end-effector orientation Y") to Joint-Space (i.e., the robot's rotation values for each joint degree-of-freedom at a particular time-point) is done both ACCURATELY and FEASIBLY. By this, we mean that RelaxedIK attempts to find the closest possible solution to the desired end-effector pose goals without exhibiting negative effects such as self-collisions, environment collisions, kinematic-singularities, or joint-space discontinuities. 16 | 17 | CollisionIK is a per-instant pose optimization method that can generate configurations that achieve specified pose or motion objectives as best as possible over a sequence of solutions, while also simultaneously avoiding collisions with static or dynamic obstacles in the environment. CollisionIK extends RelaxedIK by incorporating environment collision avoidance into the optimization structure. -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | {{ if .Title }}{{ .Title }}{{ else }}{{ .Site.Title }}{{ end }} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 39 | 40 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/relaxed_ik.rs: -------------------------------------------------------------------------------- 1 | use crate::groove::vars::RelaxedIKVars; 2 | use crate::groove::groove::{OptimizationEngineOpen}; 3 | use crate::groove::objective_master::ObjectiveMaster; 4 | use crate::utils_rust::file_utils::{*}; 5 | use crate::utils_rust::transformations::{*}; 6 | use nalgebra::{Vector3, UnitQuaternion, Quaternion}; 7 | use std::os::raw::{c_double, c_int}; 8 | 9 | #[repr(C)] 10 | pub struct Opt { 11 | pub data: *const c_double, 12 | pub length: c_int, 13 | } 14 | 15 | pub struct RelaxedIK { 16 | pub vars: RelaxedIKVars, 17 | pub om: ObjectiveMaster, 18 | pub groove: OptimizationEngineOpen 19 | } 20 | 21 | impl RelaxedIK { 22 | pub fn load_settings( path_to_setting: &str) -> Self { 23 | println!("RelaxedIK is using below setting file {}", path_to_setting); 24 | 25 | let vars = RelaxedIKVars::from_local_settings(path_to_setting); 26 | let om = ObjectiveMaster::relaxed_ik(&vars.robot.chain_lengths); 27 | 28 | let groove = OptimizationEngineOpen::new(vars.robot.num_dofs.clone()); 29 | 30 | Self{vars, om, groove} 31 | } 32 | 33 | pub fn reset(&mut self, x: Vec) { 34 | self.vars.reset( x.clone()); 35 | } 36 | 37 | pub fn solve(&mut self) -> Vec { 38 | let mut out_x = self.vars.xopt.clone(); 39 | 40 | 41 | self.groove.optimize(&mut out_x, &self.vars, &self.om, 100); 42 | 43 | let frames = self.vars.robot.get_frames_immutable(&out_x); 44 | 45 | for i in 0..out_x.len() { 46 | if (out_x[i].is_nan()) { 47 | println!("No valid solution found! Returning previous solution: {:?}. End effector position goals: {:?}", self.vars.xopt, self.vars.goal_positions); 48 | return self.vars.xopt.clone(); 49 | } 50 | } 51 | self.vars.update(out_x.clone()); 52 | out_x 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/groove/groove.rs: -------------------------------------------------------------------------------- 1 | use crate::groove::gradient::{ForwardFiniteDiff, CentralFiniteDiff, GradientFinder, ForwardFiniteDiffImmutable, CentralFiniteDiffImmutable, GradientFinderImmutable}; 2 | use crate::groove::vars::{RelaxedIKVars}; 3 | use optimization_engine::{constraints::*, panoc::*, *}; 4 | use crate::groove::objective_master::ObjectiveMaster; 5 | 6 | pub struct OptimizationEngineOpen { 7 | dim: usize, 8 | cache: PANOCCache 9 | } 10 | impl OptimizationEngineOpen { 11 | pub fn new(dim: usize) -> Self { 12 | let mut cache = PANOCCache::new(dim, 1e-14, 10); 13 | OptimizationEngineOpen { dim, cache } 14 | } 15 | 16 | pub fn optimize(&mut self, x: &mut [f64], v: &RelaxedIKVars, om: &ObjectiveMaster, max_iter: usize) { 17 | let df = |u: &[f64], grad: &mut [f64]| -> Result<(), SolverError> { 18 | let (my_obj, my_grad) = om.gradient(u, v); 19 | for i in 0..my_grad.len() { 20 | grad[i] = my_grad[i]; 21 | } 22 | Ok(()) 23 | }; 24 | 25 | let f = |u: &[f64], c: &mut f64| -> Result<(), SolverError> { 26 | *c = om.call(u, v); 27 | Ok(()) 28 | }; 29 | 30 | // let bounds = NoConstraints::new(); 31 | let bounds = Rectangle::new(Option::from(v.robot.lower_joint_limits.as_slice()), Option::from(v.robot.upper_joint_limits.as_slice())); 32 | 33 | /* PROBLEM STATEMENT */ 34 | let problem = Problem::new(&bounds, df, f); 35 | let mut panoc = PANOCOptimizer::new(problem, &mut self.cache).with_max_iter(max_iter).with_tolerance(0.0005); 36 | // let mut panoc = PANOCOptimizer::new(problem, &mut self.cache); 37 | 38 | // Invoke the solver 39 | let status = panoc.solve(x); 40 | 41 | // println!("Panoc status: {:#?}", status); 42 | // println!("Panoc solution: {:#?}", x); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/about.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "About" 3 | description = "Initial project description" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | sec = 1 7 | +++ 8 | 9 | One-Day-Only or OneDly projects help to acquire a new skill or to complete a task within a short timeframe. It limits the available time and combines it with defined objectives. This situation forces you to focus on the relevant elements in order to successfully complete a task or project. Please note, the idea is not to pack as much work as you can do within a workday. At the end you will find answers for the following questions 10 | 11 | * What were the relevant elements for success? 12 | * How good are you in estimating your work effort? 13 | * What were road blocks or even showstoppers you haven't forseen even in a short-term project horizon? 14 | * What are typical reoccuring interuptions and distractions during your work? 15 | * What is your personal pace when working intensly on a task or project? 16 | 17 | 18 | This will certainly generate some personal insights and improve your activities in future projects. 19 | 20 | ### Structuring OneDly Projects 21 | 22 | A single page stores an entire OneDly project documentation. We recommend the following concise structure. 23 | 24 | * About: Some background / intro information motivating the project 25 | * Project Definition 26 | * Goal 27 | * Approach and Objectives 28 | * Sections 29 | * ... 30 | * Summary and Conclusions 31 | * Next steps 32 | 33 | ### Example 34 | 35 | Raspi mini computers are embedded computers running linux and provide a desktop alike programming experiences. They are available at low cost. Being able to develop software for these systems is a valuable contribution to one's CV. 36 | 37 | This OneDly project experiements with the Raspi setup, development and deployment of some example software. 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/emoji-support.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Fun" 3 | description = "Some fun with emoji" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | sec = 6 7 | +++ 8 | 9 | Emoji can be enabled in a Hugo project in a number of ways. 10 | 11 | The [`emojify`](https://gohugo.io/functions/emojify/) function can be called directly in templates or [Inline Shortcodes](https://gohugo.io/templates/shortcode-templates/#inline-shortcodes). 12 | 13 | To enable emoji globally, set `enableEmoji` to `true` in your site’s [configuration](https://gohugo.io/getting-started/configuration/) and then you can type emoji shorthand codes directly in content files; e.g. 14 | 15 | 16 |

🙈 :see_no_evil: 🙉 :hear_no_evil: 🙊 :speak_no_evil:

17 |
18 | 19 | The [Emoji cheat sheet](http://www.emoji-cheat-sheet.com/) is a useful reference for emoji shorthand codes. 20 | 21 | *** 22 | 23 | **N.B.** The above steps enable Unicode Standard emoji characters and sequences in Hugo, however the rendering of these glyphs depends on the browser and the platform. To style the emoji you can either use a third party emoji font or a font stack; e.g. 24 | 25 | {{< highlight html >}} 26 | .emoji { 27 | font-family: Apple Color Emoji,Segoe UI Emoji,NotoColorEmoji,Segoe UI Symbol,Android Emoji,EmojiSymbols; 28 | } 29 | {{< /highlight >}} 30 | 31 | {{< css.inline >}} 32 | 45 | {{< /css.inline >}} -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/coding.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Section" 3 | description = "Some section with content" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | sec = 3 7 | +++ 8 | 9 | _Source: content taken from [hugoBasicExample](https://github.com/gohugoio/hugoBasicExample). File: `markdown-syntax.md`_ 10 | 11 | ## Paragraph 12 | 13 | Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat. 14 | 15 | Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat. 16 | 17 | #### Blockquote with attribution 18 | 19 | > Don't communicate by sharing memory, share memory by communicating.

20 | > — Rob Pike[^1] 21 | 22 | 23 | [^1]: The above quote is excerpted from Rob Pike's [talk](https://www.youtube.com/watch?v=PAAkCSZUG1c) during Gopherfest, November 18, 2015. 24 | 25 | ## Tables 26 | 27 | Tables aren't part of the core Markdown spec, but Hugo supports supports them out-of-the-box. 28 | 29 | Name | Age 30 | --------|------ 31 | Bob | 27 32 | Alice | 23 33 | 34 | 35 | ## Code block with Hugo's internal highlight shortcode 36 | 37 | {{< highlight html >}} 38 | 39 | 40 | 41 | 42 | Example HTML5 Document 43 | 44 | 45 |

Test

46 | 47 | 48 | {{< /highlight >}} 49 | 50 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/post/math-typesetting.mmark: -------------------------------------------------------------------------------- 1 | --- 2 | author: Christian Decker 3 | title: Math Modeling 4 | date: 2019-08-07 5 | description: A brief guide to setup KaTeX 6 | markup: mmark 7 | math: true 8 | sec: 5 9 | --- 10 | 11 | _Source: content taken from [hugoBasicExample](https://github.com/gohugoio/hugoBasicExample). File: `math-typesetting.mmark`_ 12 | 13 | Mathematical notation in a Hugo project can be enabled by using third party JavaScript libraries. 14 | 15 | 16 | In this example we will be using [KaTeX](https://katex.org/) 17 | 18 | - Create a partial under `/layouts/partials/math.html` 19 | - Within this partial reference the [Auto-render Extension](https://katex.org/docs/autorender.html) or host these scripts locally. 20 | - Include the partial in your templates like so: 21 | 22 | ``` 23 | {{ if or .Params.math .Site.Params.math }} 24 | {{ partial "math.html" . }} 25 | {{ end }} 26 | ``` 27 | - To enable KaTex globally set the parameter `math` to `true` in a project's configuration 28 | - To enable KaTex on a per page basis include the parameter `math: true` in content files. 29 | 30 | **Note:** Use the online reference of [Supported TeX Functions](https://katex.org/docs/supported.html) 31 | {{< math.inline >}} 32 | {{ if or .Page.Params.math .Site.Params.math }} 33 | 34 | 35 | 36 | 37 | {{ end }} 38 | {{}} 39 | 40 | ### Examples 41 | 42 | Inline math: $$ \varphi = \dfrac{1+\sqrt5}{2}= 1.6180339887… $$ 43 | 44 | Block math: 45 | 46 | $$ 47 | \varphi = 1+\frac{1} {1+\frac{1} {1+\frac{1} {1+\cdots} } } 48 | $$ 49 | 50 | -------------------------------------------------------------------------------- /hugo/content/post/wrappers.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Wrappers" 3 | description = "Wrappers" 4 | date = "2019-08-07" 5 | author = "" 6 | sec = 3 7 | +++ 8 | 9 | Although the core is runnable, it is not designed to be run alone. Wrappers are recommended to connect RelaxedIK to different interfaces. Here are 4 wrappers that we implemented for ROS, CoppeliaSim, Mujoco, and Unity respectively. Each wrapper has detailed instructions on how to work with them in the READMEs in their repo. If you are interested, it is possible to wrap up the core in other interfaces as well. 10 | 11 | The links to these github repos are here: 12 | 13 | - [RelaxedIK ROS1](https://github.com/uwgraphics/relaxed_ik_ros1) 14 | - [RelaxedIK Unity](https://github.com/uwgraphics/relaxed_ik_unity) 15 | - [RelaxedIK CoppeliaSim](https://github.com/uwgraphics/relaxed_ik_coppeliasim) 16 | - [RelaxedIK Mujoco](https://github.com/uwgraphics/relaxed_ik_mujoco) 17 | 18 | ### [RelaxedIK ROS1](https://github.com/uwgraphics/relaxed_ik_ros1) 19 | - This wrapper has the complete set of features available in the RelaxedIK package and it is also where CollisionIK resides. If you doesn’t have strong preferences over any specific wrapper, you probably should consider this ROS wrapper as the first choice. A keyboard pose goal driver and an rviz viewer are provided for testing purpose. 20 | 21 | ### [RelaxedIK CoppeliaSim](https://github.com/uwgraphics/relaxed_ik_coppeliasim) 22 | - This wrapper is a RelaxedIK plugin for CoppeliaSim. Although it’s possible to access the ROS1 wrapper of RelaxedIK in CoppeliaSim through ROS topics and params, it might be more convenient to directly access RelaxedIK in the form of a CoppeliaSim Pluggin. That’s where the inspiration of this wrapper comes from. If you don't need ROS in your project, this wrapper is designed for you; however, if you need ROS for other parts of your project, it is still recommended to use the ROS wrapper since that one has the complete set of features available. 23 | 24 | ### [RelaxedIK Mujoco](https://github.com/uwgraphics/relaxed_ik_mujoco) 25 | - This wrapper is a RelaxedIK Plugin for MuJoCo. MuJoCo is an advanced physics simulation engine that may have some extra features unavailable in CoppeliaSim. 26 | 27 | ### [RelaxedIK Unity](https://github.com/uwgraphics/relaxed_ik_unity) 28 | - This wrapper allows users to use RelaxedIK in Unity. This is designed to work on Windows and it probably won’t work on a Linux machine. A few commonly used simulated robot arms have already been set up for you to play with. In the simulation, you will be able to disable or enable RelaxedIK as you like. When RelaxedIK is disabled, a joint angle writer panel will show up for you to adjust and visualize the joint angle configuration. When RelaxedIK is enabled, you will be able to have real-time interactions with RelaxedIK by dragging the transform gizmo associated with the gripper of the robot. 29 | 30 | Unity screenshot 31 |

RelaxedIK Unity

-------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/share-links.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ if .Site.Params.socialShareTwitter | default true}} 9 |
  • 10 | 11 | 12 | 13 |
  • 14 | {{ end }} 15 | 16 | 17 | {{ if .Site.Params.socialShareGoogleplus | default true}} 18 |
  • 19 | 20 | 21 | 22 |
  • 23 | {{ end }} 24 | 25 | 26 | {{ if .Site.Params.socialShareFacebook | default true}} 27 | 28 |
  • 29 | 30 | 31 | 32 |
  • 33 | {{ end }} 34 | 35 | 36 | {{ if .Site.Params.socialShareReddit | default true}} 37 |
  • 38 | 39 | 40 | 41 |
  • 42 | {{ end }} 43 | 44 | 45 | {{ if .Site.Params.socialShareLinkedin | default true}} 46 |
  • 47 | 48 | 49 | 50 |
  • 51 | {{ end }} 52 | 53 | 54 | {{ if .Site.Params.socialShareStumbleupon | default true}} 55 |
  • 56 | 57 | 58 | 59 |
  • 60 | {{ end }} 61 | 62 | 63 | {{ if .Site.Params.socialSharePinterest | default true}} 64 |
  • 65 | 66 | 67 | 68 |
  • 69 | {{ end }} 70 | 71 | 72 | {{ if .Site.Params.socialShareEmail | default true}} 73 |
  • 74 | 75 | 76 | 77 |
  • 78 | {{ end }} 79 | -------------------------------------------------------------------------------- /docs/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Relaxed IK 5 | / 6 | Recent content on Relaxed IK 7 | Hugo -- gohugo.io 8 | en-us 9 | Wed, 07 Aug 2019 00:00:00 +0000 10 | 11 | About 12 | /post/about/ 13 | Wed, 07 Aug 2019 00:00:00 +0000 14 | 15 | /post/about/ 16 | Welcome to RelaxedIK! We implement the methods discussed in our paper RelaxedIK: Real-time Synthesis of Accurate and Feasible Robot Arm Motion and CollisionIK: A Per-Instant Pose Optimization Method for Generating Robot Motions with Environment Collision Avoidance. 17 | Video of presentation at RSS 2018 (RelaxedIK part starts around 12:00): https://youtu.be/bih5e9MHc88?t=737 Video explaining RelaxedIK: https://youtu.be/AhsQFJzB8WQ Video explaining CollisionIK: [Working on it&hellip;] RelaxedIK is an inverse kinematics (IK) solver designed for robot platforms such that the conversion between Cartesian end-effector pose goals (such as &ldquo;move the robot&rsquo;s right arm end-effector to position X, while maintaining an end-effector orientation Y&rdquo;) to Joint-Space (i. 18 | 19 | 20 | 21 | Contact 22 | /post/contact/ 23 | Wed, 07 Aug 2019 00:00:00 +0000 24 | 25 | /post/contact/ 26 | If you have any comments or questions on any of this, or if you encounter any bugs in the wrappers of the solver, feel free to post an issue or email me directly at rakita@cs.wisc.edu. 27 | 28 | 29 | 30 | Core 31 | /post/core/ 32 | Wed, 07 Aug 2019 00:00:00 +0000 33 | 34 | /post/core/ 35 | The core part of RelaxedIK and CollisionIK is at RelaxedIK Core. The core contains a Rust implementation of RelaxedIK and CollisionIK with both a library crate and a binary crate. The library crate includes all the kinematics libraries of RelaxedIK, while the binary crate is desgined for the purpose of testing. Since the core is not designed to be run independently in general (although it is runnable), please refer to the Wrappers section and READMEs in those wrapper repos for more information on how to run RelaxedIK or CollisionIK. 36 | 37 | 38 | 39 | Wrappers 40 | /post/wrappers/ 41 | Wed, 07 Aug 2019 00:00:00 +0000 42 | 43 | /post/wrappers/ 44 | Although the core is runnable, it is usually not intended to be run alone. Wrappers are required to connect RelaxedIK to different interfaces. Here are 4 wrappers that we implemented for ROS, CoppeliaSim, Mujoco, and Unity respectively. Each wrapper has detailed instructions on how to work with them in the READMEs in their repo. If you are interested, it is possible to wrap up the core in other interfaces as well. 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/post/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sections on Relaxed IK 5 | /post/ 6 | Recent content in Sections on Relaxed IK 7 | Hugo -- gohugo.io 8 | en-us 9 | Wed, 07 Aug 2019 00:00:00 +0000 10 | 11 | About 12 | /post/about/ 13 | Wed, 07 Aug 2019 00:00:00 +0000 14 | 15 | /post/about/ 16 | Welcome to RelaxedIK! We implement the methods discussed in our paper RelaxedIK: Real-time Synthesis of Accurate and Feasible Robot Arm Motion and CollisionIK: A Per-Instant Pose Optimization Method for Generating Robot Motions with Environment Collision Avoidance. 17 | Video of presentation at RSS 2018 (RelaxedIK part starts around 12:00): https://youtu.be/bih5e9MHc88?t=737 Video explaining RelaxedIK: https://youtu.be/AhsQFJzB8WQ Video explaining CollisionIK: [Working on it&hellip;] RelaxedIK is an inverse kinematics (IK) solver designed for robot platforms such that the conversion between Cartesian end-effector pose goals (such as &ldquo;move the robot&rsquo;s right arm end-effector to position X, while maintaining an end-effector orientation Y&rdquo;) to Joint-Space (i. 18 | 19 | 20 | 21 | Contact 22 | /post/contact/ 23 | Wed, 07 Aug 2019 00:00:00 +0000 24 | 25 | /post/contact/ 26 | If you have any comments or questions on any of this, or if you encounter any bugs in the wrappers of the solver, feel free to post an issue or email me directly at rakita@cs.wisc.edu. 27 | 28 | 29 | 30 | Core 31 | /post/core/ 32 | Wed, 07 Aug 2019 00:00:00 +0000 33 | 34 | /post/core/ 35 | The core part of RelaxedIK and CollisionIK is at RelaxedIK Core. The core contains a Rust implementation of RelaxedIK and CollisionIK with both a library crate and a binary crate. The library crate includes all the kinematics libraries of RelaxedIK, while the binary crate is desgined for the purpose of testing. Since the core is not designed to be run independently in general (although it is runnable), please refer to the Wrappers section and READMEs in those wrapper repos for more information on how to run RelaxedIK or CollisionIK. 36 | 37 | 38 | 39 | Wrappers 40 | /post/wrappers/ 41 | Wed, 07 Aug 2019 00:00:00 +0000 42 | 43 | /post/wrappers/ 44 | Although the core is runnable, it is usually not intended to be run alone. Wrappers are required to connect RelaxedIK to different interfaces. Here are 4 wrappers that we implemented for ROS, CoppeliaSim, Mujoco, and Unity respectively. Each wrapper has detailed instructions on how to work with them in the READMEs in their repo. If you are interested, it is possible to wrap up the core in other interfaces as well. 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/content/imprint-gdpr/imprint.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Imprint" 3 | description = "Imprint information" 4 | date = "2019-08-07" 5 | author = "Christian Decker" 6 | +++ 7 | 8 | Information according to § 5 TMG 9 | 10 | _first and last name_ 11 | _address_ 12 | 13 | #### Contact: 14 | Phone: _phone number_ 15 | E-Mail: _e-mail address_ 16 | 17 | #### Responsible for content according to § 55 Abs. 2 RStV: 18 | 19 | _first and last name_ 20 | _address_ 21 | 22 | #### Disclaimer: 23 | 24 | #### Content Liability 25 | 26 | The contents of our pages were created with great care. However, we can not assume any liability for the accuracy, completeness and timeliness of the content. As a service provider we are responsible according to § 7 Abs.1 TMG for own contents on these sides according to the general laws. According to §§ 8 to 10 TMG, however, we as a service provider are not obliged to monitor transmitted or stored external information or to investigate circumstances that indicate illegal activity. Obligations to remove or block the use of information under general law remain unaffected. A liability in this regard, however, is only possible from the date of knowledge of a specific infringement. Upon notification of such violations, we will remove this content immediately. 27 | 28 | #### Liability for links 29 | 30 | Our offer contains links to external websites of third parties on whose contents we have no influence. Therefore, we can not assume any liability for these external contents. The respective provider or operator of the pages is always responsible for the contents of the linked pages. The linked pages were checked for possible legal violations at the time of linking. Illegal content was not recognizable at the time of linking. However, a permanent content control of the linked pages is not reasonable without concrete evidence of an infringement. Upon notification of violations, we will remove such links immediately. 31 | 32 | #### Copyright 33 | 34 | The content and works on these pages created by the site operators are subject to German copyright law. The reproduction, processing, distribution and any kind of exploitation outside the limits of copyright require the written consent of the respective author or creator. Downloads and copies of this site are for private, non-commercial use only. As far as the contents on this side were not created by the operator, the copyrights of third parties are considered. In particular contents of third parties are marked as such. If you should still be aware of a copyright infringement, we ask for a note. Upon discovery of violations, we will remove such content immediately. 35 | 36 | #### Privacy Policy 37 | 38 | The use of our website is usually possible without providing personal information. As far as on our sides personal data (for example name, address or eMail addresses) are raised, this takes place, as far as possible, always on freiwilliger basis. These data will not be disclosed to third parties without your explicit consent. 39 | Please note that data transmission over the Internet (for example, when communicating via e-mail) may have security vulnerabilities. A complete protection of the data from access by third parties is not possible. 40 | The use of contact data published in the context of the imprint obligation by third parties for sending unsolicited advertising and information materials is hereby expressly excluded. The operators of the pages expressly reserve the right to take legal action in case of unsolicited promotional information, such as spam e-mails. 41 | 42 | Website Imprint generated by [impressum-generator.de](http://www.impressum-generator.de/) and afterwards translated using Google Translate. 43 | -------------------------------------------------------------------------------- /hugo/themes/onedly/exampleSite/config.toml: -------------------------------------------------------------------------------- 1 | baseurl = "https://example.com/" 2 | languageCode = "en-us" 3 | title = "OneDly Project" 4 | theme = "onedly" 5 | 6 | # 7 | # Personalization params 8 | # 9 | [params] 10 | # project specific params 11 | description = "One-Day-Only (OneDly) project documentation." 12 | author_url = "//cdeck3r.com" 13 | author_name = "cdeck3r" 14 | project_url = "//github.com/cdeck3r/OneDly-Theme" 15 | 16 | # optionally specify where the content is 17 | # mainSections = ["post"] 18 | 19 | # social share links to appear at the end 20 | socialShare = true 21 | # Sets specific share to appear on posts (default behavior is to appear) 22 | socialShareTwitter = true 23 | socialShareGoogleplus = true 24 | socialShareFacebook = true 25 | socialShareReddit = true 26 | socialShareLinkedin = true 27 | socialShareStumbleupon = true 28 | socialSharePinterest = true 29 | socialShareEmail = true 30 | 31 | # theme's color scheme 32 | first_color="#f8f8f8" 33 | first_border_color="#e7e7e7" 34 | first_text_color="#333" 35 | 36 | second_color="white" 37 | second_text_color="#333" 38 | 39 | header_color="#f8f8f8" 40 | header_text_color="rgb(51, 51, 51)" 41 | 42 | header_link_color="#777" 43 | header_link_hover_color="rgb(51, 51, 51)" 44 | 45 | # 46 | # Sets Social Media icons to appear and link to your account. Value should be your 47 | # username unless otherwise noted. Icons appear at the top of the page. 48 | # 49 | [social] 50 | # Coding Communities 51 | github = "cdeck3r/OneDly-Theme" 52 | gitlab = "" 53 | stackoverflow = "" # User Number 54 | bitbucket = "" 55 | jsfiddle = "" 56 | codepen = "" 57 | # Visual Art Communities 58 | deviantart = "" 59 | flickr = "" 60 | behance = "" 61 | dribbble = "" 62 | # Publishing Communities 63 | wordpress = "" 64 | medium = "" 65 | # Professional/Business Oriented Communities 66 | linkedin = "" 67 | linkedin_company = "" 68 | foursquare = "" 69 | xing = "" 70 | slideshare = "" 71 | # Social Networks 72 | facebook = "" 73 | googleplus = "" 74 | reddit = "" 75 | quora = "" 76 | youtube = "channel/UCZ5wNVV_E6AA3L3C-mvqwSA" 77 | vimeo = "" 78 | whatsapp = "" # WhatsApp Number 79 | # WeChat and QQ need testing. 80 | wechat = "" 81 | qq = "" # User ID Number 82 | instagram = "" 83 | tumblr = "" 84 | twitter = "cdeck3r" 85 | skype = "" 86 | snapchat = "" 87 | pinterest = "" 88 | telegram = "" 89 | vine = "" 90 | googlescholar = "" 91 | orcid = "" 92 | researchgate = "" 93 | # Email 94 | email = "info@cdeck3r.com" 95 | 96 | # 97 | # Adjust privacy settings 98 | # See: https://gohugo.io/about/hugo-and-gdpr/ 99 | # 100 | [privacy] 101 | [privacy.disqus] 102 | disable = true 103 | 104 | [privacy.googleAnalytics] 105 | disable = true 106 | anonymizeIP = true 107 | respectDoNotTrack = true 108 | useSessionStorage = true 109 | 110 | [privacy.instagram] 111 | disable = false 112 | simple = true 113 | 114 | [privacy.twitter] 115 | disable = false 116 | enableDNT = true 117 | simple = true 118 | 119 | [privacy.vimeo] 120 | disable = true 121 | simple = true 122 | 123 | [privacy.youtube] 124 | disable = false 125 | privacyEnhanced = true 126 | 127 | # 128 | # In simple mode for Instagram and a site styled with Bootstrap 4, 129 | # you may want to disable the inlines styles provided by Hugo: 130 | # See: https://gohugo.io/about/hugo-and-gdpr/ 131 | # 132 | [services] 133 | [services.instagram] 134 | disableInlineCSS = true 135 | 136 | [services.twitter] 137 | disableInlineCSS = true 138 | 139 | -------------------------------------------------------------------------------- /hugo/config.toml: -------------------------------------------------------------------------------- 1 | baseurl = "" 2 | languageCode = "en-us" 3 | title = "Relaxed IK" 4 | theme = "onedly" 5 | 6 | # 7 | # Personalization params 8 | # 9 | [params] 10 | # project specific params 11 | description = "An inverse kinematics (IK) solver" 12 | author_url = "http://pages.cs.wisc.edu/~rakita/" 13 | author_name = "Daniel Rakita" 14 | project_url = "https://github.com/uwgraphics/relaxed_ik_core" 15 | 16 | # optionally specify where the content is 17 | # mainSections = ["post"] 18 | 19 | # social share links to appear at the end 20 | socialShare = false 21 | # Sets specific share to appear on posts (default behavior is to appear) 22 | socialShareTwitter = false 23 | socialShareGoogleplus = false 24 | socialShareFacebook = false 25 | socialShareReddit = false 26 | socialShareLinkedin = false 27 | socialShareStumbleupon = false 28 | socialSharePinterest = false 29 | socialShareEmail = false 30 | 31 | # theme's color scheme 32 | first_color="white" 33 | first_border_color="#e7e7e7" 34 | first_text_color="#333" 35 | 36 | second_color="white" 37 | second_text_color="#333" 38 | 39 | header_color="#f8f8f8" 40 | header_text_color="rgb(51, 51, 51)" 41 | 42 | header_link_color="#777" 43 | header_link_hover_color="rgb(51, 51, 51)" 44 | 45 | # 46 | # Sets Social Media icons to appear and link to your account. Value should be your 47 | # username unless otherwise noted. Icons appear at the top of the page. 48 | # 49 | [social] 50 | # Coding Communities 51 | github = "uwgraphics/relaxed_ik_core" 52 | gitlab = "" 53 | stackoverflow = "" # User Number 54 | bitbucket = "" 55 | jsfiddle = "" 56 | codepen = "" 57 | # Visual Art Communities 58 | deviantart = "" 59 | flickr = "" 60 | behance = "" 61 | dribbble = "" 62 | # Publishing Communities 63 | wordpress = "" 64 | medium = "" 65 | # Professional/Business Oriented Communities 66 | linkedin = "" 67 | linkedin_company = "" 68 | foursquare = "" 69 | xing = "" 70 | slideshare = "" 71 | # Social Networks 72 | facebook = "" 73 | googleplus = "" 74 | reddit = "" 75 | quora = "" 76 | youtube = "watch?v=AhsQFJzB8WQ&feature=youtu.be" 77 | vimeo = "" 78 | whatsapp = "" # WhatsApp Number 79 | # WeChat and QQ need testing. 80 | wechat = "" 81 | qq = "" # User ID Number 82 | instagram = "" 83 | tumblr = "" 84 | twitter = "" 85 | skype = "" 86 | snapchat = "" 87 | pinterest = "" 88 | telegram = "" 89 | vine = "" 90 | googlescholar = "" 91 | orcid = "" 92 | researchgate = "" 93 | # Email 94 | email = "rakita@cs.wisc.edu" 95 | 96 | # 97 | # Adjust privacy settings 98 | # See: https://gohugo.io/about/hugo-and-gdpr/ 99 | # 100 | [privacy] 101 | [privacy.disqus] 102 | disable = true 103 | 104 | [privacy.googleAnalytics] 105 | disable = true 106 | anonymizeIP = true 107 | respectDoNotTrack = true 108 | useSessionStorage = true 109 | 110 | [privacy.instagram] 111 | disable = true 112 | simple = true 113 | 114 | [privacy.twitter] 115 | disable = true 116 | enableDNT = true 117 | simple = true 118 | 119 | [privacy.vimeo] 120 | disable = true 121 | simple = true 122 | 123 | [privacy.youtube] 124 | disable = true 125 | privacyEnhanced = true 126 | 127 | # 128 | # In simple mode for Instagram and a site styled with Bootstrap 4, 129 | # you may want to disable the inlines styles provided by Hugo: 130 | # See: https://gohugo.io/about/hugo-and-gdpr/ 131 | # 132 | [services] 133 | [services.instagram] 134 | disableInlineCSS = true 135 | 136 | [services.twitter] 137 | disableInlineCSS = true 138 | 139 | [markup] 140 | defaultMarkdownHandler = "blackfriday" 141 | -------------------------------------------------------------------------------- /wrappers/python_wrapper.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import ctypes 4 | import os 5 | 6 | class Opt(ctypes.Structure): 7 | _fields_ = [("data", ctypes.POINTER(ctypes.c_double)), ("length", ctypes.c_int)] 8 | 9 | class RelaxedIKS(ctypes.Structure): 10 | pass 11 | 12 | dir_path = os.path.dirname(os.path.realpath(__file__)) 13 | lib = ctypes.cdll.LoadLibrary(dir_path + '/../target/debug/librelaxed_ik_lib.so') 14 | 15 | lib.relaxed_ik_new.restype = ctypes.POINTER(RelaxedIKS) 16 | lib.solve.argtypes = [ctypes.POINTER(RelaxedIKS), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_double)] 17 | lib.solve.restype = Opt 18 | lib.solve_position.argtypes = [ctypes.POINTER(RelaxedIKS), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_double), ctypes.c_int] 19 | lib.solve_position.restype = Opt 20 | lib.solve_velocity.argtypes = [ctypes.POINTER(RelaxedIKS), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_double), ctypes.c_int] 21 | lib.solve_velocity.restype = Opt 22 | lib.reset.argtypes = [ctypes.POINTER(RelaxedIKS)] 23 | 24 | class RelaxedIKRust: 25 | def __init__(self, setting_file_path = None): 26 | ''' 27 | setting_file_path (string): path to the setting file 28 | if no path is given, the default setting file will be used 29 | /configs/settings.yaml 30 | ''' 31 | if setting_file_path is None: 32 | self.obj = lib.relaxed_ik_new(ctypes.c_char_p()) 33 | else: 34 | self.obj = lib.relaxed_ik_new(ctypes.c_char_p(setting_file_path.encode('utf-8'))) 35 | 36 | def __exit__(self, exc_type, exc_value, traceback): 37 | lib.relaxed_ik_free(self.obj) 38 | 39 | def solve_position(self, positions, orientations, tolerances): 40 | ''' 41 | Assuming the robot has N end-effectors 42 | positions (1D array with length as 3*N): list of end-effector positions 43 | orientations (1D array with length as 4*N): list of end-effector orientations (in quaternion xyzw format) 44 | tolerances (1D array with length as 6*N): list of tolerances for each end-effector (x, y, z, rx, ry, rz) 45 | ''' 46 | pos_arr = (ctypes.c_double * len(positions))() 47 | quat_arr = (ctypes.c_double * len(orientations))() 48 | tole_arr = (ctypes.c_double * len(tolerances))() 49 | for i in range(len(positions)): 50 | pos_arr[i] = positions[i] 51 | for i in range(len(orientations)): 52 | quat_arr[i] = orientations[i] 53 | for i in range(len(tolerances)): 54 | tole_arr[i] = tolerances[i] 55 | xopt = lib.solve_position(self.obj, pos_arr, len(pos_arr), quat_arr, len(quat_arr), tole_arr, len(tole_arr)) 56 | return xopt.data[:xopt.length] 57 | 58 | def solve_velocity(self, linear_velocities, angular_velocities, tolerances): 59 | ''' 60 | Assuming the robot has N end-effectors 61 | linear_velocities (1D array with length as 3*N): list of end-effector linear velocities 62 | angular_velocities (1D array with length as 4*N): list of end-effector angular velocities 63 | tolerances (1D array with length as 6*N): list of tolerances for each end-effector (x, y, z, rx, ry, rz) 64 | ''' 65 | linear_arr = (ctypes.c_double * len(linear_velocities))() 66 | angular_arr = (ctypes.c_double * len(angular_velocities))() 67 | tole_arr = (ctypes.c_double * len(tolerances))() 68 | for i in range(len(linear_velocities)): 69 | linear_arr[i] = linear_velocities[i] 70 | for i in range(len(angular_velocities)): 71 | angular_arr[i] = angular_velocities[i] 72 | for i in range(len(tolerances)): 73 | tole_arr[i] = tolerances[i] 74 | xopt = lib.solve_velocity(self.obj, linear_arr, len(linear_arr), angular_arr, len(angular_arr), tole_arr, len(tole_arr)) 75 | return xopt.data[:xopt.length] 76 | 77 | def reset(self, joint_state): 78 | js_arr = (ctypes.c_double * len(joint_state))() 79 | for i in range(len(joint_state)): 80 | js_arr[i] = joint_state[i] 81 | lib.reset(self.obj, js_arr, len(js_arr)) 82 | 83 | if __name__ == '__main__': 84 | pass 85 | -------------------------------------------------------------------------------- /docs/post/faq/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | FAQs 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 72 | 73 | 74 | 75 | 76 | 77 | 113 | 114 | 115 |
    116 |
    117 | 118 |
    119 | 120 |
    121 |
    122 |
    123 |
    124 |

    FAQs

    125 |

    Q:

    126 | 127 |

    A:

    128 | 129 |
    130 |
    131 | 132 |
    133 |
    134 | 135 |
    136 | 137 |
    138 |
    139 |
    140 |
    141 | 148 | 152 |
    153 | 154 |
    155 |
    156 |
    157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /src/relaxed_ik_web.rs: -------------------------------------------------------------------------------- 1 | 2 | use crate::groove::vars::{RelaxedIKVars, VarsConstructorData}; 3 | use crate::groove::groove::{OptimizationEngineOpen}; 4 | use crate::groove::objective_master::ObjectiveMaster; 5 | use crate::utils_rust::transformations::{*}; 6 | use wasm_bindgen::prelude::*; 7 | use js_sys::Array; 8 | extern crate serde_json; 9 | use web_sys; 10 | extern crate console_error_panic_hook; 11 | use nalgebra::{UnitQuaternion, Vector3, Vector6, Quaternion, Point3}; 12 | 13 | #[wasm_bindgen] 14 | pub struct RelaxedIK { 15 | pub(crate) vars: RelaxedIKVars, 16 | pub(crate) om: ObjectiveMaster, 17 | pub(crate) groove: OptimizationEngineOpen 18 | } 19 | 20 | #[wasm_bindgen] 21 | impl RelaxedIK { 22 | #[wasm_bindgen(constructor)] 23 | pub fn new( configs: JsValue, urdf: String) -> Self { 24 | console_error_panic_hook::set_once(); 25 | 26 | let cfg: VarsConstructorData = serde_wasm_bindgen::from_value(configs).unwrap(); 27 | 28 | let vars = RelaxedIKVars::from_jsvalue(cfg, &urdf); 29 | 30 | let om = ObjectiveMaster::relaxed_ik(&vars.robot.chain_lengths); 31 | let groove = OptimizationEngineOpen::new(vars.robot.num_dofs.clone()); 32 | Self{vars, om, groove} 33 | } 34 | 35 | pub fn reset(&mut self, init_state: JsValue) { 36 | let starting_config = if init_state.is_null() || init_state.is_undefined() { 37 | self.vars.init_state.clone() 38 | } else { 39 | let tmp: Vec = serde_wasm_bindgen::from_value(init_state).unwrap(); 40 | if tmp.len() != self.vars.robot.num_dofs { 41 | self.vars.init_state.clone() 42 | } else { 43 | tmp 44 | } 45 | }; 46 | 47 | self.vars.reset( starting_config.clone()); 48 | } 49 | 50 | pub fn solve_position(&mut self, pos_goal: JsValue, quat_goal: JsValue, tolerance: JsValue) -> Array{ 51 | self.solve_position_helper(pos_goal, quat_goal, tolerance, false) 52 | } 53 | 54 | pub fn solve_position_relative(&mut self, pos_goal: JsValue, quat_goal: JsValue, tolerance: JsValue) -> Array{ 55 | self.solve_position_helper(pos_goal, quat_goal, tolerance, true) 56 | } 57 | 58 | pub fn solve(&mut self, pos_goal: JsValue, quat_goal: JsValue) -> Array{ 59 | self.solve_position_relative(pos_goal, quat_goal, JsValue::undefined()) 60 | } 61 | } 62 | 63 | impl RelaxedIK { 64 | 65 | pub fn solve_position_helper(&mut self, pos_goal: JsValue, quat_goal: JsValue, tolerance: JsValue, relative: bool) -> Array{ 66 | 67 | let pos_vec: Vec = serde_wasm_bindgen::from_value(pos_goal).unwrap(); 68 | let quat_vec: Vec = serde_wasm_bindgen::from_value(quat_goal).unwrap(); 69 | 70 | let mut tole_vec = if tolerance.is_null() || tolerance.is_undefined() { 71 | vec![0.0; self.vars.robot.num_chains * 6] 72 | } else { 73 | serde_wasm_bindgen::from_value(tolerance).unwrap() 74 | }; 75 | 76 | let mut pos_goals: Vec> = Vec::new(); 77 | let mut quat_goals: Vec> = Vec::new(); 78 | let mut tolerances: Vec> = Vec::new(); 79 | 80 | for i in 0..self.vars.robot.num_chains { 81 | let pos = Vector3::new(pos_vec[i*3], pos_vec[i*3+1], pos_vec[i*3+2]); 82 | let quat = UnitQuaternion::from_quaternion(Quaternion::new(quat_vec[i*4], quat_vec[i*4+1], quat_vec[i*4+2], quat_vec[i*4+3])); 83 | let tole = Vector6::new(tole_vec[i*6], tole_vec[i*6+1], tole_vec[i*6+2], tole_vec[i*6+3], tole_vec[i*6+4], tole_vec[i*6+5]); 84 | pos_goals.push(pos); 85 | quat_goals.push(quat); 86 | tolerances.push(tole); 87 | } 88 | 89 | let mut out_x = self.vars.xopt.clone(); 90 | 91 | for i in 0..self.vars.robot.num_chains { 92 | if relative { 93 | self.vars.goal_positions[i] = self.vars.init_ee_positions[i] + pos_goals[i]; 94 | self.vars.goal_quats[i] = quat_goals[i] * self.vars.init_ee_quats[i]; 95 | } else { 96 | self.vars.goal_positions[i] = pos_goals[i].clone(); 97 | self.vars.goal_quats[i] = quat_goals[i].clone(); 98 | } 99 | self.vars.tolerances[i] = tolerances[i].clone(); 100 | } 101 | 102 | self.groove.optimize(&mut out_x, &self.vars, &self.om, 100); 103 | self.vars.update(out_x.clone()); 104 | 105 | out_x.into_iter().map(JsValue::from).collect() 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /docs/css/landing-page.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - Landing Page Bootstrap Theme (http://startbootstrap.com) 3 | * Code licensed under the Apache License v2.0. 4 | * For details, see http://www.apache.org/licenses/LICENSE-2.0. 5 | */ 6 | 7 | body, 8 | html { 9 | width: 100%; 10 | height: 100%; 11 | font-size: 16px; 12 | } 13 | 14 | body, 15 | h1, 16 | h2, 17 | h3, 18 | h4, 19 | h5, 20 | h6 { 21 | font-family: -apple-system-headline, 'Helvetica Neue', Helvetica, sans-serif; 22 | } 23 | 24 | .lead { 25 | font-size: 18px; 26 | font-weight: 400; 27 | } 28 | 29 | .intro-header { 30 | padding-top: 40px; 31 | text-align: center; 32 | color: #f8f8f8; 33 | } 34 | 35 | .intro-message { 36 | position: relative; 37 | padding-top: 10%; 38 | padding-bottom: 10%; 39 | color: rgb(51, 51, 51); 40 | } 41 | 42 | .intro-message > h3 { 43 | font-family: Georgia, 'Times New Roman', Times, serif; 44 | font-style: italic; 45 | } 46 | 47 | .intro-message > h1 { 48 | font-family: Georgia, 'Times New Roman', Times, serif; 49 | font-size: 5em; 50 | } 51 | 52 | .intro-divider { 53 | width: 500px; 54 | border-top: 1px solid #f8f8f8; 55 | border-bottom: 1px solid rgba(0,0,0,0.2); 56 | } 57 | 58 | .network-name { 59 | text-transform: uppercase; 60 | font-size: 14px; 61 | font-weight: 400; 62 | letter-spacing: 2px; 63 | } 64 | 65 | .container { 66 | width: 900px; 67 | line-height: 1.6em; 68 | font-family: Georgia, 'Times New Roman', Times, serif; 69 | } 70 | 71 | .header-container { 72 | width: 100%; 73 | } 74 | 75 | .container ul { 76 | line-height: 1.6em; 77 | } 78 | 79 | .container pre { 80 | margin-top: 20px; 81 | margin-bottom: 20px; 82 | line-height: 1.6em; 83 | } 84 | 85 | .container h3 { 86 | margin-top: 30px; 87 | margin-bottom: 15px; 88 | font-family: Georgia, 'Times New Roman', Times, serif; 89 | } 90 | 91 | .content-section-a { 92 | padding: 10px 0; 93 | background-color: #f8f8f8; 94 | } 95 | 96 | .content-section-b { 97 | padding: 10px 0; 98 | } 99 | 100 | .section-heading { 101 | margin-bottom: 25px; 102 | font-family: Georgia, 'Times New Roman', Times, serif; 103 | } 104 | 105 | .section-heading-spacer { 106 | float: left; 107 | width: 200px; 108 | border-top: 3px solid #e7e7e7; 109 | } 110 | 111 | .contact { 112 | padding: 100px 0; 113 | color: #f8f8f8; 114 | background: url(../img/contact-bg.jpg) no-repeat center center; 115 | background-size: cover; 116 | } 117 | 118 | .contact h2 { 119 | margin: 0; 120 | text-shadow: 2px 2px 3px rgba(0,0,0,0.6); 121 | font-size: 3em; 122 | } 123 | 124 | .contact ul { 125 | margin-bottom: 0; 126 | } 127 | 128 | .contact-social-buttons { 129 | float: right; 130 | margin-top: 0; 131 | } 132 | 133 | @media(max-width:1199px) { 134 | ul.contact-social-buttons { 135 | float: left; 136 | margin-top: 15px; 137 | } 138 | } 139 | 140 | @media(max-width:767px) { 141 | .contact h2 { 142 | margin: 0; 143 | text-shadow: 2px 2px 3px rgba(0,0,0,0.6); 144 | font-size: 3em; 145 | } 146 | 147 | ul.contact-social-buttons > li { 148 | display: block; 149 | margin-bottom: 20px; 150 | padding: 0; 151 | } 152 | 153 | ul.contact-social-buttons > li:last-child { 154 | margin-bottom: 0; 155 | } 156 | } 157 | 158 | footer { 159 | padding-top: 20px; 160 | padding-bottom: 50px; 161 | background-color: #f8f8f8; 162 | } 163 | 164 | p.copyright { 165 | margin: 10px 0 0; 166 | } 167 | 168 | @media(max-width:1000px) { 169 | .intro-message { 170 | padding-bottom: 10%; 171 | margin-top: -30px; 172 | } 173 | 174 | .intro-message > h1 { 175 | font-size: 3em; 176 | } 177 | 178 | ul.intro-social-buttons > li { 179 | display: block; 180 | margin-bottom: 20px; 181 | padding: 0; 182 | } 183 | 184 | ul.intro-social-buttons > li:last-child { 185 | margin-bottom: 0; 186 | } 187 | 188 | .intro-divider { 189 | width: 100%; 190 | } 191 | 192 | .container { 193 | width: 80%; 194 | } 195 | 196 | .intro-message { 197 | text-align: center; 198 | } 199 | } 200 | 201 | .intro-image { 202 | height: 100%; 203 | min-height: 380px; 204 | margin-top: 20px; 205 | background: url(../img/intro-bg.svg) no-repeat center center; 206 | background-size: 280px; 207 | } 208 | 209 | .github-btn { 210 | margin-top: 10px; 211 | } 212 | -------------------------------------------------------------------------------- /hugo/themes/onedly/static/css/landing-page.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - Landing Page Bootstrap Theme (http://startbootstrap.com) 3 | * Code licensed under the Apache License v2.0. 4 | * For details, see http://www.apache.org/licenses/LICENSE-2.0. 5 | */ 6 | 7 | body, 8 | html { 9 | width: 100%; 10 | height: 100%; 11 | font-size: 16px; 12 | } 13 | 14 | body, 15 | h1, 16 | h2, 17 | h3, 18 | h4, 19 | h5, 20 | h6 { 21 | font-family: -apple-system-headline, 'Helvetica Neue', Helvetica, sans-serif; 22 | } 23 | 24 | .lead { 25 | font-size: 18px; 26 | font-weight: 400; 27 | } 28 | 29 | .intro-header { 30 | padding-top: 40px; 31 | text-align: center; 32 | color: #f8f8f8; 33 | } 34 | 35 | .intro-message { 36 | position: relative; 37 | padding-top: 10%; 38 | padding-bottom: 10%; 39 | color: rgb(51, 51, 51); 40 | } 41 | 42 | .intro-message > h3 { 43 | font-family: Georgia, 'Times New Roman', Times, serif; 44 | font-style: italic; 45 | } 46 | 47 | .intro-message > h1 { 48 | font-family: Georgia, 'Times New Roman', Times, serif; 49 | font-size: 5em; 50 | } 51 | 52 | .intro-divider { 53 | width: 500px; 54 | border-top: 1px solid #f8f8f8; 55 | border-bottom: 1px solid rgba(0,0,0,0.2); 56 | } 57 | 58 | .network-name { 59 | text-transform: uppercase; 60 | font-size: 14px; 61 | font-weight: 400; 62 | letter-spacing: 2px; 63 | } 64 | 65 | .container { 66 | width: 900px; 67 | line-height: 1.6em; 68 | font-family: Georgia, 'Times New Roman', Times, serif; 69 | } 70 | 71 | .header-container { 72 | width: 100%; 73 | } 74 | 75 | .container ul { 76 | line-height: 1.6em; 77 | } 78 | 79 | .container pre { 80 | margin-top: 20px; 81 | margin-bottom: 20px; 82 | line-height: 1.6em; 83 | } 84 | 85 | .container h3 { 86 | margin-top: 30px; 87 | margin-bottom: 15px; 88 | font-family: Georgia, 'Times New Roman', Times, serif; 89 | } 90 | 91 | .content-section-a { 92 | padding: 10px 0; 93 | background-color: #f8f8f8; 94 | } 95 | 96 | .content-section-b { 97 | padding: 10px 0; 98 | } 99 | 100 | .section-heading { 101 | margin-bottom: 25px; 102 | font-family: Georgia, 'Times New Roman', Times, serif; 103 | } 104 | 105 | .section-heading-spacer { 106 | float: left; 107 | width: 200px; 108 | border-top: 3px solid #e7e7e7; 109 | } 110 | 111 | .contact { 112 | padding: 100px 0; 113 | color: #f8f8f8; 114 | background: url(../img/contact-bg.jpg) no-repeat center center; 115 | background-size: cover; 116 | } 117 | 118 | .contact h2 { 119 | margin: 0; 120 | text-shadow: 2px 2px 3px rgba(0,0,0,0.6); 121 | font-size: 3em; 122 | } 123 | 124 | .contact ul { 125 | margin-bottom: 0; 126 | } 127 | 128 | .contact-social-buttons { 129 | float: right; 130 | margin-top: 0; 131 | } 132 | 133 | @media(max-width:1199px) { 134 | ul.contact-social-buttons { 135 | float: left; 136 | margin-top: 15px; 137 | } 138 | } 139 | 140 | @media(max-width:767px) { 141 | .contact h2 { 142 | margin: 0; 143 | text-shadow: 2px 2px 3px rgba(0,0,0,0.6); 144 | font-size: 3em; 145 | } 146 | 147 | ul.contact-social-buttons > li { 148 | display: block; 149 | margin-bottom: 20px; 150 | padding: 0; 151 | } 152 | 153 | ul.contact-social-buttons > li:last-child { 154 | margin-bottom: 0; 155 | } 156 | } 157 | 158 | footer { 159 | padding-top: 20px; 160 | padding-bottom: 50px; 161 | background-color: #f8f8f8; 162 | } 163 | 164 | p.copyright { 165 | margin: 10px 0 0; 166 | } 167 | 168 | @media(max-width:1000px) { 169 | .intro-message { 170 | padding-bottom: 10%; 171 | margin-top: -30px; 172 | } 173 | 174 | .intro-message > h1 { 175 | font-size: 3em; 176 | } 177 | 178 | ul.intro-social-buttons > li { 179 | display: block; 180 | margin-bottom: 20px; 181 | padding: 0; 182 | } 183 | 184 | ul.intro-social-buttons > li:last-child { 185 | margin-bottom: 0; 186 | } 187 | 188 | .intro-divider { 189 | width: 100%; 190 | } 191 | 192 | .container { 193 | width: 80%; 194 | } 195 | 196 | .intro-message { 197 | text-align: center; 198 | } 199 | } 200 | 201 | .intro-image { 202 | height: 100%; 203 | min-height: 380px; 204 | margin-top: 20px; 205 | background: url(../img/intro-bg.svg) no-repeat center center; 206 | background-size: 280px; 207 | } 208 | 209 | .github-btn { 210 | margin-top: 10px; 211 | } 212 | -------------------------------------------------------------------------------- /docs/post/contact/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | Contact 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 72 | 73 | 74 | 75 | 76 | 77 | 113 | 114 | 115 |
    116 |
    117 | 118 |
    119 | 120 |
    121 |
    122 |
    123 |
    124 |

    Contact

    125 |

    If you have any comments or questions on any of this, or if you encounter any bugs in the wrappers of the solver, feel free to post an issue or email me directly at rakita@cs.wisc.edu.

    126 | 127 |
    128 |
    129 | 130 |
    131 |
    132 | 133 |
    134 | 135 |
    136 |
    137 |
    138 |
    139 | 146 | 150 |
    151 | 152 |
    153 |
    154 |
    155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /docs/js/jquery.easing.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 3 | * 4 | * Uses the built in easing capabilities added In jQuery 1.1 5 | * to offer multiple easing options 6 | * 7 | * TERMS OF USE - EASING EQUATIONS 8 | * 9 | * Open source under the BSD License. 10 | * 11 | * Copyright © 2001 Robert Penner 12 | * All rights reserved. 13 | * 14 | * TERMS OF USE - jQuery Easing 15 | * 16 | * Open source under the BSD License. 17 | * 18 | * Copyright © 2008 George McGinley Smith 19 | * All rights reserved. 20 | * 21 | * Redistribution and use in source and binary forms, with or without modification, 22 | * are permitted provided that the following conditions are met: 23 | * 24 | * Redistributions of source code must retain the above copyright notice, this list of 25 | * conditions and the following disclaimer. 26 | * Redistributions in binary form must reproduce the above copyright notice, this list 27 | * of conditions and the following disclaimer in the documentation and/or other materials 28 | * provided with the distribution. 29 | * 30 | * Neither the name of the author nor the names of contributors may be used to endorse 31 | * or promote products derived from this software without specific prior written permission. 32 | * 33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 34 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 35 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 36 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 37 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 38 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 39 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 41 | * OF THE POSSIBILITY OF SUCH DAMAGE. 42 | * 43 | */ 44 | jQuery.easing.jswing=jQuery.easing.swing;jQuery.extend(jQuery.easing,{def:"easeOutQuad",swing:function(e,f,a,h,g){return jQuery.easing[jQuery.easing.def](e,f,a,h,g)},easeInQuad:function(e,f,a,h,g){return h*(f/=g)*f+a},easeOutQuad:function(e,f,a,h,g){return -h*(f/=g)*(f-2)+a},easeInOutQuad:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f+a}return -h/2*((--f)*(f-2)-1)+a},easeInCubic:function(e,f,a,h,g){return h*(f/=g)*f*f+a},easeOutCubic:function(e,f,a,h,g){return h*((f=f/g-1)*f*f+1)+a},easeInOutCubic:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f+a}return h/2*((f-=2)*f*f+2)+a},easeInQuart:function(e,f,a,h,g){return h*(f/=g)*f*f*f+a},easeOutQuart:function(e,f,a,h,g){return -h*((f=f/g-1)*f*f*f-1)+a},easeInOutQuart:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f+a}return -h/2*((f-=2)*f*f*f-2)+a},easeInQuint:function(e,f,a,h,g){return h*(f/=g)*f*f*f*f+a},easeOutQuint:function(e,f,a,h,g){return h*((f=f/g-1)*f*f*f*f+1)+a},easeInOutQuint:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f*f+a}return h/2*((f-=2)*f*f*f*f+2)+a},easeInSine:function(e,f,a,h,g){return -h*Math.cos(f/g*(Math.PI/2))+h+a},easeOutSine:function(e,f,a,h,g){return h*Math.sin(f/g*(Math.PI/2))+a},easeInOutSine:function(e,f,a,h,g){return -h/2*(Math.cos(Math.PI*f/g)-1)+a},easeInExpo:function(e,f,a,h,g){return(f==0)?a:h*Math.pow(2,10*(f/g-1))+a},easeOutExpo:function(e,f,a,h,g){return(f==g)?a+h:h*(-Math.pow(2,-10*f/g)+1)+a},easeInOutExpo:function(e,f,a,h,g){if(f==0){return a}if(f==g){return a+h}if((f/=g/2)<1){return h/2*Math.pow(2,10*(f-1))+a}return h/2*(-Math.pow(2,-10*--f)+2)+a},easeInCirc:function(e,f,a,h,g){return -h*(Math.sqrt(1-(f/=g)*f)-1)+a},easeOutCirc:function(e,f,a,h,g){return h*Math.sqrt(1-(f=f/g-1)*f)+a},easeInOutCirc:function(e,f,a,h,g){if((f/=g/2)<1){return -h/2*(Math.sqrt(1-f*f)-1)+a}return h/2*(Math.sqrt(1-(f-=2)*f)+1)+a},easeInElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | Core 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 72 | 73 | 74 | 75 | 76 | 77 | 113 | 114 | 115 |
    116 |
    117 | 118 |
    119 | 120 |
    121 |
    122 |
    123 |
    124 |

    Core

    125 |

    The core part of RelaxedIK and CollisionIK is at RelaxedIK Core. The core contains a Rust implementation of RelaxedIK and CollisionIK with both a library crate and a binary crate. The library crate includes all the kinematics libraries of RelaxedIK, while the binary crate is desgined for the purpose of testing. Since the core is not designed to be run independently in general (although it is runnable), please refer to the Wrappers section and READMEs in those wrapper repos for more information on how to run RelaxedIK or CollisionIK.

    126 | 127 |

    To introduce relaxed_ik_core, let’s first talk about the previous iteration of RelaxedIK at relaxed_ik. There are three parts in this repo: the Rust library of RelaxedIK, a ROS wrapper around it, and a preprocessing toolkit for robot config files needed for RelaxedIK. To make it more convenient to extend RelaxedIK and build all kinds of wrappers around it, we extract the Rust library from that repo to be relaxed_ik_core. Also, to ease the process of setting up a robot arm with RelaxedIK, we decide to exclude the preprocessing toolkit (which is accessible in relaxed_ik) from relaxed_ik_core and instead provide all of the pre-generated config files for some mostly used robot manipulators. The list of available robots include baxter, hubo, iiwa7, jaco7, panda, sawyer, ur5, and yumi. Please refer to the READMEs in those repos if you intend to work with a robot not in this list.

    128 | 129 |
    130 |
    131 | 132 |
    133 |
    134 | 135 |
    136 | 137 |
    138 |
    139 |
    140 |
    141 | 148 | 152 |
    153 | 154 |
    155 |
    156 |
    157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /docs/post/about/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | About 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 72 | 73 | 74 | 75 | 76 | 77 | 113 | 114 | 115 |
    116 |
    117 | 118 |
    119 | 120 |
    121 |
    122 |
    123 |
    124 |

    About

    125 |

    Welcome to RelaxedIK! We implement the methods discussed in our paper RelaxedIK: Real-time Synthesis of Accurate and Feasible Robot Arm Motion and CollisionIK: A Per-Instant Pose Optimization Method for Generating Robot Motions with Environment Collision Avoidance.

    126 | 127 | 132 | 133 |

    RelaxedIK is an inverse kinematics (IK) solver designed for robot platforms such that the conversion between Cartesian end-effector pose goals (such as “move the robot’s right arm end-effector to position X, while maintaining an end-effector orientation Y”) to Joint-Space (i.e., the robot’s rotation values for each joint degree-of-freedom at a particular time-point) is done both ACCURATELY and FEASIBLY. By this, we mean that RelaxedIK attempts to find the closest possible solution to the desired end-effector pose goals without exhibiting negative effects such as self-collisions, environment collisions, kinematic-singularities, or joint-space discontinuities.

    134 | 135 |

    CollisionIK is a per-instant pose optimization method that can generate configurations that achieve specified pose or motion objectives as best as possible over a sequence of solutions, while also simultaneously avoiding collisions with static or dynamic obstacles in the environment. CollisionIK extends RelaxedIK by incorporating environment collision avoidance into the optimization structure.

    136 | 137 |
    138 |
    139 | 140 |
    141 |
    142 | 143 |
    144 | 145 |
    146 |
    147 |
    148 |
    149 | 156 | 160 |
    161 | 162 |
    163 |
    164 |
    165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /src/groove/vars.rs: -------------------------------------------------------------------------------- 1 | use nalgebra::{UnitQuaternion, Vector3, Vector6, Quaternion, Point3}; 2 | use crate::spacetime::robot::Robot; 3 | use crate::utils_rust::file_utils::{*}; 4 | use time::PreciseTime; 5 | use std::ops::Deref; 6 | use yaml_rust::{YamlLoader, Yaml}; 7 | use std::fs::File; 8 | use std::io::prelude::*; 9 | 10 | use wasm_bindgen::prelude::*; 11 | use serde::{Serialize, Deserialize}; 12 | 13 | #[derive(Serialize, Deserialize)] 14 | pub struct VarsConstructorData { 15 | // pub urdf: String, 16 | pub link_radius:f64, 17 | pub base_links: Vec, 18 | pub ee_links: Vec, 19 | starting_config: Vec 20 | } 21 | 22 | pub struct RelaxedIKVars { 23 | pub robot: Robot, 24 | pub init_state: Vec, 25 | pub xopt: Vec, 26 | pub prev_state: Vec, 27 | pub prev_state2: Vec, 28 | pub prev_state3: Vec, 29 | pub goal_positions: Vec>, 30 | pub goal_quats: Vec>, 31 | pub tolerances: Vec>, 32 | pub init_ee_positions: Vec>, 33 | pub init_ee_quats: Vec> 34 | } 35 | impl RelaxedIKVars { 36 | pub fn from_local_settings(path_to_setting: &str) -> Self { 37 | let path_to_src = get_path_to_src(); 38 | let mut file = File::open(path_to_setting).unwrap(); 39 | let mut contents = String::new(); 40 | let res = file.read_to_string(&mut contents).unwrap(); 41 | let docs = YamlLoader::load_from_str(contents.as_str()).unwrap(); 42 | let settings = &docs[0]; 43 | 44 | let path_to_urdf = path_to_src + "configs/urdfs/" + settings["urdf"].as_str().unwrap(); 45 | println!("RelaxedIK is using below URDF file: {}", path_to_urdf); 46 | let chain = k::Chain::::from_urdf_file(path_to_urdf.clone()).unwrap(); 47 | 48 | let base_links_arr = settings["base_links"].as_vec().unwrap(); 49 | let ee_links_arr = settings["ee_links"].as_vec().unwrap(); 50 | let num_chains = base_links_arr.len(); 51 | 52 | let mut base_links = Vec::new(); 53 | let mut ee_links = Vec::new(); 54 | let mut tolerances: Vec> = Vec::new(); 55 | for i in 0..num_chains { 56 | base_links.push(base_links_arr[i].as_str().unwrap().to_string()); 57 | ee_links.push(ee_links_arr[i].as_str().unwrap().to_string()); 58 | tolerances.push(Vector6::new(0., 0., 0., 0., 0., 0.)); 59 | } 60 | 61 | let urdf = &std::fs::read_to_string(path_to_urdf).unwrap(); 62 | let robot = Robot::from_urdf(urdf, &base_links, &ee_links); 63 | 64 | let mut starting_config = Vec::new(); 65 | if settings["starting_config"].is_badvalue() { 66 | println!("No starting config provided, using all zeros"); 67 | for i in 0..robot.num_dofs { 68 | starting_config.push(0.0); 69 | } 70 | } else { 71 | let starting_config_arr = settings["starting_config"].as_vec().unwrap(); 72 | for i in 0..starting_config_arr.len() { 73 | starting_config.push(starting_config_arr[i].as_f64().unwrap()); 74 | } 75 | } 76 | 77 | let mut init_ee_positions: Vec> = Vec::new(); 78 | let mut init_ee_quats: Vec> = Vec::new(); 79 | let pose = robot.get_ee_pos_and_quat_immutable(&starting_config); 80 | assert!(pose.len() == num_chains); 81 | 82 | for i in 0..pose.len() { 83 | init_ee_positions.push(pose[i].0); 84 | init_ee_quats.push(pose[i].1); 85 | } 86 | 87 | RelaxedIKVars{robot, init_state: starting_config.clone(), xopt: starting_config.clone(), 88 | prev_state: starting_config.clone(), prev_state2: starting_config.clone(), prev_state3: starting_config.clone(), 89 | goal_positions: init_ee_positions.clone(), goal_quats: init_ee_quats.clone(), tolerances, init_ee_positions, init_ee_quats} 90 | } 91 | 92 | // for webassembly 93 | pub fn from_jsvalue( configs: VarsConstructorData, urdf: &str) -> Self { 94 | 95 | let num_chains = configs.base_links.len(); 96 | 97 | let mut tolerances: Vec> = Vec::new(); 98 | for i in 0..num_chains { 99 | tolerances.push(Vector6::new(0., 0., 0., 0., 0., 0.)); 100 | } 101 | 102 | let robot = Robot::from_urdf(urdf, &configs.base_links, &configs.ee_links); 103 | 104 | let mut init_ee_positions: Vec> = Vec::new(); 105 | let mut init_ee_quats: Vec> = Vec::new(); 106 | let pose = robot.get_ee_pos_and_quat_immutable(&configs.starting_config); 107 | assert!(pose.len() == num_chains); 108 | 109 | for i in 0..pose.len() { 110 | init_ee_positions.push(pose[i].0); 111 | init_ee_quats.push(pose[i].1); 112 | } 113 | 114 | RelaxedIKVars{robot, init_state: configs.starting_config.clone(), xopt: configs.starting_config.clone(), 115 | prev_state: configs.starting_config.clone(), prev_state2: configs.starting_config.clone(), prev_state3: configs.starting_config.clone(), 116 | goal_positions: init_ee_positions.clone(), goal_quats: init_ee_quats.clone(), tolerances, init_ee_positions, init_ee_quats} 117 | 118 | } 119 | 120 | pub fn update(&mut self, xopt: Vec) { 121 | self.prev_state3 = self.prev_state2.clone(); 122 | self.prev_state2 = self.prev_state.clone(); 123 | self.prev_state = self.xopt.clone(); 124 | self.xopt = xopt.clone(); 125 | } 126 | 127 | pub fn reset(&mut self, init_state: Vec) { 128 | self.prev_state3 = init_state.clone(); 129 | self.prev_state2 = init_state.clone(); 130 | self.prev_state = init_state.clone(); 131 | self.xopt = init_state.clone(); 132 | self.init_state = init_state.clone(); 133 | 134 | let mut init_ee_positions: Vec> = Vec::new(); 135 | let mut init_ee_quats: Vec> = Vec::new(); 136 | let pose = self.robot.get_ee_pos_and_quat_immutable(&init_state); 137 | 138 | for i in 0..pose.len() { 139 | init_ee_positions.push(pose[i].0); 140 | init_ee_quats.push(pose[i].1); 141 | } 142 | 143 | self.init_ee_positions = init_ee_positions.clone(); 144 | self.init_ee_quats = init_ee_quats.clone(); 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /hugo/themes/onedly/README.md: -------------------------------------------------------------------------------- 1 | # One-Day-Only (OneDly) Project Theme 2 | 3 | This [Hugo](http://gohugo.io) theme is for documenting One-Day-Only (OneDly) projects. The theme renders a single page and is based on [Github project Page](https://themes.gohugo.io/github-project-landing-page/). 4 | 5 | # About 6 | 7 | One-Day-Only or OneDly projects help to acquire a new skill or to complete a task within a short timeframe. It limits the available time and combines it with defined objectives. This situation forces you to focus on the relevant elements in order to successfully complete a task or project. Please note, the idea is not to pack as much work as you can do within a workday. At the end you will find answers for the following questions 8 | 9 | * What were the relevant elements for success? 10 | * How good are you in estimating your work effort? 11 | * What were road blocks or even showstoppers you haven't forseen even in a short-term project horizon? 12 | * What are typical reoccuring interuptions and distractions during your work? 13 | * What is your personal pace when working intensly on a task or project? 14 | 15 | This will certainly generate some personal insights and improve your activities in future projects. 16 | 17 | # Features 18 | 19 | * Social media links as buttons at the top of the page 20 | * Social media sharing links as buttons at the end of the page 21 | * All posts on a single page as separated sections 22 | * Post ordering by `sec` parameter in post's front matter, instead of date 23 | * Imprint and GDPR examples pages 24 | * Examples for project structure included 25 | 26 | # Demo and Examples 27 | 28 | Have a look at the [demo](http://cdeck3r.com/OneDly-Theme/). 29 | 30 | The demo uses examples files. They structure a project and are stored in the theme's `exampleSite/content` directory. The `exampleSite` directory also contains a `config.toml` with default parameter settings. 31 | 32 | # Screenshot 33 | 34 | ![screenshot](https://github.com/cdeck3r/OneDly-Theme/blob/master/images/screenshot.png) 35 | 36 | # Quick Start 37 | 38 | 1. install [Hugo](http://gohugo.io) 39 | 1. Create a new site: `hugo new site myproject` 40 | 1. Change dir: `cd myproject`. We now assume this directory as _current_ dir 41 | 1. Add the OneDly theme: `git submodule add https://github.com/cdeck3r/OneDly-Theme.git themes/onedly` 42 | 1. Copy `themes/onedly/exampleSite/config.toml` into current dir 43 | 1. Copy example files from `themes/onedly/exampleSite/content` in project's `content` directory. 44 | 1. Start server: `hugo server -D -t onedly` 45 | 46 | # Customization 47 | 48 | Check [config.toml](https://github.com/cdeck3r/OneDly-Theme/blob/master/exampleSite/config.toml) for available configuration. Below is a description for each of them. 49 | 50 | **Imprint & GDRP:** Both declarations are stored in `content/imprint-gdpr`. The links are only displayed, if the files exist. So, you do not have dead links. 51 | 52 | ### Project Specification Parameters 53 | 54 | The project name is specified as the title of the site. 55 | ``` 56 | title = "OneDly Project" 57 | ``` 58 | 59 | The project description follows in the `params` section. 60 | ``` 61 | [params] 62 | description = "One-Day-Only (OneDly) project documentation." 63 | ``` 64 | 65 | Other variables within the `[params]` section are 66 | 67 | * `author_name` the project author's name. 68 | * `author_url` link to the personal website of the project author. 69 | * `project_url` link to project url, e.g. the project's github repo 70 | 71 | **Note:** `description` and `author_name` are used as the site's meta data for author and description within the html header. 72 | 73 | Examples 74 | 75 | ``` 76 | author_name = "cdeck3r" 77 | author_url = "//cdeck3r.com" 78 | project_url = "//github.com/cdeck3r/OneDly-Theme" 79 | ``` 80 | 81 | ### Section Ordering 82 | 83 | The project documentation may consists of several files indicating different documentation sections. In Hugo-Speak these sections are pages stored in separate `.md` files. All files need to be placed in `myproject/content/post` directory. An example project content structure can be found in `exampleSite/content`. 84 | 85 | Hugo uses the [content directory with the most pages](https://gohugo.io/functions/where/#mainsections) as source for displaying your documentation. You may explicitly set the `post` directory or any other directory containing your project documentation as well as add additional directories in the `config.toml`. In the example below the content sources from the `post` and the `other` directories. 86 | 87 | ``` 88 | [params] 89 | ... 90 | # optionally specify where the content is 91 | # mainSections = ["post", "other"] 92 | ``` 93 | 94 | One may create a new section using `hugo new post/about.md`. It is recommended to start with an About section. In the file's front matter specify 95 | 96 | ``` 97 | +++ 98 | title = "About" 99 | date = "2019-02-28" 100 | sec = 1 101 | +++ 102 | ``` 103 | 104 | The `sec` variable defines the position on the site. `sec = 1` lets the About section appear at the beginning right below the description and social media links. In the next section, created by the command above, you may specify a larger number, e.g. `sec = 4`. This positions this new section after the About section and before a section with `sec = 5` or larger. If you do not specify a `sec` variable ordering falls back to default ordering by the date sourced from the front matter. Information on ordering are found in [Hugo's documentation](https://gohugo.io/templates/lists/#default-weight-date-linktitle-filepath). 105 | 106 | 107 | ### Social media 108 | 109 | A user may specify links to well-known social media sites shown at the top of the page. In `config.toml` the section `[social]` lists the supported social media links. If the variable in this section specifies the user's account name, the corresponding button linking to the social media site will appear on the page. 110 | 111 | The exampleSite's [config.toml](https://github.com/cdeck3r/OneDly-Theme/blob/master/exampleSite/config.toml) for examples. 112 | 113 | ### Theme colors 114 | 115 | Standard theme colors are 116 | 117 | ``` 118 | first_color="#f8f8f8" 119 | first_border_color="#e7e7e7" 120 | first_text_color="#333" 121 | 122 | second_color="white" 123 | second_text_color="#333" 124 | 125 | header_color="#f8f8f8" 126 | header_text_color="rgb(51, 51, 51)" 127 | 128 | header_link_color="#777" 129 | header_link_hover_color="rgb(51, 51, 51)" 130 | 131 | ``` 132 | 133 | -------------------------------------------------------------------------------- /src/spacetime/robot.rs: -------------------------------------------------------------------------------- 1 | use crate::spacetime::arm; 2 | use nalgebra; 3 | use urdf_rs; 4 | 5 | #[derive(Clone, Debug)] 6 | pub struct Robot { 7 | pub arms: Vec, 8 | pub num_chains: usize, 9 | pub num_dofs: usize, 10 | pub chain_lengths: Vec, 11 | pub lower_joint_limits: Vec, 12 | pub upper_joint_limits: Vec 13 | } 14 | 15 | impl Robot { 16 | pub fn from_urdf(urdf: &str, base_links: &[String], ee_links: &[String]) -> Self { 17 | 18 | // let chain = k::Chain::::from_urdf_file(urdf).unwrap(); 19 | let description : urdf_rs::Robot = urdf_rs::read_from_string(urdf).unwrap(); 20 | let chain: k::Chain = k::Chain::from(description.clone()); 21 | 22 | let mut arms: Vec = Vec::new(); 23 | let num_chains = base_links.len(); 24 | let mut chain_lengths = Vec::new(); 25 | let mut num_dofs = 0; 26 | 27 | let mut lower_joint_limits = Vec::new(); 28 | let mut upper_joint_limits = Vec::new(); 29 | 30 | for i in 0..num_chains { 31 | let base_link = chain.find_link(base_links[i].as_str()).unwrap(); 32 | let ee_link = chain.find_link(ee_links[i].as_str()).unwrap(); 33 | let serial_chain = k::SerialChain::from_end_to_root(&ee_link, &base_link); 34 | 35 | let mut axis_types: Vec = Vec::new(); 36 | let mut joint_types: Vec = Vec::new(); 37 | let disp_offset = nalgebra::Vector3::new(0.0, 0.0, 0.0); 38 | let mut displacements = Vec::new(); 39 | let mut rot_offsets = Vec::new(); 40 | 41 | let mut first_link: bool = true; 42 | serial_chain.iter().for_each(|node| { 43 | let joint = node.joint(); 44 | if first_link { 45 | first_link = false; 46 | return 47 | } else { 48 | match joint.joint_type { 49 | k::JointType::Fixed => { 50 | joint_types.push("fixed".to_string()); 51 | }, 52 | k::JointType::Rotational { axis } => { 53 | if axis[0] == 1.0 { 54 | axis_types.push("x".to_string()); 55 | } else if axis[1] == 1.0 { 56 | axis_types.push("y".to_string()); 57 | } else if axis[2] == 1.0 { 58 | axis_types.push("z".to_string()); 59 | } else if axis[0] == -1.0 { 60 | axis_types.push("-x".to_string()); 61 | } else if axis[1] == -1.0 { 62 | axis_types.push("-y".to_string()); 63 | } else if axis[2] == -1.0 { 64 | axis_types.push("-z".to_string()); 65 | } 66 | if joint.limits.is_none() { 67 | joint_types.push("continuous".to_string()); 68 | lower_joint_limits.push(-999.0); 69 | upper_joint_limits.push(999.0); 70 | } else { 71 | joint_types.push("revolute".to_string()); 72 | lower_joint_limits.push(joint.limits.unwrap().min); 73 | upper_joint_limits.push(joint.limits.unwrap().max); 74 | } 75 | }, 76 | k::JointType::Linear { axis } => { 77 | if axis[0] == 1.0 { 78 | axis_types.push("x".to_string()); 79 | } else if axis[1] == 1.0 { 80 | axis_types.push("y".to_string()); 81 | } else if axis[2] == 1.0 { 82 | axis_types.push("z".to_string()); 83 | } else if axis[0] == -1.0 { 84 | axis_types.push("-x".to_string()); 85 | } else if axis[1] == -1.0 { 86 | axis_types.push("-y".to_string()); 87 | } else if axis[2] == -1.0 { 88 | axis_types.push("-z".to_string()); 89 | } 90 | joint_types.push("prismatic".to_string()); 91 | lower_joint_limits.push(joint.limits.unwrap().min); 92 | upper_joint_limits.push(joint.limits.unwrap().max); 93 | } 94 | } 95 | } 96 | 97 | displacements.push(joint.origin().translation.vector); 98 | rot_offsets.push(joint.origin().rotation); 99 | }); 100 | let arm: arm::Arm = arm::Arm::init(axis_types.clone(), displacements.clone(), 101 | rot_offsets.clone(), joint_types.clone()); 102 | arms.push(arm); 103 | chain_lengths.push(axis_types.len() as usize); 104 | num_dofs += axis_types.len(); 105 | } 106 | Robot{arms, num_chains, chain_lengths, num_dofs, lower_joint_limits, upper_joint_limits} 107 | 108 | } 109 | 110 | pub fn get_frames_immutable(&self, x: &[f64]) -> Vec<(Vec>, Vec>)> { 111 | let mut out: Vec<(Vec>, Vec>)> = Vec::new(); 112 | let mut l = 0; 113 | let mut r = 0; 114 | for i in 0..self.num_chains { 115 | r += self.chain_lengths[i]; 116 | out.push( self.arms[i].get_frames_immutable( &x[l..r] ) ); 117 | l = r; 118 | } 119 | out 120 | } 121 | 122 | pub fn get_manipulability_immutable(&self, x: &[f64]) -> f64 { 123 | let mut out = 0.0; 124 | let mut l = 0; 125 | let mut r = 0; 126 | for i in 0..self.num_chains { 127 | r += self.chain_lengths[i]; 128 | out += self.arms[i].get_manipulability_immutable( &x[l..r] ); 129 | l = r; 130 | } 131 | out 132 | } 133 | 134 | pub fn get_ee_pos_and_quat_immutable(&self, x: &[f64]) -> Vec<(nalgebra::Vector3, nalgebra::UnitQuaternion)> { 135 | let mut out: Vec<(nalgebra::Vector3, nalgebra::UnitQuaternion)> = Vec::new(); 136 | let mut l = 0; 137 | let mut r = 0; 138 | for i in 0..self.num_chains { 139 | r += self.chain_lengths[i]; 140 | out.push( self.arms[i].get_ee_pos_and_quat_immutable( &x[l..r] )); 141 | l = r; 142 | } 143 | out 144 | } 145 | } 146 | 147 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RangedIK Core 2 | 3 | Implementation of our ICRA'23 paper: *RangedIK: An Optimization-Based Robot Motion Generation Method for Ranged-Goal Tasks* 4 | 5 | [[Pre-print](https://arxiv.org/pdf/2302.13935.pdf)] [[Supplementary Video](https://www.youtube.com/watch?v=_QVAetYbpEY)] [[Presentation Video](https://www.youtube.com/watch?v=IKy0Yda8p4)] [[Poster](https://yepw.github.io/files/icra23_poster.pdf)] 6 | 7 | ## Introduction 8 | RangedIK is a real-time motion synthesis method that exploits range flexibility to satisfy multiple kinematic requirements. RangedIK is particularly suitable for applications that allow some tolerance, such as wielding where the tool is allowed to rotate along its principle axis. For more information, please refer to [our paper](https://arxiv.org/pdf/2302.13935.pdf). 9 | 10 | ## The RelaxedIK Family 11 | [RangedIK](https://arxiv.org/pdf/2302.13935.pdf) extends [RelaxedIK](https://github.com/uwgraphics/relaxed_ik_core/tree/relaxed-ik) by leveraging the flexibility afforded by tolerances. Also, RangedIK is recently maintained and works with more recent rust versions. 12 | 13 | [CollisionIK](https://github.com/uwgraphics/relaxed_ik_core/tree/collision-ik) extends [RelaxedIK](https://github.com/uwgraphics/relaxed_ik_core/tree/relaxed-ik) by avoiding collisions with static or dynamic obstacles in the environment. 14 | 15 | We provide a series of wrappers for our tools to be used in various platform or software. 16 | 17 | ||**ROS1**|**ROS2**|**WebAssembly**|**Coppeliasim**|**Mujoco**| 18 | |:------|:-----|:-----|:-----|:-----|:-----| 19 | |**RangedIK**|[link](https://github.com/uwgraphics/relaxed_ik_ros1/tree/ranged-ik)|[link](https://github.com/uwgraphics/relaxed_ik_ros2)|[link](https://github.com/yepw/relaxed-ik-web-demo/)|x|x| 20 | |**CollisionIK**|[link](https://github.com/uwgraphics/relaxed_ik_ros1/)|x|x|x|x| 21 | |**RelaxedIK**|[link](https://github.com/uwgraphics/relaxed_ik_ros1/)|x|x|[link](https://github.com/uwgraphics/relaxed_ik_coppeliasim)|[link](https://github.com/uwgraphics/relaxed_ik_mujoco)| 22 | 23 | 24 | 25 | ## Getting Started 26 | 27 | 1. [Install Rust](https://www.rust-lang.org/learn/get-started) 28 | 2. Compile: 29 | ```bash 30 | cargo build 31 | ``` 32 | The compiled library is at `/target/debug/librelaxed_ik_lib.so` 33 | 3. Run a small demo: 34 | ```bash 35 | cargo run --bin relaxed_ik_bin 36 | ``` 37 | ### Use your own robot 38 | 1. Place your robot's URDF under `configs/urdfs/` 39 | 2. Make a setting file. Examples are under `configs/example_settings` 40 | 41 | ### Python wrapper 42 | `wrappers/python_wrapper.py` provides a python wrapper, which is used by both the [ROS 1 wrapper](https://github.com/uwgraphics/relaxed_ik_ros1/tree/ranged-ik) 43 | and [ROS 2 wrapper](https://github.com/uwgraphics/relaxed_ik_ros2). 44 | [`relaxed_ik_ros1/scripts/relaxed_ik_rust.py`](https://github.com/uwgraphics/relaxed_ik_ros1/blob/ranged-ik/scripts/relaxed_ik_rust.py) provides an example of using the python wrapper. 45 | 46 | ### JavaScript (WebAssembly) wrapper 47 | [Online demo](https://yepw.github.io/relaxed-ik-web-demo/) 48 | 1. [Install Rust](https://www.rust-lang.org/tools/install) 49 | 2. `cargo install wasm-pack` 50 | * if there is a `linker 'cc' not found` error, run `sudo apt install gcc` 51 | * if it complains about openssl, on Ubuntu install it by `sudo apt-get install libssl-dev pkg-config openssl`. For windows, download and install [perl](https://strawberryperl.com/). 52 | 3. Compile to WebAssembly 53 | ``` 54 | wasm-pack build --target web 55 | ``` 56 | 4. [relaxed-ik-web-demo](https://github.com/yepw/relaxed-ik-web-demo) provides an example of running relaxed-ik in browser. 57 | 58 | ## Supplementary Video 59 | 60 | [YouTube video link](https://www.youtube.com/watch?v=_QVAetYbpEY) 61 | 62 | ## Citation 63 | 64 | If you use RangedIK, please cite our ICRA paper: [*RangedIK: An Optimization-based Robot Motion Generation Method for Ranged-Goal Tasks*](https://arxiv.org/abs/2302.13935) 65 | ``` 66 | @article{wang2023rangedik, 67 | title={RangedIK: An Optimization-based Robot Motion Generation Method for Ranged-Goal Tasks}, 68 | author={Wang, Yeping and Praveena, Pragathi and Rakita, Daniel and Gleicher, Michael}, 69 | booktitle={2023 IEEE International Conference on Robotics and Automation (ICRA)}, 70 | pages={9700-9706}, 71 | year={2023} 72 | } 73 | ``` 74 | 75 | If you use RelaxedIK, please cite our RSS paper: [*RelaxedIK: Real-time Synthesis of Accurate and Feasible Robot Arm Motion*](http://www.roboticsproceedings.org/rss14/p43.html) 76 | ``` 77 | @INPROCEEDINGS{Rakita-RSS-18, 78 | AUTHOR = {Daniel Rakita AND Bilge Mutlu AND Michael Gleicher}, 79 | TITLE = {{RelaxedIK: Real-time Synthesis of Accurate and Feasible Robot Arm Motion}}, 80 | BOOKTITLE = {Proceedings of Robotics: Science and Systems}, 81 | YEAR = {2018}, 82 | ADDRESS = {Pittsburgh, Pennsylvania}, 83 | MONTH = {June}, 84 | DOI = {10.15607/RSS.2018.XIV.043} 85 | } 86 | ``` 87 | 88 | If you use CollisionIK (RelaxedIK with environment collision avoidance), please cite our ICRA paper: [*CollisionIK: A Per-Instant Pose Optimization Method for Generating Robot Motions with Environment Collision Avoidance*](https://arxiv.org/abs/2102.13187) 89 | ``` 90 | @inproceedings{rakita2021collisionik, 91 | title={Collisionik: A per-instant pose optimization method for generating robot motions with environment collision avoidance}, 92 | author={Rakita, Daniel and Shi, Haochen and Mutlu, Bilge and Gleicher, Michael}, 93 | booktitle={2021 IEEE International Conference on Robotics and Automation (ICRA)}, 94 | pages={9995--10001}, 95 | year={2021}, 96 | organization={IEEE} 97 | } 98 | ``` 99 | 100 | If you use our solver for a robot teleoperation interface, also consider citing our prior work that shows the effectiveness of RelaxedIK in this setting: [*A Motion Retargeting Method for Effective Mimicry-based Teleoperation of Robot Arms*](https://dl.acm.org/citation.cfm?id=3020254) 101 | ``` 102 | @inproceedings{rakita2017motion, 103 | title={A motion retargeting method for effective mimicry-based teleoperation of robot arms}, 104 | author={Rakita, Daniel and Mutlu, Bilge and Gleicher, Michael}, 105 | booktitle={Proceedings of the 2017 ACM/IEEE International Conference on Human-Robot Interaction}, 106 | pages={361--370}, 107 | year={2017}, 108 | organization={ACM} 109 | } 110 | ``` 111 | 112 | or [*An Autonomous Dynamic Camera Method for Effective Remote Teleoperation*](https://dl.acm.org/citation.cfm?id=3171221.3171279) 113 | ``` 114 | @inproceedings{rakita2018autonomous, 115 | title={An autonomous dynamic camera method for effective remote teleoperation}, 116 | author={Rakita, Daniel and Mutlu, Bilge and Gleicher, Michael}, 117 | booktitle={Proceedings of the 2018 ACM/IEEE International Conference on Human-Robot Interaction}, 118 | pages={325--333}, 119 | year={2018}, 120 | organization={ACM} 121 | } 122 | ``` 123 | 124 | -------------------------------------------------------------------------------- /hugo/themes/onedly/layouts/partials/social.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ with .Site.Social.github }} 4 |
  • 5 | 6 |
  • 7 | {{ end }} 8 | 9 | 10 | {{ with .Site.Social.gitlab }} 11 |
  • 12 | 13 |
  • 14 | {{ end }} 15 | 16 | {{ with .Site.Social.stackoverflow }} 17 |
  • 18 | 19 |
  • 20 | {{ end }} 21 | 22 | {{ with .Site.Social.bitbucket }} 23 |
  • 24 | 25 |
  • 26 | {{ end }} 27 | 28 | {{ with .Site.Social.jsfiddle }} 29 |
  • 30 | 31 |
  • 32 | {{ end }} 33 | 34 | {{ with .Site.Social.codepen }} 35 |
  • 36 | 37 |
  • 38 | {{ end }} 39 | 40 | {{ with .Site.Social.deviantart }} 41 |
  • 42 | 43 |
  • 44 | {{ end }} 45 | 46 | {{ with .Site.Social.flickr }} 47 |
  • 48 | 49 |
  • 50 | {{ end }} 51 | 52 | {{ with .Site.Social.behance }} 53 |
  • 54 | 55 |
  • 56 | {{ end }} 57 | 58 | {{ with .Site.Social.dribbble }} 59 |
  • 60 | 61 |
  • 62 | {{ end }} 63 | 64 | {{ with .Site.Social.wordpress }} 65 |
  • 66 | 67 |
  • 68 | {{ end }} 69 | 70 | {{ with .Site.Social.medium}} 71 |
  • 72 | 73 |
  • 74 | {{ end }} 75 | 76 | {{ with .Site.Social.linkedin }} 77 |
  • 78 | 79 |
  • 80 | {{ end }} 81 | 82 | {{ with .Site.Social.linkedin_company }} 83 |
  • 84 | 85 |
  • 86 | {{ end }} 87 | 88 | {{ with .Site.Social.foursquare }} 89 |
  • 90 | 91 |
  • 92 | {{ end }} 93 | 94 | {{ with .Site.Social.xing }} 95 |
  • 96 | 97 |
  • 98 | {{ end }} 99 | 100 | {{ with .Site.Social.slideshare }} 101 |
  • 102 | 103 |
  • 104 | {{ end }} 105 | 106 | {{ with .Site.Social.facebook }} 107 |
  • 108 | 109 |
  • 110 | {{ end }} 111 | 112 | {{ with .Site.Social.googleplus }} 113 |
  • 114 | 115 |
  • 116 | {{ end }} 117 | 118 | {{ with .Site.Social.reddit }} 119 |
  • 120 | 121 |
  • 122 | {{ end }} 123 | 124 | {{ with .Site.Social.quora }} 125 |
  • 126 | 127 |
  • 128 | {{ end }} 129 | 130 | {{ with .Site.Social.youtube }} 131 |
  • 132 | 133 |
  • 134 | {{ end }} 135 | 136 | {{ with .Site.Social.vimeo }} 137 |
  • 138 | 139 |
  • 140 | {{ end }} 141 | 142 | {{ with .Site.Social.whatsapp }} 143 |
  • 144 | 145 |
  • 146 | {{ end }} 147 | 148 | 149 | 150 | {{ with .Site.Social.wechat }} 151 |
  • 152 | 153 |
  • 154 | {{ end }} 155 | 156 | {{ with .Site.Social.qq }} 157 |
  • 158 | 159 |
  • 160 | {{ end }} 161 | 162 | {{ with .Site.Social.instagram }} 163 |
  • 164 | 165 |
  • 166 | {{ end }} 167 | 168 | {{ with .Site.Social.tumblr }} 169 |
  • 170 | 171 |
  • 172 | {{ end }} 173 | 174 | {{ with .Site.Social.twitter }} 175 |
  • 176 | 177 |
  • 178 | {{ end }} 179 | 180 | {{ with .Site.Social.skype }} 181 |
  • 182 | 183 |
  • 184 | {{ end }} 185 | 186 | {{ with .Site.Social.snapchat }} 187 |
  • 188 | 189 |
  • 190 | {{ end }} 191 | 192 | {{ with .Site.Social.pinterest }} 193 |
  • 194 | 195 |
  • 196 | {{ end }} 197 | 198 | {{ with .Site.Social.telegram }} 199 |
  • 200 | 201 |
  • 202 | {{ end }} 203 | 204 | {{ with .Site.Social.vine }} 205 |
  • 206 | 207 |
  • 208 | {{ end }} 209 | 210 | {{ with .Site.Social.googlescholar }} 211 |
  • 212 | 213 |
  • 214 | {{ end }} 215 | 216 | {{ with .Site.Social.orcid }} 217 |
  • 218 | 219 |
  • 220 | {{ end }} 221 | 222 | {{ with .Site.Social.researchgate }} 223 |
  • 224 | 225 |
  • 226 | {{ end }} 227 | 228 | {{ with .Site.Social.email }} 229 |
  • 230 | 231 |
  • 232 | {{ end }} 233 | -------------------------------------------------------------------------------- /docs/post/wrappers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | Wrappers 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 72 | 73 | 74 | 75 | 76 | 77 | 113 | 114 | 115 |
    116 |
    117 | 118 |
    119 | 120 |
    121 |
    122 |
    123 |
    124 |

    Wrappers

    125 | 126 | 127 |

    Although the core is runnable, it is usually not intended to be run alone. Wrappers are required to connect RelaxedIK to different interfaces. Here are 4 wrappers that we implemented for ROS, CoppeliaSim, Mujoco, and Unity respectively. Each wrapper has detailed instructions on how to work with them in the READMEs in their repo. If you are interested, it is possible to wrap up the core in other interfaces as well.

    128 | 129 |

    The links to these github repos are here:

    130 | 131 | 137 | 138 |

    RelaxedIK ROS1

    139 | 140 |
      141 |
    • This wrapper has the complete set of features available in the RelaxedIK package and it is also where CollisionIK resides. If you doesn’t have strong preferences over any specific wrapper, you probably should consider this ROS wrapper as the first choice. A keyboard pose goal driver and an rviz viewer are provided for testing purpose.
    • 142 |
    143 | 144 |

    RelaxedIK CoppeliaSim

    145 | 146 |
      147 |
    • This wrapper is a RelaxedIK plugin for CoppeliaSim. Although it’s possible to access the ROS1 wrapper of RelaxedIK in CoppeliaSim through ROS topics and params, it might be more convenient to directly access RelaxedIK in the form of a CoppeliaSim Pluggin. That’s where the inspiration of this wrapper comes from. If you don’t need ROS in your project, this wrapper is designed for you; however, if you need ROS for other parts of your project, it is still recommended to use the ROS wrapper since that one has the complete set of features available.
    • 148 |
    149 | 150 |

    RelaxedIK Mujoco

    151 | 152 |
      153 |
    • This wrapper is a RelaxedIK Plugin for MuJoCo. MuJoCo is an advanced physics simulation engine that may have some extra features unavailable in CoppeliaSim.
    • 154 |
    155 | 156 |

    RelaxedIK Unity

    157 | 158 |
      159 |
    • This wrapper allows users to use RelaxedIK in Unity. This is designed to work on Windows and it probably won’t work on a Linux machine. A few commonly used simulated robot arms have already been set up for you to play with. In the simulation, you will be able to disable or enable RelaxedIK as you like. When RelaxedIK is disabled, a joint angle writer panel will show up for you to adjust and visualize the joint angle configuration. When RelaxedIK is enabled, you will be able to have real-time interactions with RelaxedIK by dragging the transform gizmo associated with the gripper of the robot.

      160 | 161 |

      Unity screenshot 162 |

      RelaxedIK Unity

    • 163 |
    164 | 165 |
    166 |
    167 | 168 |
    169 |
    170 | 171 |
    172 | 173 |
    174 |
    175 |
    176 |
    177 | 184 | 188 |
    189 | 190 |
    191 |
    192 |
    193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /src/groove/env_collision.rs: -------------------------------------------------------------------------------- 1 | use crate::utils_rust::yaml_utils::EnvCollisionFileParser; 2 | use nalgebra::{Vector3, Isometry3, Point3}; 3 | use nalgebra::geometry::{Translation3, UnitQuaternion, Quaternion}; 4 | use ncollide3d::pipeline::{*}; 5 | use ncollide3d::shape::{*}; 6 | use std::collections::BTreeMap; 7 | 8 | #[derive(Clone, Debug)] 9 | pub struct LinkData { 10 | pub is_link: bool, 11 | pub arm_idx: i32, 12 | } 13 | 14 | impl LinkData { 15 | pub fn new(is_link: bool, arm_idx: i32) -> LinkData { 16 | Self { 17 | is_link: is_link, 18 | arm_idx: arm_idx, 19 | } 20 | } 21 | } 22 | 23 | #[derive(Clone, Debug)] 24 | pub struct CollisionObjectData { 25 | pub name: String, 26 | pub link_data: LinkData, 27 | } 28 | 29 | impl CollisionObjectData { 30 | pub fn new(name: String, link_data: LinkData) -> CollisionObjectData { 31 | Self { 32 | name: name, 33 | link_data: link_data, 34 | } 35 | } 36 | } 37 | 38 | pub struct RelaxedIKEnvCollision { 39 | pub world: CollisionWorld, 40 | pub link_radius: f64, 41 | pub link_handles: Vec>, 42 | pub dyn_obstacle_handles: Vec<(CollisionObjectSlabHandle, String)>, 43 | pub active_pairs: Vec>>, 44 | pub active_obstacles: Vec, f64)>>, 45 | } 46 | 47 | impl RelaxedIKEnvCollision { 48 | pub fn init_collision_world ( 49 | env_collision_file: EnvCollisionFileParser, 50 | frames: &Vec<(Vec>, Vec>)>, 51 | ) -> Self { 52 | let link_radius = env_collision_file.robot_link_radius; 53 | let plane_obstacles = env_collision_file.cuboids; 54 | let sphere_obstacles = env_collision_file.spheres; 55 | let pcd_obstacles = env_collision_file.pcds; 56 | 57 | // The links are part of group 1 and can only interact with obstacles 58 | let mut link_groups = CollisionGroups::new(); 59 | link_groups.set_membership(&[1]); 60 | link_groups.set_blacklist(&[1]); 61 | link_groups.set_whitelist(&[2]); 62 | 63 | // All the other objects are part of the group 2 and interact only with the links 64 | let mut others_groups = CollisionGroups::new(); 65 | others_groups.set_membership(&[2]); 66 | others_groups.set_blacklist(&[2]); 67 | others_groups.set_whitelist(&[1]); 68 | 69 | let proximity_query = GeometricQueryType::Proximity(20.0 * link_radius); 70 | 71 | let mut world = CollisionWorld::new(0.0); 72 | let mut link_handles: Vec> = Vec::new(); 73 | let mut active_pairs: Vec>> = Vec::new(); 74 | let mut active_obstacles: Vec, f64)>> = Vec::new(); 75 | for arm_idx in 0..frames.len() { 76 | let mut handles: Vec = Vec::new(); 77 | let mut obstacles: Vec<(Option, f64)> = Vec::new(); 78 | let pair: BTreeMap> = BTreeMap::new(); 79 | let last_elem = frames[arm_idx].0.len() - 1; 80 | for i in 0..last_elem { 81 | let start_pt = Point3::from(frames[arm_idx].0[i]); 82 | let end_pt = Point3::from(frames[arm_idx].0[i + 1]); 83 | let segment = ShapeHandle::new(Segment::new(start_pt, end_pt)); 84 | let segment_pos = nalgebra::one(); 85 | let link_data = CollisionObjectData::new(format!("Link {}", i), LinkData::new(true, arm_idx as i32)); 86 | let handle = world.add(segment_pos, segment, link_groups, proximity_query, link_data); 87 | handles.push(handle.0); 88 | obstacles.push((None, 0.0)); 89 | } 90 | link_handles.push(handles); 91 | active_pairs.push(pair); 92 | active_obstacles.push(obstacles); 93 | } 94 | 95 | let mut dyn_obstacle_handles: Vec<(CollisionObjectSlabHandle, String)> = Vec::new(); 96 | for i in 0..plane_obstacles.len() { 97 | let plane_obs = &plane_obstacles[i]; 98 | let half_extents = Vector3::new(plane_obs.x_halflength, plane_obs.y_halflength, plane_obs.z_halflength); 99 | let plane = ShapeHandle::new(Cuboid::new(half_extents)); 100 | let plane_ts = Translation3::new(plane_obs.tx, plane_obs.ty, plane_obs.tz); 101 | let plane_rot = UnitQuaternion::from_euler_angles(plane_obs.rx, plane_obs.ry, plane_obs.rz); 102 | let plane_pos = Isometry3::from_parts(plane_ts, plane_rot); 103 | let plane_data = CollisionObjectData::new(plane_obs.name.clone(), LinkData::new(false, -1)); 104 | let plane_handle = world.add(plane_pos, plane, others_groups, proximity_query, plane_data); 105 | if plane_obs.is_dynamic { 106 | dyn_obstacle_handles.push((plane_handle.0, plane_handle.1.data().name.clone())); 107 | } 108 | } 109 | 110 | for i in 0..sphere_obstacles.len() { 111 | let sphere_obs = &sphere_obstacles[i]; 112 | let sphere = ShapeHandle::new(Ball::new(sphere_obs.radius)); 113 | let sphere_ts = Translation3::new(sphere_obs.tx, sphere_obs.ty, sphere_obs.tz); 114 | let sphere_rot = UnitQuaternion::identity(); 115 | let sphere_pos = Isometry3::from_parts(sphere_ts, sphere_rot); 116 | let sphere_data = CollisionObjectData::new(sphere_obs.name.clone(), LinkData::new(false, -1)); 117 | let sphere_handle = world.add(sphere_pos, sphere, others_groups, proximity_query, sphere_data); 118 | if sphere_obs.is_dynamic { 119 | dyn_obstacle_handles.push((sphere_handle.0, sphere_handle.1.data().name.clone())); 120 | } 121 | } 122 | 123 | for i in 0..pcd_obstacles.len() { 124 | let pcd_obs = &pcd_obstacles[i]; 125 | // let mut shapes: Vec<(Isometry3, ShapeHandle)> = Vec::new(); 126 | // for sphere_obs in &pcd_obs.points { 127 | // let sphere = ShapeHandle::new(Ball::new(sphere_obs.radius)); 128 | // let sphere_ts = Translation3::new(sphere_obs.tx, sphere_obs.ty, sphere_obs.tz); 129 | // let sphere_rot = UnitQuaternion::identity(); 130 | // let sphere_pos = Isometry3::from_parts(sphere_ts, sphere_rot); 131 | // shapes.push((sphere_pos, sphere)); 132 | // } 133 | let mut points: Vec> = Vec::new(); 134 | for sphere_obs in &pcd_obs.points { 135 | points.push(Point3::new(sphere_obs.tx, sphere_obs.ty, sphere_obs.tz)); 136 | } 137 | // let pcd = ShapeHandle::new(Compound::new(shapes)); 138 | let pcd = ShapeHandle::new(ConvexHull::try_from_points(&points).unwrap()); 139 | let pcd_ts = Translation3::new(pcd_obs.tx, pcd_obs.ty, pcd_obs.tz); 140 | let pcd_rot = UnitQuaternion::from_euler_angles(pcd_obs.rx, pcd_obs.ry, pcd_obs.rz); 141 | let pcd_pos = Isometry3::from_parts(pcd_ts, pcd_rot); 142 | let pcd_data = CollisionObjectData::new(pcd_obs.name.clone(), LinkData::new(false, -1)); 143 | let pcd_handle = world.add(pcd_pos, pcd, others_groups, proximity_query, pcd_data); 144 | if pcd_obs.is_dynamic { 145 | dyn_obstacle_handles.push((pcd_handle.0, pcd_handle.1.data().name.clone())); 146 | } 147 | } 148 | 149 | return Self{world, link_radius, link_handles, dyn_obstacle_handles, active_pairs, active_obstacles}; 150 | } 151 | 152 | pub fn update_links( 153 | &mut self, 154 | frames: &Vec<(Vec>, Vec>)>, 155 | ) { 156 | for arm_idx in 0..frames.len() { 157 | let last_elem = frames[arm_idx].0.len() - 1; 158 | for i in 0..last_elem { 159 | let start_pt = Point3::from(frames[arm_idx].0[i]); 160 | let end_pt = Point3::from(frames[arm_idx].0[i + 1]); 161 | let segment = ShapeHandle::new(Segment::new(start_pt, end_pt)); 162 | let link = self.world.objects.get_mut(self.link_handles[arm_idx][i]).unwrap(); 163 | link.set_shape(segment); 164 | } 165 | } 166 | } 167 | 168 | pub fn update_dynamic_obstacle( 169 | &mut self, 170 | name: &str, 171 | position: Isometry3, 172 | ) { 173 | for (handle, id) in &self.dyn_obstacle_handles { 174 | if id == name { 175 | let co = self.world.objects.get_mut(*handle).unwrap(); 176 | co.set_position(position); 177 | break; 178 | } 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/groove/objective_master.rs: -------------------------------------------------------------------------------- 1 | use crate::groove::objective::*; 2 | use crate::groove::vars::RelaxedIKVars; 3 | 4 | pub struct ObjectiveMaster { 5 | pub objectives: Vec>, 6 | pub num_chains: usize, 7 | pub weight_priors: Vec, 8 | pub lite: bool, 9 | pub finite_diff_grad: bool 10 | } 11 | 12 | impl ObjectiveMaster { 13 | pub fn standard_ik(num_chains: usize) -> Self { 14 | let mut objectives: Vec> = Vec::new(); 15 | let mut weight_priors: Vec = Vec::new(); 16 | for i in 0..num_chains { 17 | objectives.push(Box::new(MatchEEPosGoals::new(i))); 18 | weight_priors.push(1.0); 19 | objectives.push(Box::new(MatchEEQuatGoals::new(i))); 20 | weight_priors.push(1.0); 21 | } 22 | Self{objectives, num_chains, weight_priors, lite: true, finite_diff_grad: true} 23 | } 24 | 25 | 26 | pub fn relaxed_ik(chain_lengths: &[usize]) -> Self { 27 | let mut objectives: Vec> = Vec::new(); 28 | let mut weight_priors: Vec = Vec::new(); 29 | let num_chains = chain_lengths.len(); 30 | let mut num_dofs = 0; 31 | for i in 0..num_chains { 32 | objectives.push(Box::new(MatchEEPosiDoF::new(i, 0))); 33 | weight_priors.push(50.0); 34 | objectives.push(Box::new(MatchEEPosiDoF::new(i, 1))); 35 | weight_priors.push(50.0); 36 | objectives.push(Box::new(MatchEEPosiDoF::new(i, 2))); 37 | weight_priors.push(50.0); 38 | objectives.push(Box::new(MatchEERotaDoF::new(i, 0))); 39 | weight_priors.push(10.0); 40 | objectives.push(Box::new(MatchEERotaDoF::new(i, 1))); 41 | weight_priors.push(10.0); 42 | objectives.push(Box::new(MatchEERotaDoF::new(i, 2))); 43 | weight_priors.push(10.0); 44 | // objectives.push(Box::new(EnvCollision::new(i))); 45 | // weight_priors.push(1.0); 46 | num_dofs += chain_lengths[i]; 47 | } 48 | 49 | for j in 0..num_dofs { 50 | objectives.push(Box::new(EachJointLimits::new(j))); weight_priors.push(0.1 ); 51 | } 52 | 53 | objectives.push(Box::new(MinimizeVelocity)); weight_priors.push(0.7); 54 | objectives.push(Box::new(MinimizeAcceleration)); weight_priors.push(0.5); 55 | objectives.push(Box::new(MinimizeJerk)); weight_priors.push(0.3); 56 | objectives.push(Box::new(MaximizeManipulability)); weight_priors.push(1.0); 57 | 58 | for i in 0..num_chains { 59 | for j in 0..chain_lengths[i]-2 { 60 | for k in j+2..chain_lengths[i] { 61 | objectives.push(Box::new(SelfCollision::new(0, j, k))); weight_priors.push(0.01 ); 62 | } 63 | } 64 | } 65 | 66 | Self{objectives, num_chains, weight_priors, lite: false, finite_diff_grad: false} 67 | } 68 | 69 | pub fn call(&self, x: &[f64], vars: &RelaxedIKVars) -> f64 { 70 | if self.lite { 71 | self.__call_lite(x, vars) 72 | } else { 73 | self.__call(x, vars) 74 | } 75 | } 76 | 77 | pub fn gradient(&self, x: &[f64], vars: &RelaxedIKVars) -> (f64, Vec) { 78 | if self.lite { 79 | if self.finite_diff_grad { 80 | self.__gradient_finite_diff_lite(x, vars) 81 | } else { 82 | self.__gradient_lite(x, vars) 83 | } 84 | } else { 85 | if self.finite_diff_grad { 86 | self.__gradient_finite_diff(x, vars) 87 | } else { 88 | self.__gradient(x, vars) 89 | } 90 | } 91 | } 92 | 93 | pub fn gradient_finite_diff(&self, x: &[f64], vars: &RelaxedIKVars) -> (f64, Vec) { 94 | if self.lite { 95 | self.__gradient_finite_diff_lite(x, vars) 96 | } else { 97 | self.__gradient_finite_diff(x, vars) 98 | } 99 | } 100 | 101 | fn __call(&self, x: &[f64], vars: &RelaxedIKVars) -> f64 { 102 | let mut out = 0.0; 103 | let frames = vars.robot.get_frames_immutable(x); 104 | for i in 0..self.objectives.len() { 105 | out += self.weight_priors[i] * self.objectives[i].call(x, vars, &frames); 106 | } 107 | out 108 | } 109 | 110 | fn __call_lite(&self, x: &[f64], vars: &RelaxedIKVars) -> f64 { 111 | let mut out = 0.0; 112 | let poses = vars.robot.get_ee_pos_and_quat_immutable(x); 113 | for i in 0..self.objectives.len() { 114 | out += self.weight_priors[i] * self.objectives[i].call_lite(x, vars, &poses); 115 | } 116 | out 117 | } 118 | 119 | fn __gradient(&self, x: &[f64], vars: &RelaxedIKVars) -> (f64, Vec) { 120 | let mut grad: Vec = vec![0. ; x.len()]; 121 | let mut obj = 0.0; 122 | 123 | let mut finite_diff_list: Vec = Vec::new(); 124 | let mut f_0s: Vec = Vec::new(); 125 | let frames_0 = vars.robot.get_frames_immutable(x); 126 | for i in 0..self.objectives.len() { 127 | if self.objectives[i].gradient_type() == 0 { 128 | let (local_obj, local_grad) = self.objectives[i].gradient(x, vars, &frames_0); 129 | f_0s.push(local_obj); 130 | obj += self.weight_priors[i] * local_obj; 131 | for j in 0..local_grad.len() { 132 | grad[j] += self.weight_priors[i] * local_grad[j]; 133 | } 134 | } else if self.objectives[i].gradient_type() == 1 { 135 | finite_diff_list.push(i); 136 | let local_obj = self.objectives[i].call(x, vars, &frames_0); 137 | obj += self.weight_priors[i] * local_obj; 138 | f_0s.push(local_obj); 139 | } 140 | } 141 | 142 | if finite_diff_list.len() > 0 { 143 | for i in 0..x.len() { 144 | let mut x_h = x.to_vec(); 145 | x_h[i] += 0.0000001; 146 | let frames_h = vars.robot.get_frames_immutable(x_h.as_slice()); 147 | for j in &finite_diff_list { 148 | let f_h = self.objectives[*j].call(&x_h, vars, &frames_h); 149 | grad[i] += self.weight_priors[*j] * ((-f_0s[*j] + f_h) / 0.0000001); 150 | } 151 | } 152 | } 153 | 154 | (obj, grad) 155 | } 156 | 157 | fn __gradient_lite(&self, x: &[f64], vars: &RelaxedIKVars) -> (f64, Vec) { 158 | let mut grad: Vec = vec![0. ; x.len()]; 159 | let mut obj = 0.0; 160 | 161 | let mut finite_diff_list: Vec = Vec::new(); 162 | let mut f_0s: Vec = Vec::new(); 163 | let poses_0 = vars.robot.get_ee_pos_and_quat_immutable(x); 164 | for i in 0..self.objectives.len() { 165 | if self.objectives[i].gradient_type() == 1 { 166 | let (local_obj, local_grad) = self.objectives[i].gradient_lite(x, vars, &poses_0); 167 | f_0s.push(local_obj); 168 | obj += self.weight_priors[i] * local_obj; 169 | for j in 0..local_grad.len() { 170 | grad[j] += self.weight_priors[i] * local_grad[j]; 171 | } 172 | } else if self.objectives[i].gradient_type() == 0 { 173 | finite_diff_list.push(i); 174 | let local_obj = self.objectives[i].call_lite(x, vars, &poses_0); 175 | obj += self.weight_priors[i] * local_obj; 176 | f_0s.push(local_obj); 177 | } 178 | } 179 | 180 | if finite_diff_list.len() > 0 { 181 | for i in 0..x.len() { 182 | let mut x_h = x.to_vec(); 183 | x_h[i] += 0.0000001; 184 | let poses_h = vars.robot.get_ee_pos_and_quat_immutable(x_h.as_slice()); 185 | for j in &finite_diff_list { 186 | let f_h = self.objectives[*j].call_lite(x, vars, &poses_h); 187 | grad[i] += self.weight_priors[*j] * ((-f_0s[*j] + f_h) / 0.0000001); 188 | } 189 | } 190 | } 191 | 192 | (obj, grad) 193 | } 194 | 195 | fn __gradient_finite_diff(&self, x: &[f64], vars: &RelaxedIKVars) -> (f64, Vec) { 196 | let mut grad: Vec = vec![0. ; x.len()]; 197 | let mut f_0 = self.call(x, vars); 198 | 199 | for i in 0..x.len() { 200 | let mut x_h = x.to_vec(); 201 | x_h[i] += 0.000001; 202 | let f_h = self.call(x_h.as_slice(), vars); 203 | grad[i] = (-f_0 + f_h) / 0.000001; 204 | } 205 | 206 | (f_0, grad) 207 | } 208 | 209 | fn __gradient_finite_diff_lite(&self, x: &[f64], vars: &RelaxedIKVars) -> (f64, Vec) { 210 | let mut grad: Vec = vec![0. ; x.len()]; 211 | let mut f_0 = self.call(x, vars); 212 | 213 | for i in 0..x.len() { 214 | let mut x_h = x.to_vec(); 215 | x_h[i] += 0.000001; 216 | let f_h = self.__call_lite(x_h.as_slice(), vars); 217 | grad[i] = (-f_0 + f_h) / 0.000001; 218 | } 219 | 220 | (f_0, grad) 221 | } 222 | } -------------------------------------------------------------------------------- /src/relaxed_ik_wrapper.rs: -------------------------------------------------------------------------------- 1 | use crate::relaxed_ik::{RelaxedIK, Opt}; 2 | use std::sync::{Arc, Mutex}; 3 | use nalgebra::{Vector3, Vector6, UnitQuaternion, Quaternion,Translation3, Isometry3}; 4 | use std::os::raw::{*}; 5 | use std::str; 6 | use crate::utils_rust::file_utils::{*}; 7 | 8 | // http://jakegoulding.com/rust-ffi-omnibus/objects/ 9 | #[no_mangle] 10 | pub unsafe extern "C" fn relaxed_ik_new(path_to_setting: *const c_char) -> *mut RelaxedIK { 11 | if path_to_setting.is_null() 12 | { 13 | let path_to_src = get_path_to_src(); 14 | let default_path_to_setting = path_to_src + "configs/settings.yaml"; 15 | return Box::into_raw(Box::new(RelaxedIK::load_settings(default_path_to_setting.as_str()))) 16 | } 17 | let c_str = std::ffi::CStr::from_ptr(path_to_setting); 18 | let path_to_setting_str = c_str.to_str().expect("Not a valid UTF-8 string"); 19 | 20 | Box::into_raw(Box::new(RelaxedIK::load_settings(path_to_setting_str))) 21 | } 22 | 23 | #[no_mangle] 24 | pub unsafe extern "C" fn relaxed_ik_free(ptr: *mut RelaxedIK) { 25 | if ptr.is_null() { return } 26 | Box::from_raw(ptr); 27 | } 28 | 29 | #[no_mangle] 30 | pub unsafe extern "C" fn reset(ptr: *mut RelaxedIK, joint_state: *const c_double, joint_state_length: c_int) { 31 | let relaxed_ik = unsafe { 32 | assert!(!ptr.is_null()); 33 | &mut *ptr 34 | }; 35 | 36 | let x_slice: &[c_double] = std::slice::from_raw_parts(joint_state, joint_state_length as usize); 37 | let x_vec = x_slice.to_vec(); 38 | relaxed_ik.reset(x_vec); 39 | } 40 | 41 | #[no_mangle] 42 | pub unsafe extern "C" fn solve_position(ptr: *mut RelaxedIK, pos_goals: *const c_double, pos_length: c_int, 43 | quat_goals: *const c_double, quat_length: c_int, 44 | tolerance: *const c_double, tolerance_length: c_int) -> Opt { 45 | 46 | let relaxed_ik = unsafe { 47 | assert!(!ptr.is_null()); 48 | &mut *ptr 49 | }; 50 | 51 | assert!(!pos_goals.is_null(), "Null pointer for pos goals!"); 52 | assert!(!quat_goals.is_null(), "Null pointer for quat goals!"); 53 | assert!(!tolerance.is_null(), "Null pointer for tolerance!"); 54 | 55 | assert!(pos_length as usize == relaxed_ik.vars.robot.num_chains * 3 , 56 | "Pos vels are expected to have {} numbers, but got {}", 57 | relaxed_ik.vars.robot.num_chains * 3, pos_length); 58 | assert!(quat_length as usize == relaxed_ik.vars.robot.num_chains * 4, 59 | "Rot vels are expected to have {} numbers, but got {}", 60 | relaxed_ik.vars.robot.num_chains * 4, quat_length); 61 | assert!(tolerance_length as usize == relaxed_ik.vars.robot.num_chains * 6, 62 | "Tolerance are expected to have {} numbers, but got {}", 63 | relaxed_ik.vars.robot.num_chains * 6, tolerance_length); 64 | 65 | let pos_slice: &[c_double] = std::slice::from_raw_parts(pos_goals, pos_length as usize); 66 | let quat_slice: &[c_double] = std::slice::from_raw_parts(quat_goals, quat_length as usize); 67 | let tolerance_slice: &[c_double] = std::slice::from_raw_parts(tolerance, tolerance_length as usize); 68 | 69 | let pos_vec = pos_slice.to_vec(); 70 | let quat_vec = quat_slice.to_vec(); 71 | let tolerance_vec = tolerance_slice.to_vec(); 72 | 73 | let ja = solve_position_helper(relaxed_ik, pos_vec, quat_vec, tolerance_vec); 74 | 75 | let ptr = ja.as_ptr(); 76 | let len = ja.len(); 77 | std::mem::forget(ja); 78 | Opt {data: ptr, length: len as c_int} 79 | } 80 | 81 | 82 | #[no_mangle] 83 | pub unsafe extern "C" fn solve_velocity(ptr: *mut RelaxedIK, pos_vels: *const c_double, pos_length: c_int, 84 | rot_vels: *const c_double, rot_length: c_int, 85 | tolerance: *const c_double, tolerance_length: c_int) -> Opt { 86 | 87 | let relaxed_ik = unsafe { 88 | assert!(!ptr.is_null()); 89 | &mut *ptr 90 | }; 91 | 92 | assert!(!pos_vels.is_null(), "Null pointer for pos vels!"); 93 | assert!(!rot_vels.is_null(), "Null pointer for rot vels!"); 94 | assert!(!tolerance.is_null(), "Null pointer for tolerance!"); 95 | 96 | assert!(pos_length as usize == relaxed_ik.vars.robot.num_chains * 3 , 97 | "Pos vels are expected to have {} numbers, but got {}", 98 | relaxed_ik.vars.robot.num_chains * 3, pos_length); 99 | assert!(rot_length as usize == relaxed_ik.vars.robot.num_chains * 3, 100 | "Rot vels are expected to have {} numbers, but got {}", 101 | relaxed_ik.vars.robot.num_chains * 3, rot_length); 102 | assert!(tolerance_length as usize == relaxed_ik.vars.robot.num_chains * 6, 103 | "Tolerance are expected to have {} numbers, but got {}", 104 | relaxed_ik.vars.robot.num_chains * 6, tolerance_length); 105 | 106 | let pos_slice: &[c_double] = std::slice::from_raw_parts(pos_vels, pos_length as usize); 107 | let rot_slice: &[c_double] = std::slice::from_raw_parts(rot_vels, rot_length as usize); 108 | let tolerance_slice: &[c_double] = std::slice::from_raw_parts(tolerance, tolerance_length as usize); 109 | 110 | let pos_vec = pos_slice.to_vec(); 111 | let rot_vec = rot_slice.to_vec(); 112 | let tolerance_vec = tolerance_slice.to_vec(); 113 | 114 | let ja = solve_velocity_helper(relaxed_ik, pos_vec, rot_vec, tolerance_vec); 115 | 116 | let ptr = ja.as_ptr(); 117 | let len = ja.len(); 118 | std::mem::forget(ja); 119 | Opt {data: ptr, length: len as c_int} 120 | } 121 | 122 | #[no_mangle] 123 | pub unsafe extern "C" fn get_ee_positions(ptr: *mut RelaxedIK) -> Opt { 124 | let relaxed_ik = unsafe { 125 | assert!(!ptr.is_null()); 126 | &mut *ptr 127 | }; 128 | 129 | let mut positions = Vec::new(); 130 | for i in 0..relaxed_ik.vars.goal_positions.len() { 131 | positions.push(relaxed_ik.vars.goal_positions[i].x); 132 | positions.push(relaxed_ik.vars.goal_positions[i].y); 133 | positions.push(relaxed_ik.vars.goal_positions[i].z); 134 | } 135 | let ptr = positions.as_ptr(); 136 | let len = positions.len(); 137 | std::mem::forget(positions); 138 | Opt {data: ptr, length: len as c_int} 139 | } 140 | 141 | // This is mainly for backward compatibility 142 | #[no_mangle] 143 | pub unsafe extern "C" fn solve(ptr: *mut RelaxedIK, pos_goals: *const c_double, pos_length: c_int, 144 | quat_goals: *const c_double, quat_length: c_int, 145 | tolerance: *const c_double, tolerance_length: c_int) -> Opt { 146 | 147 | let relaxed_ik = unsafe { 148 | assert!(!ptr.is_null()); 149 | &mut *ptr 150 | }; 151 | 152 | assert!(!pos_goals.is_null(), "Null pointer for pos goals!"); 153 | assert!(!quat_goals.is_null(), "Null pointer for quat goals!"); 154 | assert!(!tolerance.is_null(), "Null pointer for tolerance!"); 155 | 156 | let pos_slice: &[c_double] = std::slice::from_raw_parts(pos_goals, pos_length as usize); 157 | let quat_slice: &[c_double] = std::slice::from_raw_parts(quat_goals, quat_length as usize); 158 | let tolerance_slice: &[c_double] = std::slice::from_raw_parts(tolerance, tolerance_length as usize); 159 | 160 | let pos_vec = pos_slice.to_vec(); 161 | let quat_vec = quat_slice.to_vec(); 162 | let tolerance_vec = tolerance_slice.to_vec(); 163 | 164 | let ja = solve_position_helper(relaxed_ik, pos_vec, quat_vec, tolerance_vec); 165 | 166 | let ptr = ja.as_ptr(); 167 | let len = ja.len(); 168 | std::mem::forget(ja); 169 | Opt {data: ptr, length: len as c_int} 170 | } 171 | 172 | fn solve_position_helper(relaxed_ik: &mut RelaxedIK, pos_goals: Vec, quat_goals: Vec, 173 | tolerance: Vec) -> Vec { 174 | 175 | for i in 0..relaxed_ik.vars.robot.num_chains { 176 | relaxed_ik.vars.goal_positions[i] = Vector3::new(pos_goals[3*i], pos_goals[3*i+1], pos_goals[3*i+2]); 177 | let tmp_q = Quaternion::new(quat_goals[4*i+3], quat_goals[4*i], quat_goals[4*i+1], quat_goals[4*i+2]); 178 | relaxed_ik.vars.goal_quats[i] = UnitQuaternion::from_quaternion(tmp_q); 179 | relaxed_ik.vars.tolerances[i] = Vector6::new( tolerance[6*i], tolerance[6*i+1], tolerance[6*i+2], 180 | tolerance[6*i+3], tolerance[6*i+4], tolerance[6*i+5]) 181 | } 182 | 183 | let x = relaxed_ik.solve(); 184 | return x; 185 | } 186 | 187 | fn solve_velocity_helper(relaxed_ik: &mut RelaxedIK, pos_vels: Vec, rot_vels: Vec, 188 | tolerance: Vec) -> Vec { 189 | 190 | for i in 0..relaxed_ik.vars.robot.num_chains { 191 | relaxed_ik.vars.goal_positions[i] += Vector3::new(pos_vels[3*i], pos_vels[3*i+1], pos_vels[3*i+2]); 192 | let axisangle = Vector3::new(rot_vels[3*i], rot_vels[3*i+1], rot_vels[3*i+2]); 193 | let tmp_q = UnitQuaternion::from_scaled_axis(axisangle); 194 | let org_q = relaxed_ik.vars.goal_quats[i].clone(); 195 | relaxed_ik.vars.goal_quats[i] = tmp_q * org_q; 196 | relaxed_ik.vars.tolerances[i] = Vector6::new( tolerance[3*i], tolerance[3*i+1], tolerance[3*i+2], 197 | tolerance[3*i+3], tolerance[3*i+4], tolerance[3*i+5]) 198 | } 199 | 200 | let x = relaxed_ik.solve(); 201 | 202 | 203 | let frames = relaxed_ik.vars.robot.get_frames_immutable(&x); 204 | let last = frames[0].0.len() - 1 ; 205 | let ee_pos = frames[0].0[last]; 206 | let goal = relaxed_ik.vars.goal_positions[0]; 207 | let dist = (ee_pos - goal).norm(); 208 | 209 | return x; 210 | } 211 | -------------------------------------------------------------------------------- /configs/urdfs/spot_arm.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | -------------------------------------------------------------------------------- /configs/urdfs/mobile_spot_arm.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | --------------------------------------------------------------------------------