Rotational movement of robot arm

Hi, I am trying to make a robot arm simulation. In this I have to create translation and rotational movement. I have written the code for translation and its working fine but I am confused how to start the code of rotational code. Please help me if you know anything regarding the same. I am adding my translation code below.

Code for IK

import { Vector3 } from 'three'

class CCDIK {
    solve(target, robot, joints, {
        maxIterations = 1,
        stopDistance = 0.001,
        apply = false
    } = {}) {
        let movable = [];
        // get the movable joints
        if (joints.length) {
            for (let joint of robot.arm.movable) {
                if (joints.includes(joint.name)) {
                    movable.push(joint);
                }
            }
        } else {
            movable = robot.arm.movable;
        }
        const orignalMovment = {};
        const solution = {};

        let targetPosition = new Vector3();
        let tipPosition = new Vector3();
        let deltaNormal = new Vector3();

        for (const joint of movable) {
            orignalMovment[joint.name] = joint.angle;
        }

        target.getWorldPosition(targetPosition);
    
        for (let iter = 0; iter < maxIterations; iter++) {
x
            for (let i = movable.length - 1; i >= 0; i--) {
                const joint = movable[i];
          
                robot.tcp.object.getWorldPosition(tipPosition);
              
                let tcpDirection = joint.worldToLocal(tipPosition.clone()).normalize(); // Vector from the joint to the current TCP.
                let targetDirection = joint.worldToLocal(targetPosition.clone()).normalize(); // Vector from the joint to the target position.
                // Project direction vectors onto the joint's rotation plane
                tcpDirection = tcpDirection.projectOnPlane(joint.axis);
                targetDirection = targetDirection.projectOnPlane(joint.axis);
                // deltaNormal is the cross product of the direction vectors, 
                // providing a normal vector to the plane formed by these vectors
                deltaNormal.crossVectors(tcpDirection, targetDirection).normalize();
                // Depending on which direction we have to turn, the rotation axes will be parallel or anti-parallel
                let alignment = deltaNormal.dot(joint.axis);
                let delta = Math.sign(alignment) * tcpDirection.angleTo(targetDirection);
                let angle = joint.angle + delta;
      
                const limit = joint.limit;
  
                if (limit) {
                    if ('lower' in limit && angle < limit['lower']) {
                        angle = Math.max(limit['lower'], angle);
                    }
                    if ('upper' in limit && angle > limit['upper']) {
                        angle = Math.min(limit['upper'], angle);
                    }
                }

                joint.setJointValue(angle);
                solution[joint.name] = joint.angle;
            }

            robot.tcp.object.getWorldPosition(tipPosition);
            if (targetPosition.distanceTo(tipPosition) < stopDistance) {
                console.log('IK solution found after ' + iter + ' iterations');
                break;
            }
        }

        if (!apply) {
            // Reset all movable joints to their original angles 
            for (const joint of movable) {
                joint.setJointValue(orignalMovment[joint.name]);
            }
        }
        return solution;
    }
};

export default CCDIK;

Code for robot controller

import * as UIL from "uil";
import { default as IKSolver } from "../ik/ccdik";
import * as THREE from 'three'

var gui = null;
var ik = null;

export function initRoboController(robot, renderCall, scene, tcptarget) {
    gui = new UIL.Gui(
        { css: 'position: absolute; right: 0px;top:150px;  width: 350px; z-index: 98;overflow:auto;background: rgba(0,0,0,0.8);' }
    );
    gui.content.id = 'robo-controller';
    ik = new IKSolver(scene, robot);

    gui.add('title', { name: 'Controller', prefix: 'v1.0' });
    // translation controls
    gui.add('slide', { name: 'Move X', min: -1, max: 1, value: 0 }).onChange((v) => {
        moveTCP(robot, v, null, null);
    });
    gui.add('slide', { name: 'Move Y', min: -1, max: 1, value: 0 }).onChange((v) => {
        moveTCP(robot, null, v, null);
    });
    gui.add('slide', { name: 'Move Z', min: -1, max: 1, value: 0 }).onChange((v) => {
        moveTCP(robot, null, null, v);
    });
    // rotational control
    gui.add('slide', { name: 'Roll(X)', min: -180, max: 180, value: 0 }).onChange((v) => {
        rotateTCP(robot, v, null, null);
    });
    gui.add('slide', { name: 'Pitch(Y)', min: -180, max: 180, value: 0 }).onChange((v) => {
        rotateTCP(robot, null, v, null);
    });
    gui.add('slide', { name: 'Yaw(Z)', min: -180, max: 180, value: 0 }).onChange((v) => {
        rotateTCP(robot, null, null, v);
    });

    function moveTCP(robot, x, y, z) {
        let minYValue = -3.14159265
        robot.tcp.object.getWorldPosition(tcptarget.position);
        // Update TCP target position
        if (x !== null) tcptarget.position.x = x * 10;
        if (y !== null) tcptarget.position.y = Math.max(y * 10, minYValue);;
        if (z !== null) tcptarget.position.z = z * 10;

        // Solve inverse kinematics to find new joint angles
        if (typeof ik.solve === 'function') {
            ik.solve(
                tcptarget,
                robot,
                robot.ikEnabled,
                {
                    // we don't have to be all that precise here
                    maxIterations: 10,
                    stopDistance: 0.01,
                    apply: true
                }
            );
        } else {
            console.warn("IK solver function 'solveIK' is missing!");
        }
        renderCall();
    }

    function rotateTCP(robot, roll, pitch, yaw) {
        let euler = new THREE.Euler(
            roll !== null ? THREE.MathUtils.degToRad(roll) : tcptarget.rotation.x,
            pitch !== null ? THREE.MathUtils.degToRad(pitch) : tcptarget.rotation.y,
            yaw !== null ? THREE.MathUtils.degToRad(yaw) : tcptarget.rotation.z,
            "XYZ"
        );

        tcptarget.quaternion.setFromEuler(euler); // Apply rotation to TCP

        console.log("New TCP Rotation: ", euler);

        // Solve IK for rotation
        if (typeof ik.solve === 'function') {
            ik.solve(
                tcptarget,
                robot,
                robot.ikEnabled,
                {
                    maxIterations: 10,
                    stopDistance: 0.01,
                    apply: true
                }
            );
        } else {
            console.warn("IK solver function 'solveIK' is missing!");
        }
        renderCall(); // Update the scene
    }

    gui.isOpen = true;
    gui.setHeight();
    gui.bottomText = ['Move', 'Close'];
    gui.bottom.textContent = 'Move';
}

Do you know that?
Robot Simulation / Rotation issues
Robotics Simulation - Six DoF

1 Like

Oh, yeah got it. Thank you for the reply. I will surely try this. :heart: