uniapp中加载.urdf后缀的3D模型(three.js+urdf-loader)
安装包
{"dependencies": {"sass": "^1.90.0","three": "^0.179.1","urdf-loader": "^0.12.6"}
}
1、准备好.urdf模型放在uniapp目录中的/static/model目录下面
2.查看urdf文件里面filename加载的路径(兼容于uniapp)
例如:
<mesh filename="package://piper_description/meshes/dae/base_link.dae" />
如果urdf文件里面有这种package://
开头的路径,则需要替换成:
<mesh filename="meshes/dae/base_link.dae" />
这里需要注意das文件需要放在/static/model/meshes/dae
目录下面,如上图目录所示
原因:
- package://的依赖性
package://是ROS特有的路径解析协议,依赖ROS环境(如roslaunch或rosrun)动态解析包路径。
如果直接在非ROS环境(如纯Gazebo、Web应用或静态文件服务器)中使用URDF,系统无法识别package://,导致模型加载失败。 - 静态部署的兼容性
当URDF文件需要部署到不支持ROS的场景(如通过HTTP服务器加载模型),必须使用相对路径或绝对路径,确保文件能被正确解析。
3、代码中编写
这里需要格外注意一下js中的urdf路径是否正确,请查看我标记的【重点】字眼
<template><view class="robot-model-container"><!-- three.js 渲染容器 --><view ref="container" class="canvas-container"></view></view>
</template>
import {ref,onMounted,onBeforeUnmount} from 'vue'import * as THREE from 'three'import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'import URDFLoader from 'urdf-loader'const {windowWidth,windowHeight} = uni.getSystemInfoSync()const container = ref(null)let renderer, scene, camera, controls, robot;onMounted(() => {// 创建场景scene = new THREE.Scene()scene.background = new THREE.Color(0xeeeeee) //设置背景颜色// 相机camera = new THREE.PerspectiveCamera(45, 1, 0.1, 1000)camera.position.set(0.7, 0.7, 0.7) //视觉大小// 渲染器renderer = new THREE.WebGLRenderer({antialias: true})renderer.setSize(windowWidth, windowHeight) // 固定大小,避免 uniapp 没有 windowcontainer.value.$el.appendChild(renderer.domElement)// 光源const light = new THREE.DirectionalLight(0xffffff, 1)light.position.set(10, 10, 10)scene.add(light)scene.add(new THREE.AmbientLight(0x404040))// 控制器controls = new OrbitControls(camera, renderer.domElement)// 加载 URDF 模型const loader = new URDFLoader()loader.packages = {piper_description: '/model' // 对应public目录下的资源路径【重点】}loader.load('/static/model/xxxxxx.urdf', (urdf) => { //路径【重点】robot = urdfrobotControl.value = urdfrobot.rotation.x = -Math.PI / 2scene.add(robot)console.log('控制列表==========', robot.joints);animate()})})onBeforeUnmount(() => {if (renderer) {renderer.dispose()}})// 动画循环function animate() {requestAnimationFrame(animate)controls.update()renderer.render(scene, camera)}
4、控制3D模型可以控制器
在上面代码中我们可以获取到控制器列表robot.joints
下面是一段进行控制器的代码
function rebackFun() {//这里需要自己去打印看一下robot.joints有哪些控制器名称,还有它的取值范围是多少robot.joints.joint1.setJointValue(0)
}