Kinesim/js/Robot.js

299 lines
6.7 KiB
JavaScript
Raw Normal View History

2024-10-03 06:42:49 +05:30
define((require, exports, module) => {
const storeManager = require('State')
const Kinematic = require('Kinematic')
localState = {
jointOutOfBound: [false, false, false, false, false, false],
}
const maxAngleVelocity = 90.0 / (180.0 * Math.PI) / 1000.0
const geo = [
[2.5 + 2.3, 0, 7.3],
[0, 0, 13.0],
[1, 0, 2],
[12.6, 0, 0],
[3.6, 0, 0],
[0, 0, 0],
]
const defaultRobotState = {
target: {
position: {
x: 10,
y: 10,
z: 10,
},
rotation: {
x: Math.PI,
y: 0,
z: 0,
},
},
angles: {
A0: 0,
A1: 0,
A2: 0,
A3: 0,
A4: 0,
A5: 0,
},
jointOutOfBound: [false, false, false, false, false, false],
maxAngleVelocities: {
J0: maxAngleVelocity,
J1: maxAngleVelocity,
J2: maxAngleVelocity,
J3: maxAngleVelocity,
J4: maxAngleVelocity,
J5: maxAngleVelocity,
},
jointLimits: {
J0: [-190 / 180 * Math.PI, 190 / 180 * Math.PI],
J1: [-90 / 180 * Math.PI, 90 / 180 * Math.PI],
J2: [-135 / 180 * Math.PI, 45 / 180 * Math.PI],
J3: [-90 / 180 * Math.PI, 75 / 180 * Math.PI],
J4: [-139 / 180 * Math.PI, 90 / 180 * Math.PI],
J5: [-188 / 180 * Math.PI, 181 / 180 * Math.PI],
},
configuration: [false, false, false],
geometry: {
V0: {
x: geo[0][0],
y: geo[0][1],
z: geo[0][2],
},
V1: {
x: geo[1][0],
y: geo[1][1],
z: geo[1][2],
},
V2: {
x: geo[2][0],
y: geo[2][1],
z: geo[2][2],
},
V3: {
x: geo[3][0],
y: geo[3][1],
z: geo[3][2],
},
V4: {
x: geo[4][0],
y: geo[4][1],
z: geo[4][2],
},
},
}
const robotStore = storeManager.createStore('Robot', defaultRobotState)
let IK
function updateIK(geometry) {
const geo = Object.values(geometry).map((val, i, array) => [val.x, val.y, val.z])
// todo not optimal, since IK is a sideeffect
IK = new Kinematic(geo)
}
robotStore.listen([state => state.geometry], (geometry) => {
updateIK(geometry)
})
const calculateAngles = (jointLimits, position, rotation, configuration) => {
const angles = []
IK.calculateAngles(
position.x,
position.y,
position.z,
rotation.x,
rotation.y,
rotation.z,
angles,
configuration
)
outOfBounds = [false, false, false, false, false, false]
let i = 0
for (const index in jointLimits) {
if (angles[i] < jointLimits[index][0] || angles[i] > jointLimits[index][1]) {
outOfBounds[i] = true
}
i++
}
return {
angles,
outOfBounds,
}
}
/* --- Reducer --- */
robotStore.action('ROBOT_CHANGE_TARGET', (state, data) => {
const {
angles,
outOfBounds,
} = calculateAngles(state.jointLimits, data.position, data.rotation, state.configuration)
return Object.assign({}, state, {
target: {
position: Object.assign({}, data.position),
rotation: Object.assign({}, data.rotation),
},
}, {
angles: {
A0: angles[0],
A1: angles[1],
A2: angles[2],
A3: angles[3],
A4: angles[4],
A5: angles[5],
},
}, {
jointOutOfBound: [...outOfBounds],
})
})
robotStore.action('ROBOT_CHANGE_ANGLES', (state, angles) => {
const TCPpose = []
IK.calculateTCP(
angles.A0,
angles.A1,
angles.A2,
angles.A3,
angles.A4,
angles.A5,
TCPpose,
)
// IK.calculateAngles(TCPpose[0], TCPpose[1], TCPpose[2], TCPpose[3], TCPpose[4], TCPpose[5], angles)
return Object.assign({}, state, {
target: {
position: {
x: TCPpose[0],
y: TCPpose[1],
z: TCPpose[2],
},
rotation: {
x: TCPpose[3],
y: TCPpose[4],
z: TCPpose[5],
},
},
}, {
angles: {
A0: angles.A0,
A1: angles.A1,
A2: angles.A2,
A3: angles.A3,
A4: angles.A4,
A5: angles.A5,
},
})
// return Object.assign({}, state, {
// target: {
// position: {
// x: TCPpose[0],
// y: TCPpose[1],
// z: TCPpose[2],
// },
// rotation: {
// x: TCPpose[3],
// y: TCPpose[4],
// z: TCPpose[5],
// },
// },
// }, {
// angles: {
// A0: angles[0],
// A1: angles[1],
// A2: angles[2],
// A3: angles[3],
// A4: angles[4],
// A5: angles[5],
// },
// })
// { todo
// jointOutOfBound: [...result],
// }
})
robotStore.action('ROBOT_CHANGE_GEOMETRY', (state, data) => {
const geo = Object.assign({}, state.geometry, data)
updateIK(geo)
const {
angles,
outOfBounds,
} = calculateAngles(state.jointLimits, state.target.position, state.target.rotation, state.configuration)
return Object.assign({}, state, {
angles: {
A0: angles[0],
A1: angles[1],
A2: angles[2],
A3: angles[3],
A4: angles[4],
A5: angles[5],
},
}, {
jointOutOfBound: [...outOfBounds],
}, {
geometry: {
V0: {
x: geo.V0.x,
y: geo.V0.y,
z: geo.V0.z,
},
V1: {
x: geo.V1.x,
y: geo.V1.y,
z: geo.V1.z,
},
V2: {
x: geo.V2.x,
y: geo.V2.y,
z: geo.V2.z,
},
V3: {
x: geo.V3.x,
y: geo.V3.y,
z: geo.V3.z,
},
V4: {
x: geo.V4.x,
y: geo.V4.y,
z: geo.V4.z,
},
},
})
})
robotStore.action('ROBOT_CHANGE_JOINT_LIMITS', (state, data) => {
const {
outOfBounds,
} = calculateAngles(state.jointLimits, state.target.position, state.target.rotation, state.configuration)
return { ...state,
jointOutOfBound: [...outOfBounds],
jointLimits: { ...state.jointLimits,
...data,
},
}
})
robotStore.action('ROBOT_CHANGE_CONFIGURATION', (state, data) => {
const {
angles,
outOfBounds,
} = calculateAngles(state.jointLimits, state.target.position, state.target.rotation, data)
return Object.assign({}, state, {
angles: {
A0: angles[0],
A1: angles[1],
A2: angles[2],
A3: angles[3],
A4: angles[4],
A5: angles[5],
},
configuration: [...data],
jointOutOfBound: [...outOfBounds],
})
})
module.exports = robotStore
})
// todo -> get rid of scene injection using require scene -> threerobot handles 3d view