Movable axis of rotation (joint center)

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
POST REPLY
User avatar
Michael McGeehan
Posts: 6
Joined: Wed Feb 07, 2018 2:41 pm

Movable axis of rotation (joint center)

Post by Michael McGeehan » Wed Mar 27, 2019 2:19 pm

Hello,

I am working on a project in which I am attempting to model variable joint stiffness through variable joint location (i.e. moving the axis of rotation relative to the point of force application). Currently, I have proximal and distal bodies connected by a custom joint with a CoordinateLimitForce to model joint stiffness. However, when I translate the joint, the distal body moves as well. I would like to be able to translate the joint, while maintaining constant body locations. Is it possible to translate the axis of rotation (joint center) without also translating the distal body?

Thank you in advance.

Tags:

User avatar
jimmy d
Posts: 1375
Joined: Thu Oct 04, 2007 11:51 pm

Re: Movable axis of rotation (joint center)

Post by jimmy d » Tue Apr 16, 2019 7:23 am

You could add an intermediate, massless, body that is connected by freejoint.

User avatar
Michael McGeehan
Posts: 6
Joined: Wed Feb 07, 2018 2:41 pm

Re: Movable axis of rotation (joint center)

Post by Michael McGeehan » Tue Apr 23, 2019 2:16 pm

Hi James,

Thanks for the reply. This was ultimately the setup that I settled on. Currently, I have proximal and distal bodies (foot1 and foot2, respectively) connected via a PinJoint. I've added an intermediate massless body (fulcrum) that translates in the foot1 frame via a FreeJoint. However, I'm still having trouble decoupling the translation of foot2 and the fulcrum, presumably due to the ownership of foot2 by the fulcrum. I can move foot2 independently of the fulcrum, but not vice versa. I need foot2 to rotate with respect the movable fulcrum, but still transmit force to foot1. Do you have any tips or clarifications on how to accomplish this? I've attached a code snippet below if that is helpful.

Thanks for your help.

