/// <summary>
    /// Initial setup, called at startup.
    /// </summary>
    /// <remarks>
    /// In future versions of ML-agents (> 0.14), InitializeAgent should be replaced by Initialize.
    /// </remarks>
    public override void InitializeAgent()
    {
        base.InitializeAgent();

        // Initialize joint controllers
        leftShoulder = new JointController("Left shoulder", leftShoulderJoint, new Vector3(-999, -999, -999), new Vector3(999, 999, 999)); //new Vector3(-999, -999, -25), new Vector3(999, 999, 25));
        leftUpperArm = new JointController("Left upper arm", leftUpperArmJoint, new Vector3(-999, -999, -999), new Vector3(999, 999, 999));
        leftElbow    = new JointController("Left elbow", leftElbowJoint, new Vector3(-999, -999, -999), new Vector3(999, 999, 999));       //new Vector3(-25, -999, -999), new Vector3(25, 999, 999));
        head         = new JointController("Head", headJoint, new Vector3(-999, -999, -999), new Vector3(999, 999, 999));

        // Retrieve the rubberArm and visuo-tactile stimulation objects from the environment
        rubberArmController = rubberArm.GetComponent <RubberArmController>();
        ballScript          = ballHandler.GetComponent <BallHandler>();
        vibScript           = vibHandler.GetComponent <VibHandler>();

        // Set the head rotation (and subsequently the camera perspective)
        head.SetRelativeJointAngles(new Vector3(15f, -20f));
    }
    /// <summary>
    /// Perform actions based on a vector of numbers
    /// </summary>
    /// <remarks>
    /// In future versions of ML-agents (> 0.14), AgentAction should be replaced by OnActionReceived.
    /// </remarks>
    /// <param name="vectorAction">The list of actions to take</param>
    public override void AgentAction(float[] vectorAction)
    {
        // The first action vector value specifies the type of control from the Python environment
        switch (vectorAction[0])
        {
        // Normal action (joint velocity control)
        default:
            leftShoulder.MoveJoint(0f, 0f, vectorAction[1] * turnSpeed * Time.fixedDeltaTime);
            leftElbow.MoveJoint(vectorAction[2] * turnSpeed * Time.fixedDeltaTime, 0f, 0f);
            break;

        // Joint angle rotation (set joint angle directly)
        case 1f:
            leftShoulder.SetRelativeJointAngles(new Vector3(0f, 0f, vectorAction[1]));
            leftElbow.SetRelativeJointAngles(new Vector3(vectorAction[2], 0f, 0f));
            break;

        // Rubber arm joint (set rubber arm joint angle)
        case 2f:
            rubberArmController.setRelativeLeftShoulderZ(vectorAction[1]);
            rubberArmController.setRelativeLeftElbowX(vectorAction[2]);
            break;
        }
    }
 /// <summary>
 /// Sets joint angles such that the rubber arm is in the 'left' position (hand is 15cm left of center, 45cm left of body midline).
 /// </summary>
 public void setLeftCondition()
 {
     leftShoulder.SetRelativeJointAngles(new Vector3(0, 0, -10.924f));
     leftElbow.SetRelativeJointAngles(new Vector3(-16.93f, 0, 0));
 }