Example #1
0
    def testDynComp(self):
        dynComp = iDynTree.DynamicsComputations()

        ok = dynComp.loadRobotModelFromFile('./model.urdf')

        #dynComp.getFloatingBase()

        # set state
        dofs = dynComp.getNrOfDegreesOfFreedom()
        print "dofs: {}".format(dofs)
        q = iDynTree.VectorDynSize.fromPyList(
            [random.random() for i in range(0, dofs)])
        dq = iDynTree.VectorDynSize.fromPyList(
            [random.random() for i in range(0, dofs)])
        ddq = iDynTree.VectorDynSize.fromPyList(
            [random.random() for i in range(0, dofs)])

        # set gravity
        grav = iDynTree.SpatialAcc.fromPyList([0.0, 0.0, -9.81, 0.0, 0.0, 0.0])
        dynComp.setRobotState(q, dq, ddq, grav)

        torques = iDynTree.VectorDynSize(dofs + 6)
        baseReactionForce = iDynTree.Wrench()

        # compute id with inverse dynamics
        dynComp.inverseDynamics(torques, baseReactionForce)

        # compute id with regressors
        nrOfParams = 10 * dynComp.getNrOfLinks()
        regr = iDynTree.MatrixDynSize(6 + dofs, nrOfParams)
        params = iDynTree.VectorDynSize(nrOfParams)
        dynComp.getDynamicsRegressor(regr)
        dynComp.getModelDynamicsParameters(params)

        np_reg = regr.toNumPy()
        np_params = params.toNumPy()
        generalizedForces = np.dot(np_reg, np_params)

        print 'Result of inverse dynamics:'
        #print 'baseReactionForce: {} \nTorques: {}'.format(baseReactionForce,torques)
        #print 'Generalized Forces: {}'.format(generalizedForces)

        # check consistency
        self.assertTrue(
            np.allclose(np.hstack(
                (baseReactionForce.toNumPy(), torques.toNumPy())),
                        generalizedForces,
                        rtol=1e-04,
                        atol=1e-04))
        print 'Test of DynamicsComputations completed successfully.'
Example #2
0
def main():
    '''
    open a urdf file and add noise to each parameter. Can be used for testing, but noisy params are usually not consistent, so may be of limited use.
    '''
    parser = argparse.ArgumentParser(description='Load measurements and URDF model to get inertial parameters.')
    parser.add_argument('--urdf_input', required=True, type=str, help='the file to load the robot model from')
    parser.add_argument('--urdf_output', required=True, type=str, help='the file to save the noisy robot model to')
    parser.add_argument('--noise', required=False, type=float, help='scale of noise (default 0.01)')
    parser.set_defaults(noise=0.01)
    args = parser.parse_args()

    model = iDynTree.Model()
    iDynTree.modelFromURDF(args.urdf_input, model)
    link_names = []
    for i in range(0, model.getNrOfLinks()):
        link_names.append(model.getLinkName(i))
    n_params = model.getNrOfLinks()*10

    dynComp = iDynTree.DynamicsComputations()
    dynComp.loadRobotModelFromFile(args.urdf_input)
    xStdModel = iDynTree.VectorDynSize(n_params)
    dynComp.getModelDynamicsParameters(xStdModel)
    xStdModel = xStdModel.toNumPy()
    # percentage noise
    #for p in range(0, len(xStdModel)):
    #    xStdModel[p] += np.random.randn()*args.noise*xStdModel[p]
    # additive noise
    xStdModel += np.random.randn(n_params)*args.noise


    helpers = identificationHelpers.IdentificationHelpers(n_params)
    helpers.replaceParamsInURDF(input_urdf=args.urdf_input, output_urdf=args.urdf_output, \
                                new_params=xStdModel, link_names=link_names)
Example #3
0
 def testPyHelpers(self):
     pos = [1.0, 2.0, 3.0]
     p1 = iDynTree.VectorDynSize.fromPyList(pos)
     p2 = iDynTree.VectorDynSize(3)
     p2.setVal(0, pos[0])
     p2.setVal(1, pos[1])
     p2.setVal(2, pos[2])
     self.checkVectorEqual(
         p1, p2,
         "helper does not properly create vector (vectors are not equal)")
    def get_solution(self) -> IKSolution:

        # Lazy import iDynTree
        import iDynTree

        # Initialize buffers
        base_transform = iDynTree.Transform.Identity()
        joint_positions = iDynTree.VectorDynSize(
            self._ik.model().getNrOfJoints())

        # Get the solution
        self._ik.getFullJointsSolution(base_transform, joint_positions)

        # Convert to numpy objects
        joint_positions = joint_positions.toNumPy()
        base_position = base_transform.getPosition().toNumPy()
        base_quaternion = base_transform.getRotation().asQuaternion().toNumPy()

        return IKSolution(base_position=base_position,
                          base_quaternion=base_quaternion,
                          joint_configuration=joint_positions)
Example #5
0
from iDynTree import ModelLoader


URDF_FILE = '/home/username/path/robot.urdf';

dynComp = KinDynComputations();
mdlLoader = ModelLoader();
mdlLoader.loadModelFromFile(URDF_FILE);

dynComp.loadRobotModel(mdlLoader.model());

print "The loaded model has", dynComp.model().getNrOfDOFs(), \
    "internal degrees of freedom and",dynComp.model().getNrOfLinks(),"links."

dofs = dynComp.model().getNrOfDOFs();
s = iDynTree.VectorDynSize(dofs);
ds = iDynTree.VectorDynSize(dofs);
dds = iDynTree.VectorDynSize(dofs);
for dof in range(dofs):
    # For the sake of the example, we fill the joints vector with gibberish data (remember in any case
    # that all quantities are expressed in radians-based units 
    s.setVal(dof, 1.0);
    ds.setVal(dof, 0.4);
    dds.setVal(dof, 0.3);


