diff --git a/assets/scripts/features/math/katex.js b/assets/scripts/features/math/katex.js index 6ba0dc8..b5a4bcb 100644 --- a/assets/scripts/features/math/katex.js +++ b/assets/scripts/features/math/katex.js @@ -5,7 +5,7 @@ const defaultOptions = { delimiters: [ { left: '$$', right: '$$', display: true }, { left: '\\[', right: '\\]', display: true }, - { left: '$', right: '$', display: false }, + { left: '$', right: '$', display: true }, { left: '\\(', right: '\\)', display: false } ] } diff --git a/config.yaml b/config.yaml index 3d2f2ae..05cf9e1 100644 --- a/config.yaml +++ b/config.yaml @@ -31,6 +31,8 @@ module: target: i18n - source: archetypes target: archetypes + - source: "dist/katex.js" + target: ../../assets/scripts/features/math/katex.js - source: ../../node_modules/flag-icons/flags target: static/flags - source: ../../node_modules/@fontsource/mulish/files @@ -78,77 +80,46 @@ params: id: "G-D5RCC030C7" # specify whether you want to show Table of Contents in reading page - toc: - enable: true + toc: + enable: true - # Show tags under the post title - tags: - enable: true - on_card: true # enables tags in post cards + copyCodeButton: + enable: true + + syntaxHighlight: + enable: true + services: + hljs: + # see: https://highlightjs.readthedocs.io/en/latest/api.html#configure + noHighlightRe: /^no-highlight$/i -# Enable this to use `embed-pdf` shortcode. - embedpdf: - enable: false + # Enable this to use `embed-pdf` shortcode. + embedpdf: + enable: false # Enable this to create flowcharts using shortcodes. - flowchart: - enable: false - services: - # Uncomment for `mermaid` shortcode. - mermaid: - # For config options, see: https://mermaid-js.github.io/mermaid/#/Setup?id=configuration - # theme: dark + flowchart: + enable: false + services: + # Uncomment for `mermaid` shortcode. + mermaid: + # For config options, see: https://mermaid-js.github.io/mermaid/#/Setup?id=configuration + # theme: dark # Enable this to create mathematic expressions using `$$` blocks - math: - enable: true - services: - # https://katex.org/docs/autorender.html#api for more configurations - katex: - delimiters: - - left: $$ - right: $$ - display: true - - left: \\[ - right: \\] - display: true - - left: $ - right: $ - display: false - - left: \\( - right: \\) - display: false - - # Enable to use custom syntax highlight - # Please note, Hugo comes with it's own html based syntax highlighter. - # Your code block will still be syntax highlighted by hugo. - # For more details: https://gohugo.io/content-management/syntax-highlighting/ - # To disable Hugo's builtin syntax highlight, - # see: https://gohugo.io/getting-started/configuration-markup#highlight - # ``` - # # config.yaml - # markup: - # # this disables hugo's syntax highlighting. - # codeFences: false - # ``` - syntaxHighlight: - enable: true - services: - hljs: - # see: https://highlightjs.readthedocs.io/en/latest/api.html#configure - noHighlightRe: /^no-highlight$/i + math: + enable: true + services: + katex: true + # https://katex.org/docs/autorender.html#api for more configurations # Enable to use `video-player` shortcode - videoPlayer: - enable: false - services: - # convert .js-player class into video player via https://plyr.io/ - # Can play HTML5 Video, Audio, Youtube, Vimeo. - # For more info on setup: https://github.com/sampotts/plyr#quick-setup - plyr: - # options doc: https://github.com/sampotts/plyr#options - # fullscreen: true - - # Enables copy code button - copyCodeButton: - enable: true + videoPlayer: + enable: false + services: + # convert .js-player class into video player via https://plyr.io/ + # Can play HTML5 Video, Audio, Youtube, Vimeo. + # For more info on setup: https://github.com/sampotts/plyr#quick-setup + plyr: + # options doc: https://github.com/sampotts/plyr#options + # fullscreen: true diff --git a/content/posts/mobile-manipulation/index.md b/content/posts/mobile-manipulation/index.md index c2c1be6..aabb27a 100644 --- a/content/posts/mobile-manipulation/index.md +++ b/content/posts/mobile-manipulation/index.md @@ -14,8 +14,112 @@ tags: ["Basic", "Multi-lingual"] categories: ["Basic"] --- -Greeting! This is an introduction post. This post tests the followings: +This project incorporates several robotics concepts to perform a pick and place task in simulation using a mecanum-wheeled mobile robot with a 5 degree-of-freedom robot arm. -- Hero image is in the same directory as the post. -- This post should be at top of the sidebar. -- Post author should be the same as specified in `author.yaml` file. +![Robot](robot.png) + +## Omnidirectional Mobile Base Kinematics (Mecanum Wheels) +This robot uses mecanum wheels, which are omnidirectional wheels with 45-degree rollers that allow the robot to move in any direction without changing its orientation. When controlling the robot, we command the wheel velocities, which can be described by the following equation: + +$$ +u_i=\frac{1}{r_i}\overbrace{\begin{bmatrix}1 & \tan\gamma_i\end{bmatrix}}^{\text{driving direction}}\underbrace{\begin{bmatrix}\cos\beta_i & \sin\beta_i \\\ -\sin\beta_i & \cos\beta_i\end{bmatrix}}_{\text{linear velocity in wheel frame}} +\overbrace{\begin{bmatrix}-y_i & 1 & 0 \\\ x_i & 0 & 1\end{bmatrix}}^{\text{linear velocity in body frame}} V_b +$$ + +where: +- \\(u_i\\) is the wheel velocity +- \\(r_i\\) is the wheel radius +- \\(\gamma_i\\) is the angle of the roller relative to the wheel's driving direction +- \\(\beta_i\\) is the angle of the wheel relative to the robot's x-axis +- \\(x_i\\) and \\(y_i\\) are the x and y coordinates of the wheel relative to the robot's center +- \\(V_b\\) is the robot's 3D body twist, composed of the linear and angular velocity: \\([v_x, v_y, \omega]\\) + +![Mecanum Base](mecanum_base.png) + +## Odometry +Odometry is the process of estimating the mobile robot's pose by integrating the wheel velocities. The robot's pose is represented by the chassis configuration \\([\phi, x, y]\\), where \\(\phi\\) is the orientation and \\(x, y\\) are the position in the world frame. + +The odometry function computes the new chassis configuration based on the difference between the current and previous wheel configurations assuming a constant velocity between the two wheel configurations. +```python +def odometry(chassis_config: np.array, delta_wheel_config: np.array) -> np.array: + """ + Using Odometry, a new chassis configuration is computed based on the + difference between the current and the previous wheel configuration. + + Args: + chassis_config (np.array): The current chassis configuration [phi, x, y] + delta_wheel_config (np.array): The difference in wheel configuration + + Returns: + np.array: The new chassis configuration [phi, x, y] + """ + phi, x, y = chassis_config + # delta_theta is the difference in wheel angles + # Since we are assuming constant wheel speeds, dt = 1 + dt = 1 # Use actual timestep between wheel displacements for non-constant speeds + theta_dot = delta_wheel_config / dt + # Calculate the Body twist using the pinv(H0) and theta_dot + V_b = RC.F @ theta_dot + # Integrate to get the displacement: T_bk = exp([V_b6]) + V_b6 = np.array([0, 0, *V_b, 0]) + T_bk = mr.MatrixExp6(mr.VecTose3(V_b6)) + T_sk = RC.T_sb(phi, x, y) @ T_bk + new_phi = np.arctan2(T_sk[1, 0], T_sk[0, 0]) + new_chassis_config = np.array([ + new_phi, + T_sk[0, 3], + T_sk[1, 3] + ]) + return new_chassis_config +``` + +## Task-Space Feedforward & Feedback Control +To perform the pick and place task, we need to implement a control law that can track a desired end-effector trajectory. The control law is given by: + +$$ +V_e(t) = \overbrace{[Ad_{X^{-1}X_d}]V_d(t)}^{\text{Feedforward}} + K_pX_{err}(t) + K_i \int X_{err}(t) +$$ + +where: +- \\(V_e(t)\\) is the error twist required to track the desired trajectory +- \\(X\\) is the current end-effector configuration +- \\(X_d\\) is the desired end-effector configuration +- \\(V_d(t)\\) is the desired end-effector twist +- \\(K_p\\) is the proportional gain matrix +- \\(K_i\\) is the integral gain matrix +- \\(X_{err}(t)\\) is the error between the current and desired end-effector configurations + +```python +def feedback_control(X, Xd, Xd_next, Kp, Ki, control_type: str = 'FF+PI', dt: float = 0.01) -> tuple: + """ + Calculate the kinematic task-space feedforward plus feedback control law. + V(t) = [Adjoint(inv(X)*Xd)]V_d(t) + Kp*X_err(t) + Ki*integral(X_err(t)) + Args: + X (np.array): The current actual end-effector configuration (T_se) + Xd (np.array): The current end-effector reference configuration (T_se,d) + Xd_next (np.array): The end-effector reference configuration at the next timestep in the reference trajectory + Kp (np.array): The Proportional gain matrix + Ki (np.array): The Integral gain matrix + control_type (str, optional): The type of simulation. Defaults to 'FF+PI'. ['FF+PI', 'P', 'PI'] + dt (float, optional): The timestep between reference trajectory configs. Defaults to 0.01. + Returns: + tuple: A tuple containing the twist V and the error X_err + """ + X_err = mr.se3ToVec(mr.MatrixLog6(mr.TransInv(X) @ Xd)) + # print(f'X_err:\n{np.round(X_err, 3)}') + Vd = mr.se3ToVec((1/dt) * mr.MatrixLog6(mr.TransInv(Xd) @ Xd_next)) + # print(f'Vd:\n{np.round(Vd, 3)}') + if control_type == 'FF+PI': + V = mr.Adjoint(mr.TransInv(X) @ Xd) @ Vd + \ + (Kp @ X_err) + (Ki @ (X_err * dt)) + elif control_type == 'P': + V = (Kp @ X_err) + elif control_type == 'PI': + V = (Kp @ X_err) + (Ki @ (X_err * dt)) + else: + print(f'Invalid sim_type: {control_type}, using FF+PI') + V = mr.Adjoint(mr.TransInv(X) @ Xd) @ Vd + \ + (Kp @ X_err) + (Ki @ (X_err * dt)) + # print(f'V:\n{np.round(V, 3)}') + return V, X_err +``` \ No newline at end of file diff --git a/content/posts/mobile-manipulation/mecanum_base.png b/content/posts/mobile-manipulation/mecanum_base.png new file mode 100644 index 0000000..56db983 Binary files /dev/null and b/content/posts/mobile-manipulation/mecanum_base.png differ diff --git a/content/posts/mobile-manipulation/robot.png b/content/posts/mobile-manipulation/robot.png new file mode 100644 index 0000000..0af782a Binary files /dev/null and b/content/posts/mobile-manipulation/robot.png differ diff --git a/data/en/sections/projects.yaml b/data/en/sections/projects.yaml index a5927b3..11f49bc 100644 --- a/data/en/sections/projects.yaml +++ b/data/en/sections/projects.yaml @@ -23,7 +23,7 @@ section: projects: - name: Mobile Manipulation image: /images/mobile_robot.gif - role: Final Project for ME449-Robotic Manipulation + role: "ME449: Robotic Manipulation Final Project" timeline: "Nov 2024 - Dec 2024" repo: https://github.com/Sharwin24/Mobile-Manipulation url: "/toha/posts/mobile-manipulation/"