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
|