# The gravity acceleration is a 3d acceleration vector.
gravity = iDynTree.Vector3();
gravity.zero();
gravity.setVal(2, -9.81);
dynComp.setRobotState(s,ds,gravity);
Example #6
0
    def getRandomRegressor(self, n_samples=None):
        """
        Utility function for generating a random regressor for numerical base parameter calculation
        Given n_samples, the Y (n_samples*getNrOfOutputs() X getNrOfParameters() ) regressor is
        obtained by stacking the n_samples generated regressors
        This function returns Y^T Y (getNrOfParameters() X getNrOfParameters() ) (that share the row space with Y)
        (partly ported from iDynTree)
        """

        if self.opt['identifyGravityParamsOnly']:
            regr_filename = self.urdf_file + '.gravity_regressor.npz'
        else:
            regr_filename = self.urdf_file + '.regressor.npz'
        generate_new = False
        fb = self.opt['floatingBase']

        try:
            regr_file = np.load(regr_filename)
            R = regr_file['R']  #regressor matrix
            Q = regr_file['Q']  #QR decomposition
            RQ = regr_file['RQ']
            PQ = regr_file['PQ']
            n = regr_file['n']   #number of samples that were used
            fbase = regr_file['fb']  #floating base flag
            grav = regr_file['grav_only']
            fric = regr_file['fric']
            fric_sym = regr_file['fric_sym']
            if self.opt['verbose']:
                print("loaded random structural regressor from {}".format(regr_filename))
            if n != n_samples or fbase != fb or R.shape[0] != self.num_identified_params or \
                    self.opt['identifyGravityParamsOnly'] != grav or \
                    fric != self.opt['identifyFriction'] or fric_sym != self.opt['identifySymmetricVelFriction']:
                generate_new = True
            #TODO: save and check timestamp of urdf file, if newer regenerate
        except (IOError, KeyError):
            generate_new = True

        if generate_new:
            if not n_samples:
                n_samples = self.num_dofs * 1000

            if self.opt['verbose']:
                print("(re-)generating structural regressor ({} random positions)".format(n_samples))

            R = np.array((self.N_OUT, self.num_model_params))
            regressor = iDynTree.MatrixDynSize(self.N_OUT, self.num_model_params)
            knownTerms = iDynTree.VectorDynSize(self.N_OUT)
            if len(self.limits) > 0:
                jn = self.jointNames
                q_lim_pos = [self.limits[jn[n]]['upper'] for n in range(self.num_dofs)]
                q_lim_neg = [self.limits[jn[n]]['lower'] for n in range(self.num_dofs)]
                dq_lim = [self.limits[jn[n]]['velocity'] for n in range(self.num_dofs)]
                q_range = (np.array(q_lim_pos) - np.array(q_lim_neg)).tolist()
            for i in self.progress(range(0, n_samples)):
                # set random system state
                if len(self.limits) > 0:
                    rnd = np.random.rand(self.num_dofs) #0..1
                    q = iDynTree.VectorDynSize.fromList((q_lim_neg+q_range*rnd))
                    if self.opt['identifyGravityParamsOnly']:
                        #set vel and acc to zero for static case
                        vel = np.zeros(self.num_dofs)
                        acc = np.zeros(self.num_dofs)
                    else:
                        vel = ((np.random.rand(self.num_dofs)-0.5)*2*dq_lim)
                        acc = ((np.random.rand(self.num_dofs)-0.5)*2*np.pi)
                    dq = iDynTree.VectorDynSize.fromList(vel.tolist())
                    ddq = iDynTree.VectorDynSize.fromList(acc.tolist())
                else:
                    q = iDynTree.VectorDynSize.fromList(((np.random.ranf(self.num_dofs)*2-1)*np.pi).tolist())
                    dq = iDynTree.VectorDynSize.fromList(((np.random.ranf(self.num_dofs)*2-1)*np.pi).tolist())
                    ddq = iDynTree.VectorDynSize.fromList(((np.random.ranf(self.num_dofs)*2-1)*np.pi).tolist())

                # TODO: make work with fixed dofs (set vel and acc to zero, look at iDynTree method)

                if self.opt['floatingBase']:
                    base_vel = np.pi*np.random.rand(6)
                    base_acc = np.pi*np.random.rand(6)
                    if self.opt['identifyGravityParamsOnly']:
                        #set vel and acc to zero for static case (reduces resulting amount of base dependencies)
                        base_vel[:] = 0.0
                        base_acc[:] = 0.0
                    rpy = np.random.ranf(3)*0.1
                    rot = iDynTree.Rotation.RPY(rpy[0], rpy[1], rpy[2])
                    pos = iDynTree.Position.Zero()
                    world_T_base = iDynTree.Transform(rot, pos).inverse()

                    '''
                    # rotate base vel and acc to world frame
                    to_world = world_T_base.getRotation().toNumPy()
                    base_vel[0:3] = to_world.dot(base_vel[0:3])
                    base_vel[3:] = to_world.dot(base_vel[3:])
                    base_acc[0:3] = to_world.dot(base_acc[0:3])
                    base_acc[3:] = to_world.dot(base_acc[3:])
                    '''

                    base_velocity = iDynTree.Twist.fromList(base_vel)
                    base_acceleration = iDynTree.Twist.fromList(base_acc)

                    self.generator.setRobotState(q,dq,ddq, world_T_base, base_velocity, base_acceleration, self.gravity_twist)
                else:
                    self.generator.setRobotState(q,dq,ddq, self.gravity_twist)

                # get regressor
                if not self.generator.computeRegressor(regressor, knownTerms):
                    print("Error during numeric computation of regressor")

                A = regressor.toNumPy()

                #the base forces are expressed in the base frame for the regressor, so rotate them
                if self.opt['floatingBase']:
                    to_world = np.fromstring(world_T_base.getRotation().toString(), sep=' ').reshape((3,3))
                    A[0:3, :] = to_world.dot(A[0:3, :])
                    A[3:6, :] = to_world.dot(A[3:6, :])

                if self.opt['identifyGravityParamsOnly']:
                    #delete inertia param columns
                    A = np.delete(A, self.inertia_params, 1)

                if self.opt['identifyFriction']:
                    # append unitary matrix to regressor for offsets/constant friction
                    sign = 1 #np.sign(dq.toNumPy())
                    static_diag = np.identity(self.num_dofs)*sign
                    offset_regressor = np.vstack( (np.zeros((fb*6, self.num_dofs)), static_diag))
                    A = np.concatenate((A, offset_regressor), axis=1)

                    if not self.opt['identifyGravityParamsOnly']:
                        if self.opt['identifySymmetricVelFriction']:
                            # just use velocity directly
                            vel_diag = np.identity(self.num_dofs)*dq.toNumPy()
                            friction_regressor = np.vstack( (np.zeros((fb*6, self.num_dofs)), vel_diag))   # add base dynamics rows
                        else:
                            # append positive/negative velocity matrix for velocity dependent asymmetrical friction
                            dq_p = dq.toNumPy().copy()
                            dq_p[dq_p < 0] = 0 #set to zero where v < 0
                            dq_m = dq.toNumPy().copy()
                            dq_m[dq_m > 0] = 0 #set to zero where v > 0
                            vel_diag = np.hstack((np.identity(self.num_dofs)*dq_p, np.identity(self.num_dofs)*dq_m))
                            friction_regressor = np.vstack( (np.zeros((fb*6, self.num_dofs*2)), vel_diag))   # add base dynamics rows
                        A = np.concatenate((A, friction_regressor), axis=1)

                # add to previous regressors, linear dependencies don't change
                # (if too many, saturation or accuracy problems?)
                if i==0:
                    R = A.T.dot(A)
                else:
                    R += A.T.dot(A)

            # get column space dependencies
            Q,RQ,PQ = sla.qr(R, pivoting=True, mode='economic')

            np.savez(regr_filename, R=R, Q=Q, RQ=RQ, PQ=PQ, n=n_samples, fb=self.opt['floatingBase'], grav_only=self.opt['identifyGravityParamsOnly'], fric=self.opt['identifyFriction'], fric_sym=self.opt['identifySymmetricVelFriction'])

        if 'showRandomRegressor' in self.opt and self.opt['showRandomRegressor']:
            import matplotlib.pyplot as plt
            plt.imshow(R, interpolation='nearest')
            plt.show()

        return R, Q,RQ,PQ
