Skip to content

Commit 83c079b

Browse files
raptor
1 parent f642a37 commit 83c079b

File tree

6 files changed

+108
-13
lines changed

6 files changed

+108
-13
lines changed

blob

Submodule blob updated 1 file

index.css

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1+
html, body {
2+
height: 100%;
3+
font-family: "Open Sans", sans-serif;
4+
}
15
body {
26
display: flex;
37
flex-direction: column;
4-
height: 100dvh;
8+
height: 100svh;
59
margin: 0;
6-
overflow: hidden;
710
}
811
#top-container {
912
display: flex;
1013
flex-direction: row;
11-
flex-grow: 1;
14+
flex: 1 1 auto;
1215
min-height: 0;
1316
}
1417
#vehicle-container{
1518
width: 0px;
1619
overflow: auto;
1720
white-space: nowrap;
21+
min-height: 0;
22+
min-width: 0;
1823
}
1924
#vehicle-container-header{
2025
margin: 10px;
@@ -60,10 +65,12 @@ body {
6065
background-color: white;
6166
flex: 1;
6267
min-width: 0;
68+
min-height: 0;
6369
}
6470
#controls-box{
65-
background-color: #c5c5c5;
66-
overflow:auto;
71+
overflow: auto;
72+
flex: 0 0 auto;
73+
max-height: 50svh;
6774
}
6875
.controls-container {
6976
display: flex;
@@ -255,4 +262,51 @@ canvas{
255262
#reference-trajectory-options{
256263
display:flex;
257264
flex-wrap: wrap;
265+
}
266+
267+
268+
.fancy-button {
269+
display: inline-block;
270+
margin: 5px;
271+
font-family: "Open Sans", sans-serif;
272+
font-weight: bold;
273+
text-transform: uppercase;
274+
text-decoration: none;
275+
letter-spacing: 2px;
276+
padding: 20px 40px;
277+
border: none;
278+
border-radius: 50px;
279+
background: linear-gradient(to right, #6fd0cb, #7DB9B6);
280+
color: #fff;
281+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
282+
cursor: pointer;
283+
transition: all 0.2s ease-in-out;
284+
white-space: nowrap;
285+
}
286+
287+
.fancy-button:hover{
288+
transform: translateY(-5px);
289+
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.3);
290+
}
291+
292+
.fancy-button:disabled {
293+
background: linear-gradient(to right, #cccccc, #dddddd);
294+
color: #666666;
295+
cursor: not-allowed;
296+
box-shadow: none;
297+
opacity: 0.7;
298+
}
299+
300+
301+
.fancy-button-small{
302+
letter-spacing: 1px;
303+
padding: 10px 20px;
304+
border-radius: 25px;
305+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
306+
font-size: 70%;
307+
}
308+
309+
.fancy-button-small:hover{
310+
transform: translateY(-2.5px);
311+
box-shadow: 0 4px 7.5px rgba(0, 0, 0, 0.3);
258312
}

index.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,26 @@
9393
<div id="sim-container"></div>
9494
</div>
9595
<div id="controls-box">
96+
<div id="raptor-project-page" class="controls-container" style="display: none;">
97+
<center>
98+
<h1 style="margin: 0; margin-bottom: 5px;"><img src="./blob/logo.svg" style="width: 13rem; vertical-align: middle;"></img>: A Foundation Policy for Quadrotor Control</h1>
99+
<h3 style="margin: 0; margin-bottom: 10px;">Jonas Eschmann, Dario Albani, Giuseppe Loianno</h3>
100+
<a class="fancy-button fancy-button-small" href="https://github.com/rl-tools/foundation-policy">Code on Github</a>
101+
<a class="fancy-button fancy-button-small" href="">Paper on ArXiV</a>
102+
<div style="margin: 10px;">
103+
<iframe src="https://www.youtube.com/embed/PdRgxDDvUws?si=jToj556_kJDtVbhx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
104+
</div>
105+
<div style="margin: 10px;">
106+
This web app allows you to torture the <img src="./blob/logo.svg" style="width: 7rem; vertical-align: middle;"></img> foundation policy using different quadrotor models, reference trajectories and disturbances.
107+
You can reset the episodes by pressing "Sample Initial States". You can simulate step-by-step using "Pause on Reset" and then "Step" throught the episode.
108+
<br>
109+
The "X Offset" spreads out the quadrotors (click it to change to Y/Z offset).
110+
You can drag the sidebar next to the 3D view to reveal the menu for loading dynamics parameters.
111+
You can select one of the presets in the dropdown as well as load parameters from disk, following the l2f json format.
112+
The last row allows you to perturb dynamics parameters based on a simple formula (hover over the formula input for a description of the variables).
113+
</div>
114+
</center>
115+
</div>
96116
<div id="controller-options-container" class="controls-container controls-container-every-other">
97117
<div id="controller-selector-container">
98118
<form id="controller-selector-form">

index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ async function load_model(checkpoint) {
201201
}
202202

203203
async function main() {
204+
if(window.location.hostname === "raptor.rl.tools" || urlParams.get("raptor") === "true"){
205+
document.getElementById("raptor-project-page").style.display = "block";
206+
}
204207
const trajectory_offset_container = document.getElementById("reference-trajectory-offset-container")
205208
const trajectory_offset_slider = trajectory_offset_container.querySelector("input[type=range]")
206209
const trajectory_offset_label = trajectory_offset_container.querySelectorAll(".control-container-label")[0]

l2f.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,31 @@ export class L2F{
5151
const dpr = window.devicePixelRatio || 1;
5252
const resizeCanvas = () => {
5353
const parentRect = parent.getBoundingClientRect();
54-
this.canvas.style.width = parentRect.width + 'px';
55-
this.canvas.style.height = parentRect.height + 'px';
56-
this.canvas.width = parentRect.width * dpr;
57-
this.canvas.height = parentRect.height * dpr;
54+
const newWidth = parentRect.width;
55+
const newHeight = parentRect.height;
56+
57+
// Only update if dimensions actually changed
58+
if (this.canvas.style.width !== newWidth + 'px' ||
59+
this.canvas.style.height !== newHeight + 'px') {
60+
61+
this.canvas.style.width = newWidth + 'px';
62+
this.canvas.style.height = newHeight + 'px';
63+
this.canvas.width = newWidth * dpr;
64+
this.canvas.height = newHeight * dpr;
65+
}
5866
};
59-
resizeCanvas()
60-
window.addEventListener('resize', resizeCanvas.bind(this), false);
67+
resizeCanvas();
68+
69+
// Use ResizeObserver for better resize detection
70+
if ('ResizeObserver' in window) {
71+
this.resizeObserver = new ResizeObserver(entries => {
72+
resizeCanvas();
73+
});
74+
this.resizeObserver.observe(parent);
75+
} else {
76+
// Fallback for older browsers
77+
window.addEventListener('resize', resizeCanvas.bind(this), false);
78+
}
6179
this.policy = policy
6280

6381
this.initialized = createModule().then(async (l2f_interface) => {

ui.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ export class DroneDefault{
337337
}
338338

339339
async function drone_factory(parameters, origin, displayIMUCoordinateSystem, displayActions){
340-
if(parameters.ui && parameters.ui.model){
340+
if(parameters.ui && parameters.ui.enable && parameters.ui.model){
341341
try{
342342
const model = new DroneMesh(parameters, origin, displayIMUCoordinateSystem, displayActions)
343343
await model.loaded

0 commit comments

Comments
 (0)