function [] = setRobotState(varargin)

    % SETROBOTSTATE sets the system state. The system state is composed of:
    %
    %                    - joints configuration and velocity plus gravity vector
    %                      for fixed-base systems;
    %                    - base pose and velocity, joints configuration and
    %                      velocity plus gravity vector for floating-base systems.
    %
    %                    The gravity vector expresses the gravity acceleration
    %                    in the inertial frame.
    %
    % This matlab function wraps a functionality of the iDyntree library.
    % For further info see also: https://github.com/robotology/idyntree
    %
    % FORMAT: Floating base system:
    %
    %         [] = setRobotState(KinDynModel,basePose,jointPos,baseVel,jointVel,gravAcc)
    %
    %         Fixed base system:
    %
    %         [] = setRobotState(KinDynModel,jointPos,jointVel,gravAcc)
    %
    % INPUTS:  - KinDynModel: a structure containing the loaded model and additional info.
    %          - basePose: [4 x 4] from base frame to world frame transform;
    %          - jointPos: [nDof x 1] vector representing the joints configuration
    %                      in radians;
    %          - baseVel: [6 x 1] vector of base velocities [lin, ang];
    %          - jointVel: [ndof x 1] vector of joints velocities;
    %          - gravAcc: [3 x 1] vector of the gravity acceleration in the
    %                             inertial frame.
    %
    % Author : Gabriele Nava (gabriele.nava@iit.it)
    %
    % SPDX-FileCopyrightText: Fondazione Istituto Italiano di Tecnologia (IIT)
    % SPDX-License-Identifier: BSD-3-Clause

    %% ------------Initialization----------------

    KinDynModel = varargin{1};

    % check the number of inputs
    switch nargin

        case 6

            basePose = varargin{2};
            jointPos = varargin{3};
            baseVel  = varargin{4};
            jointVel = varargin{5};
            gravAcc  = varargin{6};

            % Debug inputs
            if KinDynModel.DEBUG

                disp('[setRobotState]: debugging inputs...')

                % basePose must be a valid transformation matrix
                if size(basePose,1) ~= 4 || size(basePose,2) ~= 4

                    error('[setRobotState]: basePose is not a 4x4 matrix.')
                end

                for ii = 1:4

                    if ii < 4

                        if abs(basePose(4,ii)) > 0.0001

                            error('[setRobotState]: the last line of basePose is not [0,0,0,1].')
                        end
                    else
                        if abs(basePose(4,ii)) > 1.0001 || abs(basePose(4,ii)) < 0.9999

                            error('[setRobotState]: the last line of basePose is not [0,0,0,1].')
                        end
                    end
                end

                % baseRotation = basePose(1:3,1:3) must be a valid rotation matrix
                if det(basePose(1:3,1:3)) < 0.9 || det(basePose(1:3,1:3)) > 1.1

                    error('[setRobotState]: baseRotation is not a valid rotation matrix.')
                end

                IdentityMatr = basePose(1:3,1:3)*basePose(1:3,1:3)';

                for kk = 1:size(IdentityMatr, 1)

                    for jj = 1:size(IdentityMatr, 1)

                        if jj == kk

                            if abs(IdentityMatr(kk,jj)) < 0.9 || abs(IdentityMatr(kk,jj)) > 1.1

                                error('[setRobotState]: baseRotation is not a valid rotation matrix.')
                            end
                        else
                            if abs(IdentityMatr(kk,jj)) > 0.01

                                error('[setRobotState]: baseRotation is not a valid rotation matrix.')
                            end
                        end
                    end
                end

                % debug gravity vector size
                if length(gravAcc) ~= 3

                    error('[setRobotState]: the length of gravAcc vector is not 3.')
                end

                % check base velocity vector size
                if length(baseVel) ~= 6

                    error('[setRobotState]: the length of baseVel is not 6.')
                end

                % check joints position vector size
                if length(jointPos) ~= KinDynModel.NDOF

                    error('[setRobotState]: the length of jointPos is not KinDynModel.NDOF')
                end

                % check joints velocity vector size
                if length(jointVel) ~= KinDynModel.NDOF

                    error('[setRobotState]: the length of jointVel is not KinDynModel.NDOF')
                end

                disp('[setRobotState]: done.')
            end

            % set the element of the rotation matrix and of the base
            % position vector
            for k = 0:2

                KinDynModel.kinematics.baseOrigin_iDyntree.setVal(k,basePose(k+1,4));

                for j = 0:2

                    KinDynModel.kinematics.baseRotation_iDyntree.setVal(k,j,basePose(k+1,j+1));
                end
            end

            % add the rotation matrix and the position to basePose_iDyntree
            KinDynModel.kinematics.basePose_iDyntree.setRotation(KinDynModel.kinematics.baseRotation_iDyntree);
            KinDynModel.kinematics.basePose_iDyntree.setPosition(KinDynModel.kinematics.baseOrigin_iDyntree);

            % set the base velocities
            for k = 0:5

                KinDynModel.kinematics.baseVel_iDyntree.setVal(k,baseVel(k+1));
            end

        case 4

            jointPos = varargin{2};
            jointVel = varargin{3};
            gravAcc  = varargin{4};

            % Debug inputs
            if KinDynModel.DEBUG

                disp('[setRobotState]: debugging inputs...')

                % debug gravity vector
                if length(gravAcc) ~= 3

                    error('[setRobotState]: the length of gravAcc vector is not 3.')
                end

                % check joints position vector size
                if length(jointPos) ~= KinDynModel.NDOF

                    error('[setRobotState]: the length of jointPos is not KinDynModel.NDOF')
                end

                % check joints velocity vector size
                if length(jointVel) ~= KinDynModel.NDOF

                    error('[setRobotState]: the length of jointVel is not KinDynModel.NDOF')
                end

                disp('[setRobotState]: done.')
            end

        otherwise
            error('[setRobotState]: wrong number of inputs.')
    end

    % set joints position and velocity
    for k = 0:length(jointPos)-1

        KinDynModel.kinematics.jointVel_iDyntree.setVal(k,jointVel(k+1));
        KinDynModel.kinematics.jointPos_iDyntree.setVal(k,jointPos(k+1));
    end

    % set the gravity vector
    for k = 0:2

        KinDynModel.kinematics.gravityVec_iDyntree.setVal(k,gravAcc(k+1));
    end

    % set the current robot state
    switch nargin

        case 4

            ack = KinDynModel.kinDynComp.setRobotState(KinDynModel.kinematics.jointPos_iDyntree,KinDynModel.kinematics.jointVel_iDyntree, ...
                KinDynModel.kinematics.gravityVec_iDyntree);

        case 6

            ack = KinDynModel.kinDynComp.setRobotState(KinDynModel.kinematics.basePose_iDyntree,KinDynModel.kinematics.jointPos_iDyntree, ...
                KinDynModel.kinematics.baseVel_iDyntree,KinDynModel.kinematics.jointVel_iDyntree, ...
                KinDynModel.kinematics.gravityVec_iDyntree);
    end

    % check for errors
    if ~ack
        error('[setRobotState]: unable to set the robot state.')
    end
end