Example #7
0
    def computeRegressors(self, data, only_simulate=False):
        # type: (Model, Data, bool) -> (None)
        """ compute regressors from measurements for each time step of the measurement data
            and stack them vertically. also stack measured torques and get simulation data.
            for floating base, get estimated base forces (6D wrench) and add to torque measure stack
        """

        self.data = data

        num_time = 0
        simulate_time = 0

        #extra regressor rows for floating base
        if self.opt['floatingBase']: fb = 6
        else: fb = 0
        self.regressor_stack = np.zeros(shape=((self.num_dofs+fb)*data.num_used_samples, self.num_identified_params))
        self.torques_stack = np.zeros(shape=((self.num_dofs+fb)*data.num_used_samples))
        self.sim_torq_stack = np.zeros(shape=((self.num_dofs+fb)*data.num_used_samples))
        self.torquesAP_stack = np.zeros(shape=((self.num_dofs+fb)*data.num_used_samples))

        num_contacts = len(data.samples['contacts'].item(0).keys()) if 'contacts' in data.samples else 0
        self.contacts_stack = np.zeros(shape=(num_contacts, (self.num_dofs+fb)*data.num_used_samples))
        self.contactForcesSum = np.zeros(shape=((self.num_dofs+fb)*data.num_used_samples))

        """loop over measurement data, optionally skip some values
            - get the regressor for each time step
            - if necessary, calculate inverse dynamics to get simulated torques
            - if necessary, get torques from contact wrenches and add them to the torques
            - stack the torques, regressors and contacts into matrices
        """
        contacts = {}
        for sample_index in self.progress(range(data.num_used_samples)):
            m_idx = sample_index*(self.opt['skipSamples'])+sample_index
            with helpers.Timer() as t:
                # read samples
                pos = data.samples['positions'][m_idx]
                vel = data.samples['velocities'][m_idx]
                acc = data.samples['accelerations'][m_idx]
                torq = data.samples['torques'][m_idx]
                if 'contacts' in data.samples:
                    for frame in data.samples['contacts'].item(0).keys():
                        contacts[frame] = data.samples['contacts'].item(0)[frame][m_idx]

                if self.opt['identifyGravityParamsOnly']:
                    #set vel and acc to zero (should be almost zero already) to remove noise
                    vel[:] = 0.0
                    acc[:] = 0.0

                # system state for iDynTree
                q = iDynTree.VectorDynSize.fromList(pos)
                dq = iDynTree.VectorDynSize.fromList(vel)
                ddq = iDynTree.VectorDynSize.fromList(acc)

                # in case that we simulate the torque measurements, need torque estimation for a priori parameters
                # or that we need to simulate the base reaction forces for floating base
                if self.opt['simulateTorques'] or self.opt['useAPriori'] or self.opt['floatingBase']:
                    if self.opt['useRBDL']:
                        #TODO: make sure joint order of torques is the same as iDynTree!
                        sim_torques = self.simulateDynamicsRBDL(data.samples, m_idx)
                    else:
                        sim_torques = self.simulateDynamicsIDynTree(data.samples, m_idx)

                    if self.opt['useAPriori']:
                        # torques sometimes contain nans, just a very small C number that gets converted to nan?
                        torqAP = np.nan_to_num(sim_torques)

                    if not self.opt['useRegressorForSimulation']:
                        if self.opt['simulateTorques']:
                            torq = np.nan_to_num(sim_torques)
                        else:
                            # write estimated base forces to measured torq vector from file (usually
                            # can't be measured so they are simulated from the measured base motion,
                            # contacts are added further down)
                            if self.opt['floatingBase']:
                                if len(torq) < (self.num_dofs + fb):
                                    torq = np.concatenate((np.nan_to_num(sim_torques[0:6]), torq))
                                else:
                                    torq[0:6] = np.nan_to_num(sim_torques[0:6])

            simulate_time += t.interval

            #...still looping over measurement samples

            row_index = (self.num_dofs+fb)*sample_index   # index for current row in stacked matrices

            if not only_simulate:
                # get numerical regressor (std)
                with helpers.Timer() as t:
                    if self.opt['floatingBase']:
                        base_vel = data.samples['base_velocity'][m_idx]
                        base_acc = data.samples['base_acceleration'][m_idx]

                        # get transform from base to world
                        rpy = data.samples['base_rpy'][m_idx]
                        rot = iDynTree.Rotation.RPY(rpy[0], rpy[1], rpy[2])
                        pos = iDynTree.Position.Zero()
                        world_T_base = iDynTree.Transform(rot, pos).inverse()

                        '''
                        # rotate base vel and acc to world frame
                        to_world = world_T_base.getRotation().toNumPy()
                        base_vel[0:3] = to_world.dot(base_vel[0:3])
                        base_vel[3:] = to_world.dot(base_vel[3:])
                        base_acc[0:3] = to_world.dot(base_acc[0:3])
                        base_acc[3:] = to_world.dot(base_acc[3:])
                        '''

                        base_velocity = iDynTree.Twist.fromList(base_vel)
                        base_acceleration = iDynTree.Twist.fromList(base_acc)

                        self.generator.setRobotState(q,dq,ddq, world_T_base, base_velocity, base_acceleration,
                                                     self.gravity_twist)
                    else:
                        self.generator.setRobotState(q,dq,ddq, self.gravity_twist)

                    # get (standard) regressor
                    regressor = iDynTree.MatrixDynSize(self.N_OUT, self.num_model_params)
                    knownTerms = iDynTree.VectorDynSize(self.N_OUT)   # what are known terms useable for?
                    if not self.generator.computeRegressor(regressor, knownTerms):
                        print("Error during numeric computation of regressor")

                    regressor = regressor.toNumPy()
                    if self.opt['floatingBase']:
                        # the base forces are expressed in the base frame for the regressor, so
                        # rotate them to world frame (inverse dynamics use world frame)
                        to_world = world_T_base.getRotation().toNumPy()
                        regressor[0:3, :] = to_world.dot(regressor[0:3, :])
                        regressor[3:6, :] = to_world.dot(regressor[3:6, :])

                    if self.opt['identifyGravityParamsOnly']:
                        #delete inertia param columns
                        regressor = np.delete(regressor, self.inertia_params, 1)

                    if self.opt['identifyFriction']:
                        # append unitary matrix to regressor for offsets/constant friction
                        sign = 1 #np.sign(dq.toNumPy())   #TODO: dependent on direction or always constant?
                        static_diag = np.identity(self.num_dofs)*sign
                        offset_regressor = np.vstack( (np.zeros((fb, self.num_dofs)), static_diag))
                        regressor = np.concatenate((regressor, offset_regressor), axis=1)

                        if not self.opt['identifyGravityParamsOnly']:
                            if self.opt['identifySymmetricVelFriction']:
                                # just use velocity directly
                                vel_diag = np.identity(self.num_dofs)*dq.toNumPy()
                                friction_regressor = np.vstack( (np.zeros((fb, self.num_dofs)), vel_diag))   # add base dynamics rows
                            else:
                                # append positive/negative velocity matrix for velocity dependent asymmetrical friction
                                dq_p = dq.toNumPy().copy()
                                dq_p[dq_p < 0] = 0 #set to zero where v < 0
                                dq_m = dq.toNumPy().copy()
                                dq_m[dq_m > 0] = 0 #set to zero where v > 0
                                vel_diag = np.hstack((np.identity(self.num_dofs)*dq_p, np.identity(self.num_dofs)*dq_m))
                                friction_regressor = np.vstack( (np.zeros((fb, self.num_dofs*2)), vel_diag))   # add base dynamics rows
                            regressor = np.concatenate((regressor, friction_regressor), axis=1)

                    # simulate with regressor
                    if self.opt['useRegressorForSimulation'] and (self.opt['simulateTorques'] or
                            self.opt['useAPriori'] or self.opt['floatingBase']):
                        torques = regressor.dot(self.xStdModel[self.identified_params])
                        if self.opt['simulateTorques']:
                            torq = torques
                        else:
                            # write estimated base forces to measured torq vector from file (usually
                            # can't be measured so they are simulated from the measured base motion,
                            # contacts are added further down)
                            if self.opt['floatingBase']:
                                if len(torq) < (self.num_dofs + fb):
                                    torq = np.concatenate((np.nan_to_num(torques[0:6]), torq))
                                else:
                                    torq[0:6] = np.nan_to_num(torques[0:6])
                        torques_simulated = np.nan_to_num(torques)

                    # stack on previous regressors
                    np.copyto(self.regressor_stack[row_index:row_index+self.num_dofs+fb], regressor)
                num_time += t.interval

            # stack results onto matrices of previous time steps
            np.copyto(self.torques_stack[row_index:row_index+self.num_dofs+fb], torq)

            if self.opt['useAPriori']:
                np.copyto(self.torquesAP_stack[row_index:row_index+self.num_dofs+fb], torqAP)

            if len(contacts.keys()):
                #convert contact wrenches into torque contribution
                for c in range(num_contacts):
                    frame = list(contacts.keys())[c]

                    dim = self.num_dofs+fb
                    # get jacobian and contact wrench for each contact frame and measurement sample
                    jacobian = iDynTree.MatrixDynSize(6, dim)
                    if not self.dynComp.getFrameJacobian(str(frame), jacobian):
                        continue
                    jacobian = jacobian.toNumPy()

                    # mul each sample of measured contact wrenches with frame jacobian
                    contacts_torq = np.empty(dim)
                    contacts_torq = jacobian.T.dot(contacts[frame])

                    contact_idx = (sample_index*dim)
                    np.copyto(self.contacts_stack[c][contact_idx:contact_idx+dim], contacts_torq[-dim:])

        # finished looping over samples

        # sum over (contact torques) for each contact frame
        self.contactForcesSum = np.sum(self.contacts_stack, axis=0)

        if self.opt['floatingBase']:
            if self.opt['simulateTorques']:
                # add measured contact wrench to torque estimation from iDynTree
                if self.opt['addContacts']:
                    self.torques_stack = self.torques_stack + self.contactForcesSum
            else:
                # if not simulating, measurements of joint torques already contain contact contribution,
                # so only add it to the (always simulated) base force estimation
                torques_stack_2dim = np.reshape(self.torques_stack, (data.num_used_samples, self.num_dofs+fb))
                self.contactForcesSum_2dim = np.reshape(self.contactForcesSum, (data.num_used_samples, self.num_dofs+fb))
                if self.opt['addContacts']:
                    torques_stack_2dim[:, :6] += self.contactForcesSum_2dim[:, :6]
                self.torques_stack = torques_stack_2dim.flatten()

        if self.opt['addContacts']:
            self.sim_torq_stack = self.sim_torq_stack + self.contactForcesSum

        if len(contacts.keys()) or self.opt['simulateTorques']:
            # write back torques to data object when simulating or contacts were added
            self.data.samples['torques'] = np.reshape(self.torques_stack, (data.num_used_samples, self.num_dofs+fb))

        with helpers.Timer() as t:
            if self.opt['useAPriori']:
                # get torque delta to identify with
                self.tau = self.torques_stack - self.torquesAP_stack
            else:
                self.tau = self.torques_stack
        simulate_time+=t.interval

        self.YStd = self.regressor_stack

        # if difference between random regressor (that was used for base projection) and regressor
        # from the data is too big, the base regressor can still have linear dependencies.
        # for these cases, it seems to be better to get the base columns directly from the data regressor matrix
        if not self.opt['useStructuralRegressor'] and not only_simulate:
            if self.opt['verbose']:
                print('Getting independent base columns again from data regressor')
            self.computeRegressorLinDepsQR(self.YStd)

        if self.opt['useBasisProjection']:
            self.YBase = np.dot(self.YStd, self.B)   # project regressor to base regressor
        else:
            self.YBase = np.dot(self.YStd, self.Pb)  # regressor following Sousa, 2014

        if self.opt['filterRegressor']:
            order = 5                            # Filter order
            fs = self.data.samples['frequency']  # Sampling freq
            fc = self.opt['filterRegCutoff']     # Cut-off frequency (Hz)
            b, a = signal.butter(order, fc / (fs / 2), btype='low', analog=False)
            for j in range(0, self.num_base_inertial_params):
                for i in range(0, self.num_dofs):
                    self.YBase[i::self.num_dofs, j] = signal.filtfilt(b, a, self.YBase[i::self.num_dofs, j])

        self.sample_end = data.samples['positions'].shape[0]
        if self.opt['skipSamples'] > 0: self.sample_end -= (self.opt['skipSamples'])

        # keep absolute torques (self.tau can be relative)
        self.tauMeasured = np.reshape(self.torques_stack, (data.num_used_samples, self.num_dofs+fb))

        self.T = data.samples['times'][0:self.sample_end:self.opt['skipSamples']+1]

        if self.opt['showTiming']:
            print('(simulation for regressors took %.03f sec.)' % simulate_time)
            print('(getting regressors took %.03f sec.)' % num_time)

        if self.opt['verbose'] == 2:
            print("YStd: {}".format(self.YStd.shape), end=' ')
            print("YBase: {}, cond: {}".format(self.YBase.shape, la.cond(self.YBase)))
