API Example 1

From neuromechanicwiki
Jump to: navigation, search

This toy example demonstrates the use of most non-Tree API functions. A toy example that demonstrates the tree functions is found here.

The Tree Class in nmextension.py is used to traverse the trees in this example

  1. import os
  2. import neuromechanic as nm
  3. import nmextension as nme
  4.  
  5. directory = '... some directory to pendulum3control.nmcb ...'
  6. filetoload = 'pendulum3control.nmcb'
  7. filesaveas = 'pendulum3control_edited.nmcb'
  8. outputfilename = 'pendulum3control_edited.nmco'
  9. snapshot = 'pendulumsnapshot.gif'
  10.  
  11. # Print the current version
  12. print('The current Neuromechanic version is '+nm.version())
  13.  
  14. # Set both the python and Neuromechanic current working directories to the
  15. # path where a file that you want to load is located
  16. os.chdir(directory)
  17. nm.file_setsystempath(directory+'/'+filetoload)
  18.  
  19. # Load the file
  20. err = nm.file_load(filetoload)
  21. if err != 0:
  22.    print('Something went wrong loading the nmcb file')
  23. else:
  24.    # Find out what kind of model is loaded
  25.    modeltype = nm.file_modeltype()
  26.    if modeltype==0:
  27.       print('There is no model loaded.')
  28.    elif modeltype==1:
  29.       print('A body file (usually *.nmcb) has been loaded.')
  30.    elif modeltype==2:
  31.       print('An output file (usually *.nmco) has been loaded.')
  32.    else:
  33.       print('Zoinks, what happened?!')
  34.  
  35.    # Find out if an output name has been set
  36.    isoutputset = nm.file_isoutputfilenameset()
  37.    if isoutputset==0:
  38.       print('An output file name has NOT been set.')
  39.    else:
  40.       print('An output file name has been set.')
  41.  
  42.    # Save the loaded file to disk
  43.    saveas = nm.file_saveas(filesaveas)
  44.    if saveas==0:
  45.       print('You have saved the file as: '+filesaveas)
  46.    else:
  47.       print('We were NOT able to save the file.')
  48.  
  49.    # Re-draw all the viewports
  50.    nm.gui_renderall()
  51.  
  52.    # Take a snapshot of the viewports (*.gif or *.bmp)
  53.    nm.gui_snapshot(snapshot)
  54.  
  55.    # Check whether an error has been triggered, if it has clear it
  56.    err = nm.system_geterror()
  57.    if err != 0:
  58.       nm.system_clearerror()
  59.  
  60.    # Write a string to the log, notice
  61.    print('Notice the order that these things show up in the log window')
  62.    nm.system_log('Write a string to the log')
  63.    print('These two lines get printed together and the nm.system_log(...) line was earlier')
  64.    # The reason is that anything sent to nm.system_log(...) is processed "immediately" and 
  65.    # print commands are sent to a buffer and printed to the log after the function is complete
  66.  
  67.    # Really this should never be executed when the python script is operating as
  68.    # a SLAVE but can be run when it is operating as a MASTER
  69.    #nm.model_reloadpythonmodules()
  70.  
  71.    # nme.Tree is a class that makes it easier to traverse a Tree (such as the model 
  72.    # tree). Especially, if you already know the basic structure of the tree
  73.    nmtree = nme.Tree('model')
  74.  
  75.    # Retrieve the <BodyIndex> for the 3rd rigid body. Notice that the <BodyIndex> is 
  76.    # not the same as the order that the body shows up in the xml.
  77.    bodyindex = nmtree.NeuromechanicFile.Bodies.RigidBody[2].BodyIndex.x_
  78.    # Get the global position of the center of mass
  79.    # When the contents are a vector or matrix it is automatically cast to a numpy.array() type.
  80.    link1com = nmtree.NeuromechanicFile.Bodies.RigidBody[2].CenterOfMass.x_
  81.    print('The local position of the 3rd body is: ', link1com)
  82.  
  83.    # With the bodyindex and the local coordinates of a point you can calculate the 
  84.    # global coordinates of the point
  85.    link1com_global = nm.model_calclocaltoglobal(bodyindex,link1com.tolist())
  86.    print('The global position of the 3rd body is: ', link1com_global)
  87.  
  88.    # You can go back the other way from global to local as well.
  89.    link1com_local = nm.model_calcglobaltolocal(bodyindex,link1com_global)
  90.    print('Again, the local position of the 3rd body is: ', link1com_local)
  91.  
  92.    # You can also calculate the global velocity of a point on a body
  93.    link1com_globalv = nm.model_calcglobalvelocity(bodyindex,link1com_local)
  94.    print('The global velocity of the 3rd body is: ', link1com_globalv)
  95.  
  96.    # Calculate the kinematic Jacobian for a point
  97.    J,dJdq = nm.model_calcjacobian(bodyindex,link1com.tolist())
  98.    print('The kinematic Jacobian for the center of mass of the 3rd body is')
  99.    print(nme.np.array(J))
  100.    print('[d(Jacobian)/dt * dq/dt] for the center of mass of the 3rd body is')
  101.    print(dJdq)
  102.  
  103.    # You can move individual points by just changing their value in the model tree.
  104.    # However if you move JOINT CENTERS of a body then it affects the global position of all
  105.    # points on that body and the points on the children bodies.
  106.    # Now this may be what you want to do, but if it ISNT and you want to move a joint center
  107.    # without moving the global position of all the subsequent points use this:
  108.    link1com = nmtree.NeuromechanicFile.Bodies.RigidBody[2].CenterOfMass.x_
  109.    link1com_global = nm.model_calclocaltoglobal(bodyindex,link1com.tolist())
  110.    print('The global position of the center of mass of the 3rd body starts at : ', link1com_global)
  111.    link1JC_global = nmtree.NeuromechanicFile.Bodies.RigidBody[2].FrameLocation.x_
  112.    # Now move the joint center of the 3rd body
  113.    dx = nme.np.array([0.02,0.01,0.03])
  114.    print('Move the joint center of the third body')
  115.    nmtree.NeuromechanicFile.Bodies.RigidBody[2].FrameLocation.x_ = link1JC_global + dx
  116.    nm.model_refreshtreefromstate() # Makes sure the changes get propagated
  117.    link1com = nmtree.NeuromechanicFile.Bodies.RigidBody[2].CenterOfMass.x_
  118.    # Recalculate the center of mass position in global coordinates
  119.    link1com_global = nm.model_calclocaltoglobal(bodyindex,link1com.tolist())
  120.    print('The global position of the center of mass of the 3rd body has changed to : ', link1com_global)
  121.    # Now move the joint center of the 3rd body back
  122.    nmtree.NeuromechanicFile.Bodies.RigidBody[2].FrameLocation.x_ = link1JC_global
  123.    nm.model_refreshtreefromstate() # Makes sure the changes get propagated
  124.    link1com = nmtree.NeuromechanicFile.Bodies.RigidBody[2].CenterOfMass.x_
  125.    link1com_global = nm.model_calclocaltoglobal(bodyindex,link1com.tolist())
  126.    print('The global position of the center of mass of the 3rd body has moved back to : ', link1com_global)
  127.    nm.model_runmovejointcenter(bodyindex,dx.tolist())
  128.    nm.model_refreshtreefromstate() # Makes sure the changes get propagated
  129.    link1com = nmtree.NeuromechanicFile.Bodies.RigidBody[2].CenterOfMass.x_
  130.    link1com_global = nm.model_calclocaltoglobal(bodyindex,link1com.tolist())
  131.    print('Even though the joint center has moved, the global position of the center of mass of the 3rd body is still : ', link1com_global)
  132.  
  133.    # State information is actually stored in two places, with the element that the state is
  134.    # associated with (e.g. each rigid body states is stored in <RigidBody><DegreeOfFreedom><State>)
  135.    # and with the state vector stored in <Dynamic><ModelState>. If you change one and want those
  136.    # changes to propagate to the rest of the tree you should use nm.model_refreshstatefromtree()
  137.    # or nm.model_refreshtreefromstate() depending on where the change was made.
  138.    print('Initial states are:')
  139.    print(nmtree.NeuromechanicFile.Dynamic.ModelState.x_)
  140.    print(nmtree.NeuromechanicFile.Bodies.RigidBody[0].DegreeOfFreedom[0].State.x_)
  141.    print('Change the state in the <RigidBody> and refreshtreefromstate')
  142.    nmtree.NeuromechanicFile.Bodies.RigidBody[0].DegreeOfFreedom[0].State.x_ = [.333,0]
  143.    nm.model_refreshtreefromstate()
  144.    print(nmtree.NeuromechanicFile.Dynamic.ModelState.x_)
  145.    print(nmtree.NeuromechanicFile.Bodies.RigidBody[0].DegreeOfFreedom[0].State.x_)
  146.    print('Changes were lost!')
  147.    print('Again, change the state in the <RigidBody> but this time refreshstatefromtree')
  148.    nmtree.NeuromechanicFile.Bodies.RigidBody[0].DegreeOfFreedom[0].State.x_ = [.333,0]
  149.    nm.model_refreshstatefromtree()
  150.    print(nmtree.NeuromechanicFile.Dynamic.ModelState.x_)
  151.    print(nmtree.NeuromechanicFile.Bodies.RigidBody[0].DegreeOfFreedom[0].State.x_)
  152.    print('Changes are propagated!')
  153.  
  154.    # Notice that the invers of the inertia matrix is not calculated by default
  155.    print(nmtree.NeuromechanicFile.Dynamic.GenInertiaInverse.x_)
  156.    # To populate it you need to call
  157.    nm.model_calcinertiainverse()
  158.    print(nmtree.NeuromechanicFile.Dynamic.GenInertiaInverse.x_)
  159.  
  160.    # This is also true for dH/dt where H is the general momentum matrix H*dqdt = m*dxdt
  161.    nm.model_calcdmomentumdt()
  162.  
  163.    # This will satisfy position based motion constraints
  164.    nm.model_runsatisfyconstraints()
  165.  
  166.    # You can equilibrate the model with:
  167.    nm.model_runequilibrate()
  168.  
  169.    # This sets the <Origin> and <Rotation> elements of a <Polygon> so that <Points> defined in
  170.    # the <Polygon> are aligned with markers defined in the <RigidBody>... (need an example)
  171.    nm.model_runalignpolygons()
  172.  
  173.    # This will compress polygons to the nmcb file for smaller and self-contained files
  174.    nm.model_compresspolygons()
  175.  
  176.    # If there are <FeasibleForces> elements, populate them with this command
  177.    nm.model_runfeasibleforces()
  178.  
  179.    # These functions are mostly useful for the gui. Not demonstrated here         
  180.    # nm.model_playbackloadstate()
  181.    # nm.model_playbackreload()
  182.    # nm.model_simcountcurrent()
  183.    # nm.model_simcounttotal()
  184.    # nm.model_simgetrecoverstate()
  185.    # nm.model_simsetstatuspause()
  186.  
  187.    # Set the name of the output file to be written
  188.    nm.file_setoutputfilename(outputfilename)
  189.  
  190.    # Run a simulation. The GUI still doesn't play very nice with the python scripts
  191.    # so this may cause your gui to appear like it has hung up when it is actually processing
  192.    # check neuromechaniclog.txt to see whether it is still running
  193.    nm.model_simsetstatusstop()
  194.    nm.model_simstep()
  195.    while nm.model_simgetstatus()==1:
  196.       nm.model_simstep()
  197.       nm.system_log(str(nmtree.NeuromechanicFile.Dynamic.Time.x_)+\
  198.          ' of '+str(nmtree.NeuromechanicFile.Parameters.EndTime.x_))
  199.  
  200.  
  201.    # Clear the model
  202.    nm.model_clear()