如何模拟一组对象的直线运动

rdrgkggo  于 2022-10-02  发布在  Java
关注(0)|答案(1)|浏览(128)

bounty 4天后到期。这个问题的答案有资格获得+50的声誉奖励。Bilal想要引起更多的关注这个问题:我需要一种方法来设置Group()上下运动的动画,并将对象从场景中分离出来。

我的目标是制作一个直线抓握运动(拾取/放置)的动画,这里是一个codesandbox来重现我的问题:

1.创建夹爪后,它开始向下移动,直到到达乐高积木,然后停止。

const grip_pos = new Vector3(
    pick_pos.x,
    pick_pos.y,
    pick_pos.z + 5
);
createGripper(grip_pos, this.scene);
console.log(this.scene.getObjectByName("gripper", true));
const gripper = this.scene.getObjectByName("gripper", true);
// Down
while (gripper.position.y > (pick_pos.z / 0.48)) {
    gripper.position.y -= 0.1;
};

1.夹持器连接到乐高上,它拿起乐高,并移动到位置上方。

gripper.add(lego);

    // if Down then Up
    if (!gripper.position.y > pick_pos.z / 0.48) {
      while (gripper.position.y < grip_pos) {
        gripper.position.y += step;
      }

      if (pick_rot) {
        gripper.rotateY(Math.PI / 2);
      }
    }

    // Move to Place Position
    while (gripper.position.x > place_pos.y / 0.8 + 9.2) {
      gripper.position.x -= step;
    }
    while (gripper.position.x < place_pos.y / 0.8 + 9.2) {
      gripper.position.x += step;
    }

    while (gripper.position.z > place_pos.x / 0.8 + 2.8) {
      gripper.position.z -= step;
    }
    while (gripper.position.z < place_pos.x / 0.8 + 2.8) {
      gripper.position.z += step;
    }

1.夹持器向下移动到放置位置,它到达放置位置,然后它脱离乐高,向上移动,然后消失。

// Place Down
if (
  gripper.position.x === place_pos.y &&
  gripper.position.z === place_pos.x
) {
  while (gripper.position.y > pick_pos.z / 0.48) {
    gripper.position.y -= step;
  }
}
if (place_rot) {
  gripper.rotateY(Math.PI / 2);
}

this.scene.add(lego);
this.scene.remove(gripper);
this.renderer.render(this.scene, this.camera);
cancelAnimationFrame(id);

为了做到这一点,我有created my gripper,并尝试按照事先解释的那样移动它。但我看不到任何动作,而且我的浏览器卡住了,没有显示任何错误!你能指导我怎样才能实现那个直线运动吗?提前谢谢你。

请注意,由于我使用了两个坐标框架xyzzyx,并进行了平移和缩放,因此在位置上进行了转换。

ergxz8rk

ergxz8rk1#

解决方案是避免将参数传递给动画函数,因为它将为每个requestAnimationFrame调用,

export class PickPlace {
    /***********************************************************
     * 
     * @param {*} renderer 
     * @param {*} scene 
     * @param {*} camera 
     * @param {*} lego 
     * @param {*} place_position 
     * @param {*} place_rotation 
   ***********************************************************/
    constructor(renderer, scene, camera, lego,
        place_position, place_rotation = false) {
        //
        this.renderer = renderer;
        this.scene = scene;
        this.camera = camera;
        //
        this.lego = this.scene.getObjectByName(lego);
        //
        this.pick_position = new Vector3(
            Number((Math.round( ((this.lego.position.z + 2.8) / 0.8) * 100) / 100).toFixed(1)),
            Number((Math.round( ((this.lego.position.x + 9.2) / 0.8) * 100) / 100).toFixed(1)),
            Number((Math.round( (this.lego.position.y/0.48 - 0.01)   * 100) / 100).toFixed(1))
        );
        this.place_position = place_position
        this.place_rotation = place_rotation;
        this.step = 0.05;
        this.motion_down = true;
        this.planar_motion = false;
        this.x_lock = 0;
        this.z_lock = 0;
        this.pick();
    };

    pick = () => {
        /* grip_pos in units, 
        * createGripper() function does the conversion unit => mm
        */
        this.grip_pos = new Vector3(
            this.pick_position.x,
            this.pick_position.y,
            this.pick_position.z + 5);

        /* Create the gripper,
        * (scene.add(gripper)) is done internally.
        */
        createGripper(this.scene, this.grip_pos);
        this.gripper = this.scene.getObjectByName("gripper");

        if (!this.lego.userData.rotation) {
            this.gripper.rotateY(-Math.PI / 2);
        };
    };

    place = () => {
        if (this.place_rotation) {
            this.gripper.rotateY(-Math.PI / 2);
            if (this.lego.userData.size == 6 && this.lego.userData.rotation) {
                this.lego.translateX(-1.6);
            }
        };
    };