Example #8
0
    def simulateDynamicsIDynTree(self, samples, sample_idx, dynComp=None, xStdModel=None):
        # type: (Dict[str, np._ArrayLike], int, iDynTree.DynamicsComputations, np._ArrayLike[float]) -> np._ArrayLike[float]
        """ compute torques for one time step of measurements """

        if not dynComp:
            dynComp = self.dynComp
        if xStdModel is None:
            xStdModel = self.xStdModel
        world_gravity = iDynTree.SpatialAcc.fromList(self.gravity)

        # read sample data
        pos = samples['positions'][sample_idx]
        vel = samples['velocities'][sample_idx]
        acc = samples['accelerations'][sample_idx]

        # system state for iDynTree
        q = iDynTree.VectorDynSize.fromList(pos)
        dq = iDynTree.VectorDynSize.fromList(vel)
        ddq = iDynTree.VectorDynSize.fromList(acc)

        # calc torques and forces with iDynTree dynamicsComputation class
        if self.opt['floatingBase']:
            base_vel = samples['base_velocity'][sample_idx]
            base_acc = samples['base_acceleration'][sample_idx]
            rpy = samples['base_rpy'][sample_idx]

            # get the homogeneous transformation that transforms vectors expressed
            # in the base reference frame to frames expressed in the world
            # reference frame, i.e. pos_world = world_T_base*pos_base
            # for identification purposes, the position does not matter but rotation is taken
            # from IMU estimation. The gravity, base velocity and acceleration all need to be
            # expressed in world frame
            rot = iDynTree.Rotation.RPY(rpy[0], rpy[1], rpy[2])
            pos = iDynTree.Position.Zero()
            world_T_base = iDynTree.Transform(rot, pos).inverse()

            '''
            # rotate base vel and acc to world frame
            to_world = world_T_base.getRotation().toNumPy()
            base_vel[0:3] = to_world.dot(base_vel[0:3])
            base_vel[3:] = to_world.dot(base_vel[3:])
            base_acc[0:3] = to_world.dot(base_acc[0:3])
            base_acc[3:] = to_world.dot(base_acc[3:])
            '''

            # The twist (linear, angular velocity) of the base, expressed in the world
            # orientation frame and with respect to the base origin
            base_velocity = iDynTree.Twist.fromList(base_vel)
            # The 6d classical acceleration (linear, angular acceleration) of the base
            # expressed in the world orientation frame and with respect to the base origin
            base_acceleration = iDynTree.ClassicalAcc.fromList(base_acc)

            dynComp.setRobotState(q, dq, ddq, world_T_base, base_velocity, base_acceleration,
                                  world_gravity)
        else:
            dynComp.setRobotState(q, dq, ddq, world_gravity)

        # compute inverse dynamics
        torques = iDynTree.VectorDynSize(self.num_dofs)
        baseReactionForce = iDynTree.Wrench()
        dynComp.inverseDynamics(torques, baseReactionForce)
        torques = torques.toNumPy()

        if self.opt['identifyFriction']:
            # add friction torques
            # constant
            sign = 1 #np.sign(vel)
            p_constant = range(self.friction_params_start, self.friction_params_start+self.num_dofs)
            torques += sign*xStdModel[p_constant]

            # vel dependents
            if not self.opt['identifyGravityParamsOnly']:
                # (take only first half of params as they are not direction dependent in urdf anyway)
                p_vel = range(self.friction_params_start+self.num_dofs, self.friction_params_start+self.num_dofs*2)
                torques += xStdModel[p_vel]*vel

        if self.opt['floatingBase']:
            return np.concatenate((baseReactionForce.toNumPy(), torques))
        else:
            return torques
