1%createActuatorsFile   make and Print an OpenSim Actuator File from a Model
2%
3%  createActuatorsFile makes a template actuators file that can
4%  be used in Static Optimization, RRA and CMC. This identifies the
5%  coordinates that are connected to ground and places point or torque
6%  actuators on translational or rotational coordinates, respectively. All
7%  other coordiantes will get coordinate actuators. Any constrained
8%  coordinates will be ignored.
9
10% ----------------------------------------------------------------------- %
11% The OpenSim API is a toolkit for musculoskeletal modeling and           %
12% simulation. See http://opensim.stanford.edu and the NOTICE file         %
13% for more information. OpenSim is developed at Stanford University       %
14% and supported by the US National Institutes of Health (U54 GM072970,    %
15% R24 HD065690) and by DARPA through the Warrior Web program.             %
16%                                                                         %
17% Copyright (c) 2005-2016 Stanford University and the Authors             %
18% Author(s): James Dunne                                                  %
19%                                                                         %
20% Licensed under the Apache License, Version 2.0 (the "License");         %
21% you may not use this file except in compliance with the License.        %
22% You may obtain a copy of the License at                                 %
23% http://www.apache.org/licenses/LICENSE-2.0.                             %
24%                                                                         %
25% Unless required by applicable law or agreed to in writing, software     %
26% distributed under the License is distributed on an "AS IS" BASIS,       %
27% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or         %
28% implied. See the License for the specific language governing            %
29% permissions and limitations under the License.                          %
30% ----------------------------------------------------------------------- %
31
32% Author: James Dunne, Tom Uchida, Chris Dembia,
33% Ajay Seth, Ayman Habib, Shrinidhi K. Lakshmikanth, Jen Hicks.
34
35function createActuatorsFile(varargin)
36
37% Import OpenSim Libraries
38import org.opensim.modeling.*
39
40if isempty(varargin)
41    % open dialog boxes to select the model
42    [filename, pathname] = uigetfile('*.osim', 'Select an OpenSim Model File');
43elseif nargin == 1
44    if exist(varargin{1}, 'file') == 2
45        [pathname,filename,ext] = fileparts(varargin{1});
46        filename = [filename ext];
47    else
48        error(['Input file is invalid or does not exist']);
49    end
50else
51    error(['Number of inputs is > 1. Function only takes a single filepath']);
52end
53
54% get the model path
55modelFilePath = fullfile(pathname,filename);
56
57% Generate an instance of the model
58model = Model(modelFilePath);
59
60% Get the number of coordinates  and a handle to the coordainte set
61nCoord = model.getCoordinateSet.getSize();
62coordSet = model.getCoordinateSet();
63
64% Create some empty vec3's for later.
65massCenter = Vec3();
66axisValues = Vec3();
67
68% Create an empty Force set
69forceSet = ForceSet();
70
71% Create the underlying computational System and return a handle to the State
72state = model.initSystem();
73
74optimalForce = 1;
75
76%% Start going through the coordinates, creating an actuator for each
77for iCoord = 0 : nCoord - 1
78
79    % get a reference to the current coordinate
80    coordinate = coordSet.get(iCoord);
81    % If the coodinate is constrained (locked or prescribed), don't
82    % add an actuator
83    if coordinate.isConstrained(state)
84        continue
85    end
86
87    % get the joint, parent and child names for the coordiante
88    joint = coordinate.getJoint();
89    parentName = joint.getParentFrame().getName();
90    childName = joint.getChildFrame().getName();
91
92    % If the coordinates parent body is connected to ground, we need to
93    % add residual actuators (torque or point).
94    if strcmp(parentName, model.getGround.getName() )
95
96        % Custom and Free Joints have three translational and three
97        % rotational coordinates.
98        if strcmp(joint.getConcreteClassName(), 'CustomJoint') | strcmp(joint.getConcreteClassName(), 'FreeJoint')
99               % get the coordainte motion type
100               motion = char(coordinate.getMotionType());
101               % to get the axis value for the coordinate, we need to drill
102               % down into the coordinate transform axis
103               eval(['concreteJoint = ' char(joint.getConcreteClassName()) '.safeDownCast(joint);'])
104               sptr = concreteJoint.getSpatialTransform();
105               for ip = 0 : 5
106                  if strcmp(char(sptr.getCoordinateNames().get(ip)), char(coordinate.getName))
107                        sptr.getTransformAxis(ip).getAxis(axisValues);
108                        break
109                  end
110               end
111
112
113               % make a torque actuator if a rotational coordinate
114               if strcmp(motion, 'Rotational')
115                   newActuator = TorqueActuator(joint.getParentFrame(),...
116                                         joint.getParentFrame(),...
117                                         axisValues);
118
119               % make a point actuator if a translational coordinate.
120             elseif strcmp(motion, 'translational')
121                    % make a new Point actuator
122                    newActuator = PointActuator();
123                    % set the body
124                    newActuator.set_body(char(joint.getChildFrame().getName()))
125                    % set point that forces acts at
126                    newActuator.set_point(massCenter)
127                    % the point is expressed in the local
128                    newActuator.set_point_is_global(false)
129                    % set the direction that actuator will act in
130                    newActuator.set_direction(axisValues)
131                    % the force is expressed in the global
132                    newActuator.set_force_is_global(true)
133              else % something else that we don't support right now
134                    newActuator = CoordinateActuator();
135              end
136        else % if the joint type is not free or custom, just add coordinate actuators
137                % make a new coordinate actuator for that coordinate
138                newActuator = CoordinateActuator();
139        end
140
141    else % the coordinate is not connected to ground, and can just be a
142         % coordinate actuator.
143         newActuator = CoordinateActuator( char(coordinate.getName) );
144    end
145
146    % set the optimal force for that coordinate
147    newActuator.setOptimalForce(optimalForce);
148    % set the actuator name
149    newActuator.setName( coordinate.getName() );
150    % set min and max controls
151    newActuator.setMaxControl(Inf)
152    newActuator.setMinControl(-Inf)
153
154    % append the new actuator onto the empty force set
155    forceSet.cloneAndAppend(newActuator);
156end
157
158%% get the parts of the file path
159[pathname,filename,ext] = fileparts(modelFilePath);
160% define the new print path
161printPath = fullfile(pathname, [filename '_actuators.xml']);
162% print the actuators xml file
163forceSet.print(printPath);
164% Display printed file
165display(['Printed actuators to ' printPath])
166
167end
168