Skip to content

Commit ba55e73

Browse files
committed
added videos
1 parent a87ea7a commit ba55e73

3 files changed

Lines changed: 77 additions & 4 deletions

File tree

content/robotics/rovi.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,22 @@ features:
1212

1313
# Github
1414

15+
The source code of all ROS2 packages developed in this project are available in this repo. The readme contains detailed documentation and diagrams.
16+
1517
:button[]{label="Rovi ROS2 Jazzy Workspace" link="https://github.com/Roblibs/rovi_ros_ws" icon="github"}
1618

1719
# Description
1820
A car robot platform based on the Yahboom Rosmaster X3-Plus mecanum chassis, customized sensors and fresh new ROS2 Jazzy software for native ubuntu 24 development (no docker) on Raspberry pi 5
1921

20-
![rovi-controlled-with-joystick](./room_view_bot/20251018_141343.jpg)
22+
Video from the latest development stage. The robot can navigate to a goal while building a map with SLAM, control can also be overriden from a Joystick.
23+
24+
:iframe[]{src="https://youtu.be/TfBXTf1QenI" title="Centered Video" center}
25+
26+
27+
This video below demonstrates the Mecanum wheels omnidirectional capabilities
28+
29+
:iframe[]{src="https://youtu.be/-Qnhs4Jbu7k" title="Centered Video" center}
2130

22-
Photo from the latest development stage. The robot can be controlled with PS4 joystick over bluetooth and using python and Rosmaster_Lib.
2331

2432
# Steps
2533

@@ -29,7 +37,7 @@ This robot will be built in stage with progressive functionalities
2937
| --- | --- | --- | --- | --- | --- |
3038
| Manual | Done | Test car movement with a Joystick | WiFi, M-Control, BT Joystick | 12_V | Raspi_Ports |
3139
| Slam | Done | ROS2 Slam with Lidar | WiFi, M-Control, Lidar | 12_V + USB_Bank | x1 Hub |
32-
| Navi | - | ROS2 Slam+Nav with Lidar | WiFi, M-Control, Lidar | 12_V + USB_Bank | x1 Hub |
40+
| Navi | Done | ROS2 Slam+Nav with Lidar | WiFi, M-Control, Lidar | 12_V + USB_Bank | x1 Hub |
3341
| Navi+ | - | Slam+Nav with Depth obstacles avoidance | WiFi, M-Control, Lidar, Depth | 12_V + USB_Bank | x1 Hub |
3442
| VR | - | Stereo Camera for Virtual Reality telepresence and inspection | WiFi, M-Control, Lidar, Depth, Stereo_Cam | 12_V + USB_Bank | x1 Hub |
3543
| Interaction | - | Interactive voice communication | WiFi, M-Control, Lidar, Depth, Stereo_Cam, Mic_Array, Speaker | 12_V + USB_Bank | x2 Hubs |

src/components/markdown/directive/Directive.astro

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import ImageDirective from './ImageDirective.astro';
88
//import ImageDirective from './OptimizedImageDirective.astro';
99
import ButtonDirective from './ButtonDirective.astro'
10+
import IframeDirective from './IframeDirective.astro'
1011
1112
export interface Props {
1213
node: object;
@@ -17,7 +18,8 @@ const { node, dirpath} = Astro.props as Props;
1718
1819
const is_image = (node.name == "image")
1920
const is_button = (node.name == "button")
20-
const is_other = !(is_image || is_button)
21+
const is_iframe = (node.name == "iframe")
22+
const is_other = !(is_image || is_button || is_iframe)
2123
2224
---
2325
{is_image &&
@@ -26,6 +28,9 @@ const is_other = !(is_image || is_button)
2628
{is_button &&
2729
<ButtonDirective label={node.attributes.label} link={node.attributes.link} icon={node.attributes.icon} />
2830
}
31+
{is_iframe &&
32+
<IframeDirective node={node} dirpath={dirpath} />
33+
}
2934
{is_other &&
3035
<div>{node.name}
3136
{Object.keys(node.attributes).map((key)=>(<span>{key} = {node.attributes[key]}</span>))}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
export interface Props {
3+
node: object;
4+
dirpath: string;
5+
}
6+
7+
const { node, dirpath } = Astro.props as Props;
8+
9+
// Get the src attribute
10+
let src = node.attributes.src || "";
11+
12+
// Convert YouTube URLs to embed format
13+
if (src.includes("youtu.be/")) {
14+
// Format: https://youtu.be/VIDEO_ID?si=XXXX
15+
const match = src.match(/youtu\.be\/([^?]+)/);
16+
if (match) {
17+
src = `https://www.youtube.com/embed/${match[1]}`;
18+
}
19+
} else if (src.includes("youtube.com/watch")) {
20+
// Format: https://www.youtube.com/watch?v=VIDEO_ID
21+
const match = src.match(/[?&]v=([^&]+)/);
22+
if (match) {
23+
src = `https://www.youtube.com/embed/${match[1]}`;
24+
}
25+
}
26+
27+
const title = node.attributes.title || "";
28+
const width = node.attributes.width || "560";
29+
const height = node.attributes.height || "315";
30+
31+
let containerClass = "iframe-container";
32+
if (Object.hasOwn(node.attributes, "center")) {
33+
containerClass += " center";
34+
}
35+
---
36+
37+
<div class={containerClass}>
38+
<iframe
39+
src={src}
40+
title={title}
41+
width={width}
42+
height={height}
43+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
44+
allowfullscreen
45+
></iframe>
46+
</div>
47+
48+
<style>
49+
.iframe-container {
50+
margin-bottom: 1em;
51+
}
52+
.center {
53+
display: flex;
54+
justify-content: center;
55+
}
56+
iframe {
57+
border: none;
58+
max-width: 100%;
59+
}
60+
</style>

0 commit comments

Comments
 (0)