Example #9
0
    def __init__(self, opt, urdf_file, regressor_file=None, regressor_init=True):
        # (Dict[str, Any, str, str]) -> None
        self.urdf_file = urdf_file
        self.opt = opt

        progress_inst = helpers.Progress(opt)
        self.progress = progress_inst.progress

        # set these options in case model was not instanciated from Identification
        if 'orthogonalizeBasis' not in self.opt:
            self.opt['orthogonalizeBasis'] = 1

        if 'useBasisProjection' not in self.opt:
            self.opt['useBasisProjection'] = 0

        # debug options
        self.opt['useRegressorForSimulation'] = 0
        self.opt['addContacts'] = 1

        # create generator instance and load model
        self.generator = iDynTree.DynamicsRegressorGenerator()
        ret = self.generator.loadRobotAndSensorsModelFromFile(urdf_file)
        if not ret:
            sys.exit()

        # load also with new model class for some functions
        #self.idyn_model = iDynTree.Model()
        #iDynTree.modelFromURDF(urdf_file, self.idyn_model)

        #viz = iDynTree.Visualizer()
        #viz.addModel(self.idyn_model, 'model')
        #for i in range(0,30):
            #model_inst = viz.modelViz('model')
            #model_inst.setPositions(world_H_base, VectorDynSize jointPos)
        #    viz.draw()
        #viz.close()

        if self.opt['verbose']:
            print('loaded model {}'.format(urdf_file))

        # define what regressor type
        if regressor_file:
            with open(regressor_file, 'r') as filename:
                regrXml = filename.read()

            self.jointNames = []   # type: List[str]
            import xml.etree.ElementTree as ET
            tree = ET.fromstring(regrXml)
            for l in tree.iter():
                if l.tag == 'joint':
                    self.jointNames.append(l.text)
            self.num_dofs = len(self.jointNames)
        else:
            # (default for all joints)
            if self.opt['floatingBase']:
                regrXml = '''
                <regressor>
                  <baseLinkDynamics/>
                  <jointTorqueDynamics>
                    <allJoints/>
                  </jointTorqueDynamics>
                </regressor>'''
            else:
                regrXml = '''
                <regressor>
                  <jointTorqueDynamics>
                    <allJoints/>
                  </jointTorqueDynamics>
                </regressor>'''
        self.generator.loadRegressorStructureFromString(regrXml)
        self.regrXml = regrXml

        if not regressor_file:
            import re
            self.jointNames = re.sub(r"DOF Index: \d+ Name: ", "", self.generator.getDescriptionOfDegreesOfFreedom()).split()
            self.num_dofs = self.generator.getNrOfDegreesOfFreedom()

        # TODO: reported dofs and links are not dependent on joints specified in regressor (but
        # uses all from model file)
        # dynComp simulates with all joints regardless of regressor, regressor rows should be as specified
        # (worked around ATM by reading from XML directly)
        if self.opt['verbose']:
            print('# DOFs: {}'.format(self.num_dofs))
            print('Joints: {}'.format(self.jointNames))

        # Get the number of outputs of the regressor
        # (should eq #dofs + #base vals)
        self.N_OUT = self.generator.getNrOfOutputs()
        if self.opt['verbose']:
            if self.opt['floatingBase']:
                print('# regressor outputs: {} (DOFs + 6 base)'.format(self.N_OUT))
            else:
                print('# regressor outputs: {}'.format(self.N_OUT))


        self.num_links = self.generator.getNrOfLinks()-self.generator.getNrOfFakeLinks()
        if self.opt['verbose']:
            print('# links: {} (+ {} fake)'.format(self.num_links, self.generator.getNrOfFakeLinks()))

        self.inertia_params = list()  # type: List[int]
        self.mass_params = list()     # type: List[int]
        for i in range(self.num_links):
            self.mass_params.append(i*10)
            self.inertia_params.extend([i*10+4, i*10+5, i*10+6, i*10+7, i*10+8, i*10+9])

        #self.linkNames = self.generator.getDescriptionOfLinks().split()
        self.linkNames = []  # type: List[str]
        import re
        for d in self.generator.getDescriptionOfParameters().strip().split("\n"):
            link = re.findall(r"of link (.*)", d)[0]
            if link not in self.linkNames:
                self.linkNames.append(link)
        if self.opt['verbose']:
            print('{}'.format({i: self.linkNames[i] for i in range(self.num_links)}))

        self.limits = helpers.URDFHelpers.getJointLimits(self.urdf_file, use_deg=False)

        # get amount of initial inertia params (from urdf) (full params, no friction, no removed columns)
        self.num_model_params = self.num_links*10
        self.num_all_params = self.num_model_params

        # add N offset params (offsets or constant friction) and 2*N velocity dependent friction params
        # (velocity +- for asymmetrical friction)
        if self.opt['identifyFriction']:
            self.num_identified_params = self.num_model_params + self.num_dofs
            self.num_all_params += self.num_dofs

            if not self.opt['identifyGravityParamsOnly']:
                if self.opt['identifySymmetricVelFriction']:
                    self.num_identified_params += self.num_dofs
                    self.num_all_params += self.num_dofs
                else:
                    self.num_identified_params += 2*self.num_dofs
                    self.num_all_params += 2*self.num_dofs
        else:
            self.num_identified_params = self.num_model_params

        self.friction_params_start = self.num_model_params

        if self.opt['identifyGravityParamsOnly']:
            self.num_identified_params = self.num_identified_params - len(self.inertia_params)
            self.friction_params_start = self.num_model_params - len(self.inertia_params)

        if self.opt['verbose']:
            print('# params: {} ({} will be identified)'.format(self.num_model_params, self.num_identified_params))

        self.baseNames = ['base f_x', 'base f_y', 'base f_z', 'base m_x', 'base m_y', 'base m_z']

        self.gravity = [0,0,-9.81,0,0,0]
        self.gravity_twist = iDynTree.Twist.fromList(self.gravity)

        if self.opt['useRBDL']:
            import rbdl
            self.rbdlModel = rbdl.loadModel(self.urdf_file, floating_base=self.opt['floatingBase'], verbose=False)
            self.rbdlModel.gravity = np.array(self.gravity[0:3])
        self.dynComp = iDynTree.DynamicsComputations()
        self.dynComp.loadRobotModelFromFile(self.urdf_file)

        # get model parameters
        xStdModel = iDynTree.VectorDynSize(self.generator.getNrOfParameters())
        self.generator.getModelParameters(xStdModel)
        self.xStdModel = xStdModel.toNumPy()
        if self.opt['identifyFriction']:
            self.xStdModel = np.concatenate((self.xStdModel, np.zeros(self.num_dofs)))
            if not self.opt['identifyGravityParamsOnly']:
                if self.opt['identifySymmetricVelFriction']:
                    self.xStdModel = np.concatenate((self.xStdModel, np.zeros(self.num_dofs)))
                else:
                    self.xStdModel = np.concatenate((self.xStdModel, np.zeros(2*self.num_dofs)))
            helpers.ParamHelpers.addFrictionFromURDF(self, self.urdf_file, self.xStdModel)

        if opt['estimateWith'] == 'urdf':
            self.xStd = self.xStdModel

        if regressor_init:
            # get model dependent projection matrix and linear column dependencies (i.e. base
            # groupings)
            self.computeRegressorLinDepsQR()
