|
145 | 145 | from muscleData import getBodyMass
|
146 | 146 | bodyMass = getBodyMass(pathModelFolder, modelName, loadBodyMass)
|
147 | 147 |
|
148 |
| - # %% Muscles. |
| 148 | + # %% Muscles (very messy). |
149 | 149 | # This section is very specific to the OpenSim model being used.
|
150 | 150 | # The list 'muscles' includes all right leg muscles, as well both side
|
151 | 151 | # trunk muscles.
|
|
163 | 163 | rightSideMuscles = muscles[:-3]
|
164 | 164 | leftSideMuscles = [muscle[:-1] + 'l' for muscle in rightSideMuscles]
|
165 | 165 | bothSidesMuscles = leftSideMuscles + rightSideMuscles
|
| 166 | + leftTrunkMuscles = muscles[-3:] |
| 167 | + rightTrunkMuscles = muscles[-6:-3] |
| 168 | + trunkMuscles = leftTrunkMuscles + rightTrunkMuscles |
166 | 169 | nMuscles = len(bothSidesMuscles)
|
167 | 170 | nSideMuscles = len(rightSideMuscles)
|
168 | 171 |
|
|
391 | 394 | from casadiFunctions import polynomialApproximation
|
392 | 395 | leftPolynomialJoints = [
|
393 | 396 | 'hip_flexion_l', 'hip_adduction_l', 'hip_rotation_l', 'knee_angle_l',
|
394 |
| - 'ankle_angle_l', 'subtalar_angle_l', 'mtp_angle_l', |
395 |
| - 'lumbar_extension', 'lumbar_bending', 'lumbar_rotation'] |
| 397 | + 'ankle_angle_l', 'subtalar_angle_l', 'mtp_angle_l'] |
396 | 398 | rightPolynomialJoints = [
|
397 | 399 | 'hip_flexion_r', 'hip_adduction_r', 'hip_rotation_r', 'knee_angle_r',
|
398 |
| - 'ankle_angle_r', 'subtalar_angle_r', 'mtp_angle_r', |
| 400 | + 'ankle_angle_r', 'subtalar_angle_r', 'mtp_angle_r'] |
| 401 | + trunkPolynomialJoints = [ |
399 | 402 | 'lumbar_extension', 'lumbar_bending', 'lumbar_rotation']
|
400 | 403 | if not withMTP:
|
401 | 404 | leftPolynomialJoints.remove(mtpJoints[0])
|
402 | 405 | rightPolynomialJoints.remove(mtpJoints[1])
|
403 |
| - nPolynomialJoints = len(leftPolynomialJoints) |
| 406 | + # nPolynomialJoints = len(leftPolynomialJoints) |
404 | 407 |
|
405 | 408 | loadPolynomialData = False
|
406 | 409 | # Support loading/saving polynomial data such that they do not needed to
|
407 | 410 | # be recomputed every time.
|
408 |
| - if os.path.exists(os.path.join( |
409 |
| - pathModelFolder, |
410 |
| - '{}_polynomial_{}.npy'.format(modelName, 'r'))): |
| 411 | + if (os.path.exists( |
| 412 | + os.path.join(pathModelFolder, |
| 413 | + '{}_polynomial_{}.npy'.format(modelName, 'r'))) and |
| 414 | + os.path.exists( |
| 415 | + os.path.join(pathModelFolder, |
| 416 | + '{}_polynomial_{}.npy'.format(modelName, 'l')))): |
411 | 417 | loadPolynomialData = True
|
412 | 418 | from muscleData import getPolynomialData
|
413 |
| - polynomialData = getPolynomialData( |
| 419 | + polynomialData = {} |
| 420 | + |
| 421 | + polynomialData['r'] = getPolynomialData( |
| 422 | + loadPolynomialData, pathModelFolder, modelName, |
| 423 | + pathMotionFile4Polynomials, rightPolynomialJoints, |
| 424 | + rightSideMuscles[:-3], side='r') |
| 425 | + polynomialData['l'] = getPolynomialData( |
| 426 | + loadPolynomialData, pathModelFolder, modelName, |
| 427 | + pathMotionFile4Polynomials, leftPolynomialJoints, |
| 428 | + leftSideMuscles[:-3], side='l') |
| 429 | + polynomialData['trunk'] = getPolynomialData( |
414 | 430 | loadPolynomialData, pathModelFolder, modelName,
|
415 |
| - pathMotionFile4Polynomials, rightPolynomialJoints, muscles, side='r') |
| 431 | + pathMotionFile4Polynomials, trunkPolynomialJoints, trunkMuscles, |
| 432 | + side='trunk') |
416 | 433 | if loadPolynomialData:
|
417 |
| - polynomialData = polynomialData.item() |
| 434 | + polynomialData['r'] = polynomialData['r'].item() |
| 435 | + polynomialData['l'] = polynomialData['l'].item() |
| 436 | + polynomialData['trunk'] = polynomialData['trunk'].item() |
418 | 437 |
|
419 | 438 | # The function f_polynomial takes as inputs joint positions and velocities
|
420 | 439 | # from one side (trunk included), and returns muscle-tendon lengths,
|
421 | 440 | # velocities, and moments for the muscle of that side (trunk included).
|
422 |
| - f_polynomial = polynomialApproximation(muscles, polynomialData, |
423 |
| - nPolynomialJoints) |
| 441 | + f_polynomial = {} |
| 442 | + f_polynomial['r'] = polynomialApproximation( |
| 443 | + rightSideMuscles[:-3], polynomialData['r'], len(rightPolynomialJoints)) |
| 444 | + f_polynomial['l'] = polynomialApproximation( |
| 445 | + leftSideMuscles[:-3], polynomialData['l'], len(rightPolynomialJoints)) |
| 446 | + f_polynomial['trunk'] = polynomialApproximation( |
| 447 | + trunkMuscles, polynomialData['trunk'], len(trunkPolynomialJoints)) |
424 | 448 | leftPolJointIdx = getJointIndices(joints, leftPolynomialJoints)
|
425 | 449 | rightPolJointIdx = getJointIndices(joints, rightPolynomialJoints)
|
| 450 | + trunkPolJointIdx = getJointIndices(joints, trunkPolynomialJoints) |
426 | 451 |
|
427 |
| - # The left and right polynomialMuscleIndices below are used to identify |
428 |
| - # the left and right muscles in the output of f_polynomial. Since |
429 |
| - # f_polynomial return data from side muscles (trunk included), we have the |
430 |
| - # side leg muscles + all trunk muscles as output. Here we make sure we |
431 |
| - # only include the side trunk muscles when identifying all side muscles. |
432 |
| - # This is pretty sketchy I know. |
433 |
| - rightPolMuscleIdx = [muscles.index(i) for i in rightSideMuscles] |
434 |
| - rightTrunkMuscles = ['ercspn_r', 'intobl_r', 'extobl_r'] |
435 |
| - leftTrunkMuscles = ['ercspn_l', 'intobl_l', 'extobl_l'] |
436 |
| - leftPolMuscleIdx = ( |
437 |
| - [muscles.index(i) for i in rightSideMuscles |
438 |
| - if i not in rightTrunkMuscles] + |
439 |
| - [muscles.index(i) for i in leftTrunkMuscles]) |
| 452 | + # Helper indices. |
| 453 | + sidePolMuscleIdx = [muscles.index(i) for i in rightSideMuscles[:-3]] |
| 454 | + leftTrunkPolMuscleIdx = [trunkMuscles.index(i) for i in leftTrunkMuscles] |
| 455 | + rightTrunkPolMuscleIdx = [trunkMuscles.index(i) for i in rightTrunkMuscles] |
440 | 456 | from utilities import getMomentArmIndices
|
441 | 457 | momentArmIndices = getMomentArmIndices(
|
442 | 458 | rightSideMuscles, leftPolynomialJoints, rightPolynomialJoints,
|
443 |
| - polynomialData) |
| 459 | + polynomialData['r']) |
| 460 | + for joint in trunkPolynomialJoints: |
| 461 | + momentArmIndices[joint] = getJointIndices(bothSidesMuscles, |
| 462 | + trunkMuscles) |
| 463 | + |
444 | 464 | trunkMomentArmPolynomialIndices = (
|
445 | 465 | [muscles.index(i) for i in leftTrunkMuscles] +
|
446 | 466 | [muscles.index(i) for i in rightTrunkMuscles])
|
|
453 | 473 | pathModelFolder, 'data4PolynomialFitting_{}.npy'.format(modelName))
|
454 | 474 | data4PolynomialFitting = np.load(path_data4PolynomialFitting,
|
455 | 475 | allow_pickle=True).item()
|
456 |
| - momentArms = testPolynomials( |
457 |
| - data4PolynomialFitting, rightPolynomialJoints, muscles, |
458 |
| - f_polynomial, polynomialData, momentArmIndices, |
459 |
| - trunkMomentArmPolynomialIndices) |
| 476 | + _ = testPolynomials(data4PolynomialFitting, rightPolynomialJoints, |
| 477 | + rightSideMuscles[:-3], f_polynomial['r'], |
| 478 | + polynomialData['r'], momentArmIndices) |
| 479 | + _ = testPolynomials(data4PolynomialFitting, leftPolynomialJoints, |
| 480 | + leftSideMuscles[:-3], f_polynomial['l'], |
| 481 | + polynomialData['l'], momentArmIndices) |
460 | 482 |
|
461 | 483 | # %% External function.
|
462 | 484 | # The external function is written in C++ and compiled as a library, which
|
|
901 | 923 | # Left side.
|
902 | 924 | Qsinj_l = Qskj_nsc[leftPolJointIdx, j+1]
|
903 | 925 | Qdsinj_l = Qdskj_nsc[leftPolJointIdx, j+1]
|
904 |
| - [lMTj_l, vMTj_l, dMj_l] = f_polynomial(Qsinj_l, Qdsinj_l) |
| 926 | + [lMTj_l, vMTj_l, dMj_l] = f_polynomial['l'](Qsinj_l, Qdsinj_l) |
905 | 927 | # Right side.
|
906 | 928 | Qsinj_r = Qskj_nsc[rightPolJointIdx, j+1]
|
907 | 929 | Qdsinj_r = Qdskj_nsc[rightPolJointIdx, j+1]
|
908 |
| - [lMTj_r, vMTj_r, dMj_r] = f_polynomial(Qsinj_r, Qdsinj_r) |
909 |
| - # Muscle-tendon lengths and velocities. |
910 |
| - lMTj_lr = ca.vertcat(lMTj_l[leftPolMuscleIdx], |
911 |
| - lMTj_r[rightPolMuscleIdx]) |
912 |
| - vMTj_lr = ca.vertcat(vMTj_l[leftPolMuscleIdx], |
913 |
| - vMTj_r[rightPolMuscleIdx]) |
| 930 | + [lMTj_r, vMTj_r, dMj_r] = f_polynomial['r'](Qsinj_r, Qdsinj_r) |
| 931 | + # Trunk. |
| 932 | + Qsinj_trunk = Qskj_nsc[trunkPolJointIdx, j+1] |
| 933 | + Qdsinj_trunk = Qdskj_nsc[trunkPolJointIdx, j+1] |
| 934 | + [lMTj_trunk, vMTj_trunk, dMj_trunk] = f_polynomial['trunk']( |
| 935 | + Qsinj_trunk, Qdsinj_trunk) |
| 936 | + # Muscle-tendon lengths and velocities. |
| 937 | + lMTj_lr = ca.vertcat(lMTj_l[sidePolMuscleIdx], |
| 938 | + lMTj_trunk[leftTrunkPolMuscleIdx], |
| 939 | + lMTj_r[sidePolMuscleIdx], |
| 940 | + lMTj_trunk[rightTrunkPolMuscleIdx]) |
| 941 | + vMTj_lr = ca.vertcat(vMTj_l[sidePolMuscleIdx], |
| 942 | + vMTj_trunk[leftTrunkPolMuscleIdx], |
| 943 | + vMTj_r[sidePolMuscleIdx], |
| 944 | + vMTj_trunk[rightTrunkPolMuscleIdx],) |
914 | 945 | # Moment arms.
|
915 | 946 | dMj = {}
|
916 | 947 | # Left side.
|
917 |
| - for joint in leftPolynomialJoints: |
| 948 | + for c_j, joint in enumerate(leftPolynomialJoints): |
918 | 949 | if ((joint != 'mtp_angle_l') and
|
919 | 950 | (joint != 'lumbar_extension') and
|
920 | 951 | (joint != 'lumbar_bending') and
|
921 | 952 | (joint != 'lumbar_rotation')):
|
922 |
| - dMj[joint] = dMj_l[momentArmIndices[joint], |
923 |
| - leftPolynomialJoints.index(joint)] |
| 953 | + dMj[joint] = dMj_l[momentArmIndices[joint], c_j] |
924 | 954 | # Right side.
|
925 |
| - for joint in rightPolynomialJoints: |
| 955 | + for c_j, joint in enumerate(rightPolynomialJoints): |
926 | 956 | if ((joint != 'mtp_angle_r') and
|
927 | 957 | (joint != 'lumbar_extension') and
|
928 | 958 | (joint != 'lumbar_bending') and
|
|
932 | 962 | # subtract by the number of side muscles.
|
933 | 963 | c_ma = [
|
934 | 964 | i - nSideMuscles for i in momentArmIndices[joint]]
|
935 |
| - dMj[joint] = dMj_r[c_ma, |
936 |
| - rightPolynomialJoints.index(joint)] |
| 965 | + dMj[joint] = dMj_r[c_ma, c_j] |
937 | 966 | # Trunk.
|
938 |
| - for joint in trunkJoints: |
939 |
| - dMj[joint] = dMj_l[trunkMomentArmPolynomialIndices, |
940 |
| - leftPolynomialJoints.index(joint)] |
| 967 | + for c_j, joint in enumerate(trunkJoints): |
| 968 | + dMj[joint] = dMj_trunk[:, c_j] |
941 | 969 |
|
942 | 970 | ###################################################################
|
943 | 971 | # Hill-equilibrium.
|
|
1462 | 1490 | # Left leg.
|
1463 | 1491 | Qsk_GC_l = Qs_GC_rad[leftPolJointIdx, k]
|
1464 | 1492 | Qdsk_GC_l = Qds_GC_rad[leftPolJointIdx, k]
|
1465 |
| - [lMTk_GC_l, vMTk_GC_l, _] = f_polynomial(Qsk_GC_l, Qdsk_GC_l) |
| 1493 | + [lMTk_GC_l, vMTk_GC_l, _] = f_polynomial['l'](Qsk_GC_l, Qdsk_GC_l) |
1466 | 1494 | # Right leg.
|
1467 | 1495 | Qsk_GC_r = Qs_GC_rad[rightPolJointIdx, k]
|
1468 | 1496 | Qdsk_GC_r = Qds_GC_rad[rightPolJointIdx, k]
|
1469 |
| - [lMTk_GC_r, vMTk_GC_r, _] = f_polynomial(Qsk_GC_r, Qdsk_GC_r) |
| 1497 | + [lMTk_GC_r, vMTk_GC_r, _] = f_polynomial['r'](Qsk_GC_r, Qdsk_GC_r) |
| 1498 | + # Trunk. |
| 1499 | + Qsk_GC_trunk = Qs_GC_rad[trunkPolJointIdx, k] |
| 1500 | + Qdsk_GC_trunk = Qds_GC_rad[trunkPolJointIdx, k] |
| 1501 | + [lMTk_GC_trunk, vMTk_GC_trunk, _] = f_polynomial['trunk']( |
| 1502 | + Qsk_GC_trunk, Qdsk_GC_trunk) |
1470 | 1503 | # Both leg.
|
1471 |
| - lMTk_GC_lr = ca.vertcat(lMTk_GC_l[leftPolMuscleIdx], |
1472 |
| - lMTk_GC_r[rightPolMuscleIdx]) |
1473 |
| - vMTk_GC_lr = ca.vertcat(vMTk_GC_l[leftPolMuscleIdx], |
1474 |
| - vMTk_GC_r[rightPolMuscleIdx]) |
| 1504 | + lMTk_GC_lr = ca.vertcat(lMTk_GC_l[sidePolMuscleIdx], |
| 1505 | + lMTk_GC_trunk[leftTrunkPolMuscleIdx], |
| 1506 | + lMTk_GC_r[sidePolMuscleIdx], |
| 1507 | + lMTk_GC_trunk[rightTrunkPolMuscleIdx]) |
| 1508 | + vMTk_GC_lr = ca.vertcat(vMTk_GC_l[sidePolMuscleIdx], |
| 1509 | + vMTk_GC_trunk[leftTrunkPolMuscleIdx], |
| 1510 | + vMTk_GC_r[sidePolMuscleIdx], |
| 1511 | + vMTk_GC_trunk[rightTrunkPolMuscleIdx]) |
1475 | 1512 |
|
1476 | 1513 | ###################################################################
|
1477 | 1514 | # Derive Hill-equilibrium.
|
|
1621 | 1658 | # Left leg.
|
1622 | 1659 | Qsinj_opt_l = Qskj_opt_nsc[leftPolJointIdx, j+1]
|
1623 | 1660 | Qdsinj_opt_l = Qdskj_opt_nsc[leftPolJointIdx, j+1]
|
1624 |
| - [lMTj_opt_l, vMTj_opt_l, _] = f_polynomial(Qsinj_opt_l, |
| 1661 | + [lMTj_opt_l, vMTj_opt_l, _] = f_polynomial['l'](Qsinj_opt_l, |
1625 | 1662 | Qdsinj_opt_l)
|
1626 | 1663 | # Right leg.
|
1627 | 1664 | Qsinj_opt_r = Qskj_opt_nsc[rightPolJointIdx, j+1]
|
1628 | 1665 | Qdsinj_opt_r = Qdskj_opt_nsc[rightPolJointIdx, j+1]
|
1629 |
| - [lMTj_opt_r, vMTj_opt_r, _] = f_polynomial(Qsinj_opt_r, |
| 1666 | + [lMTj_opt_r, vMTj_opt_r, _] = f_polynomial['r'](Qsinj_opt_r, |
1630 | 1667 | Qdsinj_opt_r)
|
| 1668 | + # Trunk. |
| 1669 | + Qsinj_opt_trunk = Qskj_opt_nsc[trunkPolJointIdx, j+1] |
| 1670 | + Qdsinj_opt_trunk = Qdskj_opt_nsc[trunkPolJointIdx, j+1] |
| 1671 | + [lMTj_opt_trunk, vMTj_opt_trunk, _] = f_polynomial['trunk']( |
| 1672 | + Qsinj_opt_trunk, Qdsinj_opt_trunk) |
1631 | 1673 | # Both legs .
|
1632 |
| - lMTj_opt_lr = ca.vertcat(lMTj_opt_l[leftPolMuscleIdx], |
1633 |
| - lMTj_opt_r[rightPolMuscleIdx]) |
1634 |
| - vMTj_opt_lr = ca.vertcat(vMTj_opt_l[leftPolMuscleIdx], |
1635 |
| - vMTj_opt_r[rightPolMuscleIdx]) |
| 1674 | + lMTj_opt_lr = ca.vertcat( |
| 1675 | + lMTj_opt_l[sidePolMuscleIdx], |
| 1676 | + lMTj_opt_trunk[leftTrunkPolMuscleIdx], |
| 1677 | + lMTj_opt_r[sidePolMuscleIdx], |
| 1678 | + lMTj_opt_trunk[rightTrunkPolMuscleIdx]) |
| 1679 | + vMTj_opt_lr = ca.vertcat( |
| 1680 | + vMTj_opt_l[sidePolMuscleIdx], |
| 1681 | + vMTj_opt_trunk[leftTrunkPolMuscleIdx], |
| 1682 | + vMTj_opt_r[sidePolMuscleIdx], |
| 1683 | + vMTj_opt_trunk[rightTrunkPolMuscleIdx],) |
1636 | 1684 |
|
1637 | 1685 | ###############################################################
|
1638 | 1686 | # Derive Hill-equilibrium.
|
|
0 commit comments