    animatePickPlace = () => {
        const tolerance = 1.1 * this.step;
        let frame_id = requestAnimationFrame(this.animatePickPlace);

        if ((this.gripper.position.y > this.lego.position.y + 0.04)
            && this.motion_down && !this.planar_motion) {

            this.gripper.position.y -= this.step;
        }
        else {
            if (this.motion_down) {
                this.gripper.add(this.lego);
                this.lego.rotateY(Math.PI / 2);
                // 2x2
                if (this.lego.userData.size === 2) {
                    if (this.lego.userData.rotation) {
                        this.lego.position.x += 9.2 - this.pick_position.y * 0.8;
                        this.lego.position.z += 2.8 - this.pick_position.x * 0.8;
                        this.lego.position.y -= this.pick_position.z * 0.48;
                    }
                    else {
                        this.lego.position.z += 2.8 - this.pick_position.y * 0.8;
                        this.lego.position.x += 9.2 - this.pick_position.x * 0.8;
                        this.lego.position.y -= this.pick_position.z * 0.48;
                    }
                }
                // 2x4
                else if (this.lego.userData.size === 4) {
                    if (this.lego.userData.rotation) {
                        this.lego.rotateY(Math.PI / 2);
                        this.lego.position.x += 9.2 - this.pick_position.y * 0.8;
                        this.lego.position.z += 2.0 - this.pick_position.x * 0.8;
                        this.lego.position.y -= this.pick_position.z * 0.48;
                    }
                    else {
                        this.lego.position.x += 9.2 - this.pick_position.y * 0.8;
                        this.lego.position.z += 2.8 - this.pick_position.x * 0.8;
                        this.lego.position.y -= this.pick_position.z * 0.48;
                    }
                }
                // 2x6
                else {
                    if (this.lego.userData.rotation) {
                        this.lego.rotateY(Math.PI / 2);
                        this.lego.position.x += 9.2 - this.pick_position.y * 0.8;
                        this.lego.position.z += 1.2 - this.pick_position.x * 0.8;
                        this.lego.position.y -= this.pick_position.z * 0.48;
                    }
                    else {
                        this.lego.position.z += 2.8 - this.pick_position.y * 0.8;
                        this.lego.position.x += 9.2 - this.pick_position.x * 0.8;
                        this.lego.position.y -= this.pick_position.z * 0.48;
                    }
                }
                this.motion_down = false;
            }
            if (this.gripper.position.y < this.grip_pos.z
                && !this.planar_motion) {
                this.gripper.position.y += this.step;
                if (this.gripper.position.y >= this.grip_pos.z) {
                    this.planar_motion = true;
                };
            }
            //
            if ((this.gripper.position.y >= this.grip_pos.z)
                && !this.motion_down && this.planar_motion) {

                let x_diff = this.gripper.position.x - (this.place_position.y * 0.8 - 9.2);
                let z_diff = this.gripper.position.z - (this.place_position.x * 0.8 - 2.8);

                if ((x_diff > tolerance) && this.x_lock !== 2) {
                    this.x_lock = 1;
                    this.gripper.position.x -= this.step;
                }
                else if ((x_diff < tolerance) && this.x_lock !== 1) {
                    this.x_lock = 2;
                    this.gripper.position.x += this.step;
                }
                else if ((z_diff > tolerance) && this.z_lock !== 2) {
                    this.z_lock = 1;
                    this.gripper.position.z -= this.step;
                }
                else if ((z_diff < tolerance) && this.z_lock !== 1) {
                    this.z_lock = 2;
                    this.gripper.position.z += this.step;
                }
                else {
                    cancelAnimationFrame(frame_id);
                    this.place();
                    this.animatePlace();
                }
            }
        }

        this.renderer.render(this.scene, this.camera);
    };

    animatePlace = () => {
        this.planar_motion = false;
        let frame_id = requestAnimationFrame(this.animatePlace);
        /**TODO: to handle placing rotation */
        if ((this.gripper.position.y > (this.place_position.z * 0.48))
            && !this.motion_down) {

            this.gripper.position.y -= this.step;
        }
        else {
            this.motion_down = true;
            this.scene.add(this.lego);
                /* Position World Unit to mm conversion.*/
                this.lego.position.set(
                    this.place_position.y * 0.8 - 9.2,
                    this.place_position.z * 0.48,
                    this.place_position.x * 0.8 - 2.8
                )
            /**TODO: Move gripper up and make it vanish gradually */
            this.scene.remove(this.gripper);
            cancelAnimationFrame(frame_id);
            /*********************************
             * Place Translation/Orientation *
           *********************************/
            if (this.lego.userData.size == 4) {
                if (this.place_rotation) { 
                    if (this.lego.userData.rotation) {
                        this.lego.rotateY(Math.PI / 2);
                    }
                    else { 
                        this.lego.translateX(-0.8);
                    }
                }
                else { 
                    if (this.lego.userData.rotation) {
                        // Do Nothing
                    }
                    else { 
                        this.lego.rotateY(Math.PI / 2);
                        this.lego.translateX(-0.8);
                    }
                }
            }
            else if (this.lego.userData.size == 6) { 
                if (this.place_rotation) { 
                    if (this.lego.userData.rotation) {
                        this.lego.rotateY(Math.PI / 2);
                    }
                    else { 
                        this.lego.translateX(-1.6);
                    }
                }
                else { 
                    if (this.lego.userData.rotation) {
                        // Do Nothing
                    }
                    else { 
                        this.lego.rotateY(Math.PI / 2);
                        this.lego.translateX(-1.6);
                    }
                }
            }
        }
    };
}

相关问题