Spaces:
Running
Running
fix urdf viewer
Browse files
src/components/UrdfViewer.tsx
CHANGED
@@ -22,6 +22,7 @@ import {
|
|
22 |
if (typeof window !== "undefined" && !customElements.get("urdf-viewer")) {
|
23 |
customElements.define("urdf-viewer", URDFManipulator);
|
24 |
}
|
|
|
25 |
|
26 |
// Extend the interface for the URDF viewer element to include background property
|
27 |
interface UrdfViewerElement extends HTMLElement {
|
@@ -167,6 +168,66 @@ const UrdfViewer: React.FC = () => {
|
|
167 |
setHighlightedJoint
|
168 |
);
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
// Setup animation event handler for the default model or when hasAnimation is true
|
171 |
const onModelProcessed = () => {
|
172 |
hasInitializedRef.current = true;
|
@@ -177,6 +238,8 @@ const UrdfViewer: React.FC = () => {
|
|
177 |
cleanupAnimationRef.current = null;
|
178 |
}
|
179 |
}
|
|
|
|
|
180 |
};
|
181 |
|
182 |
viewer.addEventListener("urdf-processed", onModelProcessed);
|
@@ -192,7 +255,13 @@ const UrdfViewer: React.FC = () => {
|
|
192 |
cleanupModelLoading();
|
193 |
viewer.removeEventListener("urdf-processed", onModelProcessed);
|
194 |
};
|
195 |
-
}, [
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
|
197 |
return (
|
198 |
<div
|
|
|
22 |
if (typeof window !== "undefined" && !customElements.get("urdf-viewer")) {
|
23 |
customElements.define("urdf-viewer", URDFManipulator);
|
24 |
}
|
25 |
+
import * as THREE from "three";
|
26 |
|
27 |
// Extend the interface for the URDF viewer element to include background property
|
28 |
interface UrdfViewerElement extends HTMLElement {
|
|
|
168 |
setHighlightedJoint
|
169 |
);
|
170 |
|
171 |
+
// Function to fit the robot to the camera view
|
172 |
+
const fitRobotToView = (viewer: URDFViewerElement) => {
|
173 |
+
if (!viewer || !viewer.robot) {
|
174 |
+
console.log(
|
175 |
+
"[RobotViewer] Cannot fit to view: No viewer or robot available"
|
176 |
+
);
|
177 |
+
return;
|
178 |
+
}
|
179 |
+
|
180 |
+
try {
|
181 |
+
// Create a bounding box for the robot
|
182 |
+
const boundingBox = new THREE.Box3().setFromObject(viewer.robot);
|
183 |
+
|
184 |
+
// Calculate the center of the bounding box
|
185 |
+
const center = new THREE.Vector3();
|
186 |
+
boundingBox.getCenter(center);
|
187 |
+
|
188 |
+
// Calculate the size of the bounding box
|
189 |
+
const size = new THREE.Vector3();
|
190 |
+
boundingBox.getSize(size);
|
191 |
+
|
192 |
+
// Get the maximum dimension to ensure the entire robot is visible
|
193 |
+
const maxDim = Math.max(size.x, size.y, size.z);
|
194 |
+
|
195 |
+
// Position camera to see the center of the model
|
196 |
+
viewer.camera.position.copy(center);
|
197 |
+
|
198 |
+
// Move the camera back to see the entire robot
|
199 |
+
// Use the model's up direction to determine which axis to move along
|
200 |
+
const upVector = new THREE.Vector3();
|
201 |
+
if (viewer.up === "+Z" || viewer.up === "Z") {
|
202 |
+
upVector.set(1, 1, 1); // Move back in a diagonal
|
203 |
+
} else if (viewer.up === "+Y" || viewer.up === "Y") {
|
204 |
+
upVector.set(1, 1, 1); // Move back in a diagonal
|
205 |
+
} else {
|
206 |
+
upVector.set(1, 1, 1); // Default direction
|
207 |
+
}
|
208 |
+
|
209 |
+
// Normalize the vector and multiply by the size
|
210 |
+
upVector.normalize().multiplyScalar(maxDim * 1.3);
|
211 |
+
viewer.camera.position.add(upVector);
|
212 |
+
|
213 |
+
// Make the camera look at the center of the model
|
214 |
+
viewer.controls.target.copy(center);
|
215 |
+
|
216 |
+
// Update controls and mark for redraw
|
217 |
+
viewer.controls.update();
|
218 |
+
viewer.redraw();
|
219 |
+
|
220 |
+
console.log("[RobotViewer] Robot auto-fitted to view");
|
221 |
+
} catch (error) {
|
222 |
+
console.error("[RobotViewer] Error fitting robot to view:", error);
|
223 |
+
}
|
224 |
+
};
|
225 |
+
|
226 |
+
// Add event listener for when the robot is loaded to auto-fit to view
|
227 |
+
const onRobotLoad = () => {
|
228 |
+
fitRobotToView(viewer);
|
229 |
+
};
|
230 |
+
|
231 |
// Setup animation event handler for the default model or when hasAnimation is true
|
232 |
const onModelProcessed = () => {
|
233 |
hasInitializedRef.current = true;
|
|
|
238 |
cleanupAnimationRef.current = null;
|
239 |
}
|
240 |
}
|
241 |
+
// Auto-fit the robot to view when the model is processed
|
242 |
+
onRobotLoad();
|
243 |
};
|
244 |
|
245 |
viewer.addEventListener("urdf-processed", onModelProcessed);
|
|
|
255 |
cleanupModelLoading();
|
256 |
viewer.removeEventListener("urdf-processed", onModelProcessed);
|
257 |
};
|
258 |
+
}, [
|
259 |
+
isDefaultModel,
|
260 |
+
customUrdfPath,
|
261 |
+
urlModifierFunc,
|
262 |
+
defaultUrlModifier,
|
263 |
+
alternativeUrdfModels,
|
264 |
+
]);
|
265 |
|
266 |
return (
|
267 |
<div
|