Example #10
0
@author: adelpret
"""

import iDynTree
from iDynTree import DynamicsComputations

URDF_FILE = '/home/username/path/robot.urdf'

dynComp = DynamicsComputations()
dynComp.loadRobotModelFromFile(URDF_FILE)
print "The loaded model has", dynComp.getNrOfDegreesOfFreedom(), \
    "internal degrees of freedom and",dynComp.getNrOfLinks(),"links."

dofs = dynComp.getNrOfDegreesOfFreedom()
q = iDynTree.VectorDynSize(dofs)
dq = iDynTree.VectorDynSize(dofs)
ddq = iDynTree.VectorDynSize(dofs)
for dof in range(dofs):
    # For the sake of the example, we fill the joints vector with gibberish data (remember in any case
    # that all quantities are expressed in radians-based units
    q.setVal(dof, 1.0)
    dq.setVal(dof, 0.4)
    ddq.setVal(dof, 0.3)

# The spatial acceleration is a 6d acceleration vector.
# For all 6d quantities, we use the linear-angular serialization
# (the first three value are for the linear quantity, the
#  the last  three values are for the angular quantity)
gravity = iDynTree.SpatialAcc()
gravity.zero()
Example #11
0
def test_regressors():
    #get some random state values and compare inverse dynamics torques with torques
    #obtained with regressor and parameter vector

    idyn_model = iDynTree.Model()
    iDynTree.modelFromURDF(urdf_file, idyn_model)

    # create generator instance and load model
    generator = iDynTree.DynamicsRegressorGenerator()
    generator.loadRobotAndSensorsModelFromFile(urdf_file)
    regrXml = '''
    <regressor>
      <baseLinkDynamics/>
      <jointTorqueDynamics>
        <allJoints/>
      </jointTorqueDynamics>
    </regressor>'''
    generator.loadRegressorStructureFromString(regrXml)
    num_model_params = generator.getNrOfParameters()
    num_out = generator.getNrOfOutputs()
    n_dofs = generator.getNrOfDegreesOfFreedom()
    num_samples = 100

    xStdModel = iDynTree.VectorDynSize(num_model_params)
    generator.getModelParameters(xStdModel)
    xStdModel = xStdModel.toNumPy()

    gravity_twist = iDynTree.Twist.fromList([0, 0, -9.81, 0, 0, 0])
    gravity_acc = iDynTree.SpatialAcc.fromList([0, 0, -9.81, 0, 0, 0])

    dynComp = iDynTree.DynamicsComputations()
    dynComp.loadRobotModelFromFile(urdf_file)

    regressor_stack = np.zeros(shape=((n_dofs + 6) * num_samples,
                                      num_model_params))
    idyn_torques = np.zeros(shape=((n_dofs + 6) * num_samples))
    contactForceSum = np.zeros(shape=((n_dofs + 6) * num_samples))

    for sample_index in range(0, num_samples):
        q = iDynTree.VectorDynSize.fromList(
            ((np.random.ranf(n_dofs) * 2 - 1) * np.pi).tolist())
        dq = iDynTree.VectorDynSize.fromList(
            ((np.random.ranf(n_dofs) * 2 - 1) * np.pi).tolist())
        ddq = iDynTree.VectorDynSize.fromList(
            ((np.random.ranf(n_dofs) * 2 - 1) * np.pi).tolist())
        base_vel = np.pi * np.random.rand(6)
        base_acc = np.pi * np.random.rand(6)

        #rpy = [0,0,0]
        rpy = np.random.ranf(3) * 0.1
        rot = iDynTree.Rotation.RPY(rpy[0], rpy[1], rpy[2])
        pos = iDynTree.Position.Zero()
        world_T_base = iDynTree.Transform(rot, pos).inverse()

        # rotate base vel and acc to world frame
        to_world = world_T_base.getRotation().toNumPy()
        base_vel[0:3] = to_world.dot(base_vel[0:3])
        base_vel[3:] = to_world.dot(base_vel[3:])
        base_acc[0:3] = to_world.dot(base_acc[0:3])
        base_acc[3:] = to_world.dot(base_acc[3:])

        base_velocity = iDynTree.Twist.fromList(base_vel)
        base_acceleration = iDynTree.Twist.fromList(base_acc)
        base_acceleration_acc = iDynTree.ClassicalAcc.fromList(base_acc)

        # regressor
        generator.setRobotState(q, dq, ddq, world_T_base, base_velocity,
                                base_acceleration, gravity_twist)

        regressor = iDynTree.MatrixDynSize(num_out, num_model_params)
        knownTerms = iDynTree.VectorDynSize(num_out)
        if not generator.computeRegressor(regressor, knownTerms):
            print("Error during numeric computation of regressor")

        #the base forces are expressed in the base frame for the regressor, so transform them
        to_world = np.fromstring(world_T_base.getRotation().toString(),
                                 sep=' ').reshape((3, 3))
        regressor = regressor.toNumPy()
        regressor[0:3, :] = to_world.dot(regressor[0:3, :])
        regressor[3:6, :] = to_world.dot(regressor[3:6, :])

        row_index = (
            n_dofs + 6
        ) * sample_index  # index for current row in stacked regressor matrix
        np.copyto(regressor_stack[row_index:row_index + n_dofs + 6], regressor)

        # inverse dynamics
        #dynComp.setFloatingBase('base_link')
        dynComp.setRobotState(q, dq, ddq, world_T_base, base_velocity,
                              base_acceleration_acc, gravity_acc)
        torques = iDynTree.VectorDynSize(n_dofs)
        baseReactionForce = iDynTree.Wrench()
        dynComp.inverseDynamics(torques, baseReactionForce)

        torques = np.concatenate(
            (baseReactionForce.toNumPy(), torques.toNumPy()))
        np.copyto(idyn_torques[row_index:row_index + n_dofs + 6], torques)

        # contacts
        dim = n_dofs + 6
        contact = np.array([0, 0, 10, 0, 0, 0])
        jacobian = iDynTree.MatrixDynSize(6, dim)
        dynComp.getFrameJacobian(contactFrame, jacobian)
        jacobian = jacobian.toNumPy()
        contactForceSum[sample_index * dim:(sample_index + 1) *
                        dim] = jacobian.T.dot(contact)

    regressor_torques = np.dot(regressor_stack, xStdModel) + contactForceSum
    idyn_torques += contactForceSum

    error = np.reshape(regressor_torques - idyn_torques, (num_samples, dim))

    #plots = plt.plot(range(0, num_samples), error)
    #plt.legend(plots, ['f_x', 'f_y', 'f_z', 'm_x', 'm_y', 'm_z', 'j_0'])
    #plt.show()

    error_norm = la.norm(error)
    print(error_norm)
    assert error_norm <= 0.01
Example #12
0
# TODO : put in the regressor only the relevant parameters
params = regrGen.getNrOfParameters()

# Get the number of outputs of the regressor
# Given that we are considering only the base dynamics
# of a subtree, we will have just 6 outputs (3 force, 3 torques)
outs = regrGen.getNrOfOutputs()

# We can now create the input for the regressor:
# joint position, velocities and acceleration
# and gravity acceleration at the base frame
# (you can get the base link with the regrGen.getBaseLink() method)

# If you are unsure of the assumed serialization of the DOFs, you can use
# the regrGen.getDescriptionOfDegreesOfFreedom() method
qj = iDynTree.VectorDynSize(dof)
dqj = iDynTree.VectorDynSize(dof)
ddqj = iDynTree.VectorDynSize(dof)
gravity = iDynTree.Twist()

# Currently the smooth conversion between Matlab and iDynTree vector and
# matrices is still a TODO, so for now we have to rely on the setVal/getVal
# methods
gravity.setVal(0, 0.0)
gravity.setVal(1, 0.0)
gravity.setVal(2, -9.81)

# Here we should fill the q/dqj/ddqj with measured values

# Note that we are using the "fixed base" version of setRobotState
regrGen.setRobotState(qj, dqj, ddqj, gravity)
Example #13
0
    def __init__(self, opt, urdf_file, urdf_file_real, measurements_files, regressor_file, validation_file):
        # type: (Dict, str, str, str, str, str) -> None
        self.opt = opt

        # some additional options (experiments)

        # in order ot get regressor and base equations, use basis projection matrix. Otherwise use
        # permutation from QR directly (Gautier/Sousa method)
        self.opt['useBasisProjection'] = 0

        # in case projection is used, orthogonalize the basis matrix (SDP estimation seem to work
        # more stable that way)
        self.opt['orthogonalizeBasis'] = 1

        # add regularization term to SDP identification that minimized CAD distance for non-identifiable params
        self.opt['useRegressorRegularization'] = 1
        self.opt['regularizationFactor'] = 1000.0   #proportion of distance term

        # if using fixed base dynamics, remove first link that is the fixed base which should completely
        # not be identifiable and not be part of equations (as it does not move)
        self.opt['deleteFixedBase'] = 1

        # end additional config flags


        # load model description and initialize
        self.model = Model(self.opt, urdf_file, regressor_file)

        # load measurements
        self.data = Data(self.opt)
        if measurements_files:
            self.data.init_from_files(measurements_files)

        self.paramHelpers = helpers.ParamHelpers(self.model, self.opt)
        self.urdfHelpers = helpers.URDFHelpers(self.paramHelpers, self.model, self.opt)
        self.sdp = sdp.SDP(self)
        if self.opt['constrainUsingNL']:
            from identification.nlopt import NLOPT
            self.nlopt = NLOPT(self)

        self.tauEstimated = None    # type: np._ArrayLike
        self.res_error = 100        # last residual error in percent

        self.urdf_file_real = urdf_file_real
        if self.urdf_file_real:
            dc = iDynTree.DynamicsRegressorGenerator()
            if not dc.loadRobotAndSensorsModelFromFile(urdf_file_real):
                sys.exit()
            tmp = iDynTree.VectorDynSize(self.model.num_model_params)
            #set regressor, otherwise getModelParameters segfaults
            dc.loadRegressorStructureFromString(self.model.regrXml)
            dc.getModelParameters(tmp)
            self.xStdReal = tmp.toNumPy()
            #add some zeros for friction
            self.xStdReal = np.concatenate((self.xStdReal, np.zeros(self.model.num_all_params-self.model.num_model_params)))
            if self.opt['identifyFriction']:
                self.paramHelpers.addFrictionFromURDF(self.model, self.urdf_file_real, self.xStdReal)

        self.validation_file = validation_file

        progress_inst = helpers.Progress(opt)
        self.progress = progress_inst.progress
    def _to_idyntree_dyn_vector(array: np.ndarray):
        import iDynTree
        dyn_vector = iDynTree.VectorDynSize()
        dyn_vector = dyn_vector.FromPython(array)

        return dyn_vector
    def objectiveFunc(self, x, test=False):
        self.iter_cnt += 1
        print("call #{}/{}".format(self.iter_cnt, self.iter_max))

        wf, q, a, b = self.vecToParams(x)
        
        if self.config['verbose']:
            print('wf {}'.format(wf))
            print('a {}'.format(np.round(a,5).tolist()))
            print('b {}'.format(np.round(b,5).tolist()))
            print('q {}'.format(np.round(q,5).tolist()))

        #input vars out of bounds, skip call
        if not self.testBounds(x):
            # give penalty obj value for out of bounds (because we shouldn't get here)
            # TODO: for some algorithms (with augemented lagrangian added bounds) this should
            # not be very high as it is added again anyway)
            f = 1000.0
            if self.config['minVelocityConstraint']:
                g = [10.0]*self.num_constraints
            else:
                g = [10.0]*self.num_constraints

            fail = 1.0
            return f, g, fail

        self.trajectory.initWithParams(a,b,q, self.nf, wf)

        old_verbose = self.config['verbose']
        self.config['verbose'] = 0
        #old_floatingBase = self.config['floatingBase']
        #self.config['floatingBase'] = 0
        trajectory_data, data = self.sim_func(self.config, self.trajectory, model=self.model)

        self.config['verbose'] = old_verbose
        #self.config['floatingBase'] = old_floatingBase

        self.last_trajectory_data = trajectory_data
        if self.config['showOptimizationTrajs']:
            plotter(self.config, data=trajectory_data)

        f = np.linalg.cond(self.model.YBase)
        #f = np.log(np.linalg.det(self.model.YBase.T.dot(self.model.YBase)))   #fisher information matrix

        #xBaseModel = np.dot(model.Binv | K, model.xStdModel)
        #f = np.linalg.cond(model.YBase.dot(np.diag(xBaseModel)))    #weighted with CAD params

        f1 = 0
        # add constraints  (later tested for all: g(n) <= 0)
        g = [1e10]*self.num_constraints
        jn = self.model.jointNames
        for n in range(self.num_dofs):
            # check for joint limits
            # joint pos lower
            print("minma of trajectory",np.min(trajectory_data['positions'][:, n]))
            print("maxima of trajectory",np.max(trajectory_data['positions'][:, n]))
            
            if len(self.config['ovrPosLimit'])>n and self.config['ovrPosLimit'][n]:
                g[n] = np.deg2rad(self.config['ovrPosLimit'][n][0]) - np.min(trajectory_data['positions'][:, n])
                
            else:
                g[n] = self.limits[jn[n]]['lower'] - np.min(trajectory_data['positions'][:, n])
            # joint pos upper
            if len(self.config['ovrPosLimit'])>n and self.config['ovrPosLimit'][n]:
                g[self.num_dofs+n] = np.max(trajectory_data['positions'][:, n]) - np.deg2rad(self.config['ovrPosLimit'][n][1])
            else:
                g[self.num_dofs+n] = np.max(trajectory_data['positions'][:, n]) - self.limits[jn[n]]['upper']
            # max joint vel
            #g[2*self.num_dofs+n] = np.max(np.abs(trajectory_data['velocities'][:, n])) - self.limits[jn[n]]['velocity']
            
            # max torques
           # g[3*self.num_dofs+n] = np.nanmax(np.abs(data.samples['torques'][:, n])) - self.limits[jn[n]]['torque']

            '''if self.config['minVelocityConstraint']:
                # max joint vel of trajectory should at least be 10% of joint limit
                g[3*self.num_dofs+n] = self.limits[jn[n]]['velocity']*self.config['minVelocityPercentage'] - \
                                    np.max(np.abs(trajectory_data['velocities'][:, n]))'''

            # highest joint torque should at least be 10% of joint limit
            '''g[5*self.num_dofs+n] = self.limits[jn[n]]['torque']*0.1 - np.max(np.abs(data.samples['torques'][:, n]))
            f_tmp = self.limits[jn[n]]['torque']*0.1 - np.max(np.abs(data.samples['torques'][:, n]))
            if f_tmp > 0:
                f1+=f_tmp'''
        print(g)   
        # check collision constraints
        # (for whole trajectory but only get closest distance as constraint value)
        c_s = self.num_constraints - self.num_coll_constraints  # start where collision constraints start
        traversal = iDynTree.Traversal()
        success = self.idyn_model.computeFullTreeTraversal(traversal)
        rotation = iDynTree.Rotation(1.0, 0.0, 0.0,
                                     0.0, 1.0, 0.0,
                                     0.0, 0.0, 1.0)
        position = iDynTree.Position(0.0, 0.0, 0.0)
        worldHbase = iDynTree.Transform(rotation, position)
        jointPosition = iDynTree.VectorDynSize(5)
        
        if self.config['verbose'] > 1:
            print('checking collisions')
        for p in range(0, trajectory_data['positions'].shape[0], 10):
            g_cnt1 = 0
            g_cnt2 = 1
        
            if self.config['verbose'] > 1:
                print("Sample {}".format(p))
            q = trajectory_data['positions'][p]

            for i in range(len(q)):
                jointPosition[i] = q[i]

            linkPositions = iDynTree.LinkPositions(self.idyn_model) 
            iDynTree.ForwardPositionKinematics(self.idyn_model, traversal, worldHbase,jointPosition, linkPositions)
            pose_link5 = linkPositions(5)
            z = pose_link5.getPosition().getVal(2)
            origin = (0, 0 , 0)
            end_eff = (pose_link5.getPosition().getVal(0), pose_link5.getPosition().getVal(1), (pose_link5.getPosition().getVal(2)))
            dist = distance.euclidean(origin, end_eff)
            
            if(z < 0.35 ):
                if (z < g[c_s+g_cnt1]):
                    g[c_s+g_cnt1] = z
               
            if(dist < 0.25):
                if (dist < g[c_s+g_cnt2]):
                    g[c_s+g_cnt2] = dist
                
                
                      
            '''for l0 in range(self.model.num_links + len(self.world_links)):
                for l1 in range(self.model.num_links + len(self.world_links)):
                    l0_name = (self.model.linkNames + self.world_links)[l0]
                    l1_name = (self.model.linkNames + self.world_links)[l1]

                    if (l0 >= l1):  # don't need, distance is the same in both directions; same link never collides
                        continue
                    if l0_name in self.config['ignoreLinksForCollision'] \
                            or l1_name in self.config['ignoreLinksForCollision']:
                        continue
                    if [l0_name, l1_name] in self.config['ignoreLinkPairsForCollision'] or \
                       [l1_name, l0_name] in self.config['ignoreLinkPairsForCollision']:
                        continue

                    # neighbors can't collide with a proper joint range, so ignore--
                    if l0 < self.model.num_links and l1 < self.model.num_links:
                        if l0_name in self.neighbors[l1_name]['links'] or l1_name in self.neighbors[l0_name]['links']:
                            continue

                    if l0 < l1:
                        d = self.getLinkDistance(l0_name, l1_name, q)
                        if d < g[c_s+g_cnt]:
                            print("l0: {} l1: {}".format(l0,l1))
                            g[c_s+g_cnt] = d
                            
                        g_cnt += 1'''

        self.last_g = g
        

        #add min join torques as second objective
        if f1 > 0:
            f+= f1
            print("added cost: {}".format(f1))

        c = self.testConstraints(g)
        if c:
            print(Fore.GREEN, end=' ')
        else:
            print(Fore.YELLOW, end=' ')

        print("objective function value: {} (last best: {} + {})".format(f,
                                                            self.last_best_f-self.last_best_f_f1,
                                                            self.last_best_f_f1), end=' ')
        print(Fore.RESET)

        if self.config['verbose']:
            if self.opt_prob.is_gradient:
                print("(Gradient evaluation)")

        if self.mpi_rank == 0 and not self.opt_prob.is_gradient and self.config['showOptimizationGraph']:
            self.xar.append(self.iter_cnt)
            self.yar.append(f)
            self.x_constr.append(c)
            self.updateGraph()

        self.showVisualizerTrajectory(self.trajectory)

        #keep last best solution (some solvers don't keep it)
        if c and f < self.last_best_f:
            self.last_best_f = f
            self.last_best_f_f1 = f1
            self.last_best_sol = x

        print("\n\n")

        fail = 0.0
        #funcs = {}
        #funcs['opt'] = f
        #funcs['con'] = g
        #return funcs, fail
        return f, g, fail
Example #16
0
from identification import helpers

if __name__ == '__main__':
    #urdf_file = '../model/centauro.urdf'
    urdf_file = '../model/walkman_orig.urdf'
    dynamics = iDynTree.DynamicsComputations()
    dynamics.loadRobotModelFromFile(urdf_file)
    dynamics.setFloatingBase('LFoot')
    n_dofs = dynamics.getNrOfDegreesOfFreedom()
    jointNames = []
    for i in range(n_dofs):
        jointNames.append(dynamics.getJointName(i))
    limits = helpers.URDFHelpers.getJointLimits(urdf_file, use_deg=False)

    #for each joint, sweep through all possible joint angles and get mass matrix
    q = iDynTree.VectorDynSize(n_dofs)
    q.zero()
    dq = iDynTree.VectorDynSize(n_dofs)
    #dq.fromList([1.0]*n_dofs)
    dq.zero()
    ddq = iDynTree.VectorDynSize(n_dofs)
    ddq.zero()
    world_gravity = iDynTree.SpatialAcc.fromList([0, 0, -9.81, 0, 0, 0])
    base_velocity = iDynTree.Twist()
    base_velocity.zero()
    base_acceleration = iDynTree.ClassicalAcc()
    base_acceleration.zero()
    rot = iDynTree.Rotation.RPY(0, 0, 0)
    pos = iDynTree.Position.Zero()
    world_T_base = iDynTree.Transform(rot, pos)
    torques = iDynTree.VectorDynSize(n_dofs)