🛸 Adds tranformcontroller for body
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { BufferGeometry, Line, LineBasicMaterial, Vector3, type NormalBufferAttributes } from 'three';
|
||||
import { BufferGeometry, Line, LineBasicMaterial, Mesh, MeshBasicMaterial, Object3D, SphereGeometry, Vector3, type NormalBufferAttributes, type Object3DEventMap } from 'three';
|
||||
import uzip from 'uzip';
|
||||
import { kinematicData, model, outControllerData, servoAnglesOut } from '$lib/stores';
|
||||
import { ModesEnum, kinematicData, mode, model, outControllerData, servoAnglesOut } from '$lib/stores';
|
||||
import { footColor, isEmbeddedApp, throttler, toeWorldPositions } from '$lib/utilities';
|
||||
import { fileService } from '$lib/services';
|
||||
import { servoAngles, mpu, jointNames } from '$lib/stores';
|
||||
import SceneBuilder from '$lib/sceneBuilder';
|
||||
import { lerp, degToRad } from 'three/src/math/MathUtils';
|
||||
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
|
||||
import Kinematic, { type position_t } from '$lib/kinematic';
|
||||
import Kinematic, { GaitPlanner, type body_state_t } from '$lib/kinematic';
|
||||
import { radToDeg } from 'three/src/math/MathUtils.js';
|
||||
import type { URDFRobot } from 'urdf-loader';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
export let sky = true
|
||||
export let orbit = false
|
||||
@@ -28,8 +30,12 @@
|
||||
|
||||
let feet_trace = new Array(4).fill([]);
|
||||
let trace_lines: BufferGeometry<NormalBufferAttributes>[] = []
|
||||
let target: Object3D<Object3DEventMap>;
|
||||
|
||||
let target_position = {x: 0, z: 0, yaw: 0}
|
||||
|
||||
let kinematic = new Kinematic()
|
||||
let gaitPlanner = new GaitPlanner()
|
||||
const dir = [-1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1]
|
||||
const Lp = [
|
||||
[100, -100, 100, 1],
|
||||
@@ -39,7 +45,9 @@
|
||||
];
|
||||
|
||||
let settings = {
|
||||
'Internal kinematic':false,
|
||||
'Internal kinematic':true,
|
||||
'Robot transform controls':false,
|
||||
'Auto orient robot':true,
|
||||
'Trace feet':debug,
|
||||
'Trace points': 30,
|
||||
'Fix camera on robot': true,
|
||||
@@ -69,12 +77,25 @@
|
||||
s: buffer[6],
|
||||
};
|
||||
|
||||
settings.omega = 0
|
||||
settings.phi = data.rx / 4,
|
||||
settings.psi = data.ry / 4,
|
||||
settings.x = data.ly / 2,
|
||||
settings.y = (data.h+128)*0.75,
|
||||
settings.z = data.lx / 2
|
||||
settings.y = (data.h+128)*0.75
|
||||
|
||||
switch (get(mode)) {
|
||||
case ModesEnum.Stand:
|
||||
settings.omega = 0
|
||||
settings.phi = data.rx / 4
|
||||
settings.psi = data.ry / 4
|
||||
settings.x = data.ly / 2
|
||||
settings.z = data.lx / 2
|
||||
break;
|
||||
|
||||
case ModesEnum.Walk:
|
||||
// target_position.yaw += data.lx / 100
|
||||
// const angle = radToDeg(Math.atan2(data.rx, data.ry)) - 90 + $mpu.heading + target_position.yaw;
|
||||
// const distance = Math.sqrt(data.rx**2 + data.ry**2) / 25
|
||||
// target_position.x = distance * Math.cos(degToRad(angle))
|
||||
// target_position.z = distance * Math.sin(degToRad(angle))
|
||||
break;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -96,11 +117,13 @@
|
||||
|
||||
const general = gui_panel.addFolder('General');
|
||||
general.add(settings, 'Internal kinematic')
|
||||
general.add(settings, 'Robot transform controls')
|
||||
general.add(settings, 'Auto orient robot')
|
||||
|
||||
const kinematic = gui_panel.addFolder('Kinematics');
|
||||
kinematic.add(settings, 'omega', -20, 20).onChange(updateKinematicPosition)
|
||||
kinematic.add(settings, 'phi', -30, 30).onChange(updateKinematicPosition)
|
||||
kinematic.add(settings, 'psi', -20, 15).onChange(updateKinematicPosition)
|
||||
kinematic.add(settings, 'omega', -20, 20).onChange(updateKinematicPosition).listen();
|
||||
kinematic.add(settings, 'phi', -30, 30).onChange(updateKinematicPosition).listen();
|
||||
kinematic.add(settings, 'psi', -20, 15).onChange(updateKinematicPosition).listen();
|
||||
kinematic.add(settings, 'x', -90, 90).onChange(updateKinematicPosition)
|
||||
kinematic.add(settings, 'y', 0, 200).onChange(updateKinematicPosition)
|
||||
kinematic.add(settings, 'z', -130, 130).onChange(updateKinematicPosition)
|
||||
@@ -146,6 +169,7 @@
|
||||
.addAmbientLight({ color: 0xffffff, intensity: 0.6 })
|
||||
.addFogExp2(0xcccccc, 0.015)
|
||||
.addModel($model)
|
||||
.addTransformControls(sceneManager.model)
|
||||
.fillParent()
|
||||
.addRenderCb(render)
|
||||
.startRenderLoop();
|
||||
@@ -165,6 +189,11 @@
|
||||
trace_lines.push(geometry);
|
||||
sceneManager.scene.add(line);
|
||||
}
|
||||
|
||||
const geometry = new SphereGeometry(0.1, 32, 16 );
|
||||
const material = new MeshBasicMaterial( { color: 0xffff00 } );
|
||||
target = new Mesh(geometry, material);
|
||||
sceneManager.scene.add(target);
|
||||
};
|
||||
|
||||
const renderTraceLines = (foot_positions: Vector3[]) => {
|
||||
@@ -183,19 +212,60 @@
|
||||
}
|
||||
|
||||
const calculate_kinematics = () => {
|
||||
const position:position_t = {
|
||||
if (sceneManager.isDragging || !settings['Internal kinematic']) return
|
||||
const position:body_state_t = {
|
||||
omega: settings.omega,
|
||||
phi: settings.phi,
|
||||
psi: settings.psi,
|
||||
xm: settings.x,
|
||||
ym: settings.y,
|
||||
zm: settings.z
|
||||
zm: settings.z,
|
||||
feet: Lp
|
||||
}
|
||||
|
||||
let new_angles = kinematic.calcIK(Lp, position).map((x, i) => radToDeg(x * dir[i]));
|
||||
let new_angles = kinematic.calcIK(position).map((x, i) => radToDeg(x * dir[i]));
|
||||
modelTargetAngles = new_angles;
|
||||
}
|
||||
|
||||
const orient_robot = (robot: URDFRobot, toes:Vector3[]) => {
|
||||
if (settings['Robot transform controls'] || !settings['Auto orient robot']) return
|
||||
robot.position.y = robot.position.y - Math.min(...toes.map(toe => toe.y));
|
||||
robot.position.z = lerp(robot.position.z, -settings.x / 100, 0.1);
|
||||
|
||||
robot.rotation.z = lerp(robot.rotation.z, degToRad(settings.phi + $mpu.heading + 90), 0.1);
|
||||
robot.rotation.y = lerp(robot.rotation.y, degToRad(settings.omega - settings.z / 2.5), 0.1);
|
||||
robot.rotation.x = lerp(robot.rotation.x, degToRad(settings.psi - 90), 0.1);
|
||||
}
|
||||
|
||||
const update_camera = (robot:URDFRobot) => {
|
||||
if (!settings['Fix camera on robot']) return
|
||||
sceneManager.orbit.target = robot.position.clone()
|
||||
}
|
||||
|
||||
const update_gate = () => {
|
||||
if (get(mode) != ModesEnum.Walk) return
|
||||
const body_state = {
|
||||
omega: settings.omega,
|
||||
phi: settings.phi,
|
||||
psi: settings.psi,
|
||||
xm: settings.x,
|
||||
ym: settings.y,
|
||||
zm: settings.z,
|
||||
feet: Lp
|
||||
}
|
||||
gaitPlanner.step(body_state, 0.1)
|
||||
|
||||
}
|
||||
|
||||
const update_robot_position = (robot:URDFRobot) => {
|
||||
if (!settings['Robot transform controls']) return
|
||||
settings.omega = radToDeg(robot.rotation.y)
|
||||
settings.phi = radToDeg(robot.rotation.z) + $mpu.heading -90
|
||||
settings.psi = radToDeg(robot.rotation.x) + 90
|
||||
settings.x = robot.position.z * 100
|
||||
settings.z = -robot.position.x * 100
|
||||
}
|
||||
|
||||
const render = () => {
|
||||
const robot = sceneManager.model;
|
||||
if (!robot) return;
|
||||
@@ -203,28 +273,29 @@
|
||||
const toes = toeWorldPositions(robot)
|
||||
|
||||
renderTraceLines(toes)
|
||||
|
||||
if (settings['Fix camera on robot']) {
|
||||
sceneManager.controls.target = robot.position.clone()
|
||||
}
|
||||
|
||||
if (settings['Internal kinematic']) calculate_kinematics()
|
||||
|
||||
robot.position.y = robot.position.y - Math.min(...toes.map(toe => toe.y));
|
||||
robot.position.z = lerp(robot.position.z, -settings.x / 100, 0.1);
|
||||
|
||||
robot.rotation.z = lerp(robot.rotation.z, degToRad(settings.phi + $mpu.heading + 90), 0.1);
|
||||
robot.rotation.y = lerp(robot.rotation.y, degToRad(settings.omega - settings.z / 2.5), 0.1);
|
||||
robot.rotation.x = lerp(robot.rotation.x, degToRad(settings.psi - 90), 0.1);
|
||||
|
||||
update_camera(robot)
|
||||
update_gate()
|
||||
calculate_kinematics()
|
||||
update_robot_position(robot)
|
||||
|
||||
sceneManager.transformControl.showX = settings['Robot transform controls']
|
||||
sceneManager.transformControl.showY = settings['Robot transform controls']
|
||||
sceneManager.transformControl.showZ = settings['Robot transform controls']
|
||||
|
||||
for (let i = 0; i < $jointNames.length; i++) {
|
||||
currentModelAngles[i] = lerp(
|
||||
(robot.joints[$jointNames[i]].angle as number) * (180 / Math.PI),
|
||||
currentModelAngles[i] = lerp(
|
||||
(robot.joints[$jointNames[i]].angle as number) * (180 / Math.PI),
|
||||
modelTargetAngles[i],
|
||||
0.1
|
||||
);
|
||||
robot.joints[$jointNames[i]].setJointValue(degToRad(currentModelAngles[i]));
|
||||
}
|
||||
);
|
||||
robot.joints[$jointNames[i]].setJointValue(degToRad(currentModelAngles[i]));
|
||||
}
|
||||
|
||||
orient_robot(robot, toes)
|
||||
|
||||
target.position.x = lerp(target.position.x, target_position.x, 0.5)
|
||||
// target.position.y = lerp(target.position.y, robot.position.y, 0.5)
|
||||
target.position.z = lerp(target.position.z, target_position.z, 0.5)
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user