Code: Select all

                <FreeJoint name="fulcrum_FJ">
					<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The parent frame for the joint.).-->
					<socket_parent_frame_connectee_name>../foot1</socket_parent_frame_connectee_name>
					<!--Path to a Component that satisfies the Socket 'child_frame' of type PhysicalFrame (description: The child frame for the joint.).-->
					<socket_child_frame_connectee_name>../fulcrum</socket_child_frame_connectee_name>
					<!--List containing the generalized coordinates (q's) that parameterize this joint.-->
					<coordinates>
						<Coordinate name="fulcrum_xRotation">
							<!--The value of this coordinate before any value has been set. Rotational coordinate value is in radians and Translational in meters.-->
							<default_value>0</default_value>
							<!--The speed value of this coordinate before any value has been set. Rotational coordinate value is in rad/s and Translational in m/s.-->
							<default_speed_value>0</default_speed_value>
							<!--The minimum and maximum values that the coordinate can range between. Rotational coordinate range in radians and Translational in meters.-->
							<range>-1.5708 1.5708</range>
							<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
							<clamped>false</clamped>
							<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
							<locked>false</locked>
							<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
							<prescribed_function />
						</Coordinate>
						<Coordinate name="fulcrum_yRotation">
							<!--The value of this coordinate before any value has been set. Rotational coordinate value is in radians and Translational in meters.-->
							<default_value>0</default_value>
							<!--The speed value of this coordinate before any value has been set. Rotational coordinate value is in rad/s and Translational in m/s.-->
							<default_speed_value>0</default_speed_value>
							<!--The minimum and maximum values that the coordinate can range between. Rotational coordinate range in radians and Translational in meters.-->
							<range>-1.5708 1.5708</range>
							<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
							<clamped>false</clamped>
							<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
							<locked>false</locked>
							<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
							<prescribed_function />
						</Coordinate>
						<Coordinate name="fulcrum_zRotation">
							<!--The value of this coordinate before any value has been set. Rotational coordinate value is in radians and Translational in meters.-->
							<default_value>0</default_value>
							<!--The speed value of this coordinate before any value has been set. Rotational coordinate value is in rad/s and Translational in m/s.-->
							<default_speed_value>0</default_speed_value>
							<!--The minimum and maximum values that the coordinate can range between. Rotational coordinate range in radians and Translational in meters.-->
							<range>-1.5708 1.5708</range>
							<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
							<clamped>false</clamped>
							<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
							<locked>false</locked>
							<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
							<prescribed_function />
						</Coordinate>
						<Coordinate name="fulcrum_tx">
							<!--The value of this coordinate before any value has been set. Rotational coordinate value is in radians and Translational in meters.-->
							<default_value>0</default_value>
							<!--The speed value of this coordinate before any value has been set. Rotational coordinate value is in rad/s and Translational in m/s.-->
							<default_speed_value>0</default_speed_value>
							<!--The minimum and maximum values that the coordinate can range between. Rotational coordinate range in radians and Translational in meters.-->
							<range>-1 1</range>
							<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
							<clamped>false</clamped>
							<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
							<locked>false</locked>
							<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
							<prescribed_function />
						</Coordinate>
						<Coordinate name="fulcrum_ty">
							<!--The value of this coordinate before any value has been set. Rotational coordinate value is in radians and Translational in meters.-->
							<default_value>0</default_value>
							<!--The speed value of this coordinate before any value has been set. Rotational coordinate value is in rad/s and Translational in m/s.-->
							<default_speed_value>0</default_speed_value>
							<!--The minimum and maximum values that the coordinate can range between. Rotational coordinate range in radians and Translational in meters.-->
							<range>-1 1</range>
							<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
							<clamped>false</clamped>
							<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
							<locked>false</locked>
							<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
							<prescribed_function />
						</Coordinate>
						<Coordinate name="fulcrum_tz">
							<!--The value of this coordinate before any value has been set. Rotational coordinate value is in radians and Translational in meters.-->
							<default_value>0</default_value>
							<!--The speed value of this coordinate before any value has been set. Rotational coordinate value is in rad/s and Translational in m/s.-->
							<default_speed_value>0</default_speed_value>
							<!--The minimum and maximum values that the coordinate can range between. Rotational coordinate range in radians and Translational in meters.-->
							<range>-1 1</range>
							<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
							<clamped>false</clamped>
							<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
							<locked>false</locked>
							<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
							<prescribed_function />
						</Coordinate>
					</coordinates>
                    <frames>
					</frames>
					<!--Physical offset frames owned by the Joint that are typically used to satisfy the owning Joint's parent and child frame connections (sockets). PhysicalOffsetFrames are often used to describe the fixed transformation from a Body's origin to another location of interest on the Body (e.g., the joint center). When the joint is deleted, so are the PhysicalOffsetFrame components in this list.-->
				</FreeJoint>
                <PinJoint name="foot_flex">
					<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The parent frame for the joint.).-->
					<socket_parent_frame_connectee_name>foot1_offset</socket_parent_frame_connectee_name>
					<!--Path to a Component that satisfies the Socket 'child_frame' of type PhysicalFrame (description: The child frame for the joint.).-->
					<socket_child_frame_connectee_name>foot2_offset</socket_child_frame_connectee_name>
					<!--List containing the generalized coordinates (q's) that parameterize this joint.-->
					<coordinates>
						<Coordinate name="foot_flex">
							<!--The value of this coordinate before any value has been set. Rotational coordinate value is in radians and Translational in meters.-->
							<default_value>0</default_value>
							<!--The speed value of this coordinate before any value has been set. Rotational coordinate value is in rad/s and Translational in m/s.-->
							<default_speed_value>0</default_speed_value>
							<!--The minimum and maximum values that the coordinate can range between. Rotational coordinate range in radians and Translational in meters.-->
							<range>-0.34906585000000001 0.34906585000000001</range>
							<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
							<clamped>true</clamped>
							<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
							<locked>true</locked>
							<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
							<prescribed_function />
							<!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.-->
							<prescribed>false</prescribed>
						</Coordinate>
					</coordinates>
					<!--Physical offset frames owned by the Joint that are typically used to satisfy the owning Joint's parent and child frame connections (sockets). PhysicalOffsetFrames are often used to describe the fixed transformation from a Body's origin to another location of interest on the Body (e.g., the joint center). When the joint is deleted, so are the PhysicalOffsetFrame components in this list.-->
				    <frames>
						<PhysicalOffsetFrame name="foot1_offset">
							<!--The geometry used to display the axes of this Frame.-->
							<FrameGeometry name="frame_geometry">
								<!--Path to a Component that satisfies the Socket 'frame' of type Frame.-->
								<socket_frame_connectee_name>..</socket_frame_connectee_name>
								<!--Path to an output (channel) to satisfy the one-value Input 'transform' of type SimTK::Transform (description: The transform that positions the Geometry in Ground so it can be positioned. Note, either the Geometry is attached to a Frame OR the input transform can be supplied, but not both. ).-->
								<input_transform_connectee_name></input_transform_connectee_name>
								<!--Scale factors in X, Y, Z directions respectively.-->
								<scale_factors>0.20000000000000001 0.20000000000000001 0.20000000000000001</scale_factors>
							</FrameGeometry>
							<!--Path to a Component that satisfies the Socket 'parent' of type C (description: The parent frame to this frame.).-->
							<socket_parent_connectee_name>../../foot1</socket_parent_connectee_name>
							<!--Translational offset (in meters) of this frame's origin from the parent frame's origin, expressed in the parent frame.-->
							<translation>-0.048770000000000001 0.041950000000000001 -0.00792</translation>
							<!--Orientation offset (in radians) of this frame in its parent frame, expressed as a frame-fixed x-y-z rotation sequence.-->
							<orientation>0 0 0</orientation>
						</PhysicalOffsetFrame>
						<PhysicalOffsetFrame name="foot2_offset">
							<!--The geometry used to display the axes of this Frame.-->
							<FrameGeometry name="frame_geometry">
								<!--Path to a Component that satisfies the Socket 'frame' of type Frame.-->
								<socket_frame_connectee_name>..</socket_frame_connectee_name>
								<!--Path to an output (channel) to satisfy the one-value Input 'transform' of type SimTK::Transform (description: The transform that positions the Geometry in Ground so it can be positioned. Note, either the Geometry is attached to a Frame OR the input transform can be supplied, but not both. ).-->
								<input_transform_connectee_name></input_transform_connectee_name>
								<!--Scale factors in X, Y, Z directions respectively.-->
								<scale_factors>0.20000000000000001 0.20000000000000001 0.20000000000000001</scale_factors>
							</FrameGeometry>
							<!--Path to a Component that satisfies the Socket 'parent' of type C (description: The parent frame to this frame.).-->
							<socket_parent_connectee_name>../../foot2</socket_parent_connectee_name>
							<!--Translational offset (in meters) of this frame's origin from the parent frame's origin, expressed in the parent frame.-->
							<translation>0 0 0</translation>
							<!--Orientation offset (in radians) of this frame in its parent frame, expressed as a frame-fixed x-y-z rotation sequence.-->
							<orientation>1.7681899999999999 -0.906223 1.8196000000000001</orientation>
						</PhysicalOffsetFrame>
					</frames>
				</PinJoint>

User avatar
anton kaniewski
Posts: 2
Joined: Thu Apr 22, 2021 1:47 am

Re: Movable axis of rotation (joint center)

Post by anton kaniewski » Thu Apr 22, 2021 6:04 am

Hello,

I am also interested about this topic.
Currently, I try to create a script to launch several Inverse Kinematics and see what will be the impact of the rotations axis's modification on the angles during the gait and RMSE.

Same problem than expose above:
"However, when I translate the joint, the distal body moves as well. I would like to be able to translate the joint, while maintaining constant body locations. Is it possible to translate the axis of rotation (joint center) without also translating the distal body" - from Michael McGeehan

I find the way to rotate the axis without changing the position of the distal body but not how to translate it.
For that, I change the different point in the transform axis with a rotation matrix depending and the angle modification expected.

Did you manage to do what you wanted to do Micheal ?
It's possible to adapt it with a script ?

Thanks you for your help !

User avatar
Michael McGeehan
Posts: 6
Joined: Wed Feb 07, 2018 2:41 pm

Re: Movable axis of rotation (joint center)

Post by Michael McGeehan » Thu Apr 22, 2021 8:53 am

Hi Anton,

Unfortunately, I never did find a good solution to this problem. The best solution I found was to create multiple models and simulate them independently. It's possible that a better solution exists in the more recent iterations of OpenSim. I ended up moving to an alternative simulation platform that allowed me to dynamically move joint centers.

Best of luck,

Michael

User avatar
Thomas Uchida
Posts: 1783
Joined: Wed May 16, 2012 11:40 am

Re: Movable axis of rotation (joint center)

Post by Thomas Uchida » Thu Apr 22, 2021 10:48 am

However, when I translate the joint, the distal body moves as well. I would like to be able to translate the joint, while maintaining constant body locations. Is it possible to translate the axis of rotation (joint center) without also translating the distal body
It sounds like you are trying to move a joint to a different location without also moving the distal bodies. You can do this by changing the location of the frame on the parent body by (dx,dy,dz) relative to the global frame and changing the location of the frame on the child body by (-dx,-dy,-dz) relative to the global frame.

User avatar
anton kaniewski
Posts: 2
Joined: Thu Apr 22, 2021 1:47 am

Re: Movable axis of rotation (joint center)

Post by anton kaniewski » Wed May 05, 2021 6:50 am

Hey,

Micheal, I am sorry to heard that but happy that you found a solution !
Unfortunately I have a high amount of rotation to change and test so it will not be possible for me if I cannot automatise it.
Thank you for your precious answer and your time !

Thomas, I think your solution seems to work !
I try only one of the both location frame but not the both in the same time.
I need to go futher into study to see if it's possible to use it.
Thank you a lot for you advice ! I think it will help me to continue.

Best of luck for you both,
Anton K

POST REPLY