solidworks_urdf_exporter
solidworks_urdf_exporter copied to clipboard
Overridden mass properties are not currently utilized by add-in
Due to limitations in the SolidWorks API, it is not currently possible to support overridden mass properties. This issue is meant to track the discussion related to this problem.
Have you got any good workarounds for this issue? Or do I just have to manually edit the .urdf file with the correct masses and intertias?
The only one that I can think of is to change the material of the component so that the mass and MoI matches the real world values. Often times, this means that you might have to choose a very strange material in order to get the appropriate values at the end.
@brawner Can you provide a link to the Solidworks API for the current mass properties you are pulling from and where in this code base this is being implemented? I'm just curious if anything can be done and am not too familiar with the Solidworks API or this repo yet and would appreciate a point in the right direction.
There are a couple of different APIs for getting the mass properties of a component. Here is an example utilizing the CreateMassProperty()
method, which is used for overridden properties. But it is currently only usable on a component level.
The organization of this code base could definitely use some better namespacing and organization, but these calculations are happening here. https://github.com/ros/solidworks_urdf_exporter/blob/master/SW2URDF/URDFExport/ExportHelperExtension.cs#L249-L303
The limitation is that the exporter lets you add multiple components to a link and it needs to get the properties of the combined sum of parts. It does not recognize overridden mass properties when you do that.
The limitation is that the exporter lets you add multiple components to a link and it needs to get the properties of the combined sum of parts. It does not recognize overridden mass properties when you do that.
Do you mean it can't handle situations where you override the mass of a group or selection of multiple parts? Or would an overridden mass of a single part also not work? I can see how the former would be difficult if not impossible to handle, while the latter seems like it could work easily enough.
I'm not sure what is happening in the background of swMass.Mass (i.e. how Solidworks is actually calculating the mass of each body you have added to this swMass object) but from the example code you sent it looks like they are able to read an overridden mass via the Mass property:
Debug.Print("OverrideMass property is set to " + MyMassProp.OverrideMass);
Debug.Print("Mass is overridden? " + MyMassProp.SetOverrideMassValue(100.0, (int)swInConfigurationOpts_e.swThisConfiguration, null));
val = MyMassProp.Mass;
For example if I have a single part for my link and I have overridden this single part's mass, are you saying that this would still pull the mass from the material properties rather than the overridden one?
The difference is that the method used in the exporter adds a bunch of bodies and then calculates the properties. The example I linked gets it from the solidworks model itself and doesn't add any bodies. When you add bodies, SW just ignores overridden properties unfortunately. As far as I've been able to figure out, it's just a limitation with their API. I would love to find a solution that incorporates overridden properties, but that may end up requiring a one-assembly-per-link type of workflow.
When you add bodies, SW just ignores overridden properties unfortunately.
I see. Do you know why this is? I'd think the Mass Properties dialog is using the AddBodies method when you select things in the model (otherwise it defaults to the entire assembly). Do you think they are doing something different in their GUI implementation?
For your code, is this inability due to something with how swMass.Mass is calculated internally or does the Body2 Interface just not contain any reference to the overridden mass, i.e. is this overridden mass property held in some higher parent object like the ModelDoc2?
Fundamentally, do you think the overridden mass double is stored in a separate parameter than the non-overridden one? It looks like they are one in the same according to the example code (i.e. when you override it, it overwrites the previous mass value, and does not keep track of the original value, but this would remained stored in the material properties), but maybe I am missing something.
It looks like the example is pulling this from a ModelDoc2 object created from the output of the OpenDoc6 method.
Side question: is there any rhyme or reason as to the numerical suffixes on the Soliworks API interfaces/methods (i.e. Body2, ModelDoc2 OpenDoc6)?
So it seems if you run the CreateMassProperty method on a ModelDoc2.Extension property, the resulting Mass property (e.g. MyMassProp.Mass) would have access or somehow be getting the overridden mass right? Have you actually run the example code and seen this to be the case? You are saying that if you simply included a line MyMassProp.AddBodies(someBody)
ths MyMassProp.Mass property would not longer be representative of the overridden mass they set via the SetOverrideMassValue() method?
If that is the case, then it seems you would need the ModelDoc2 object associated with each body so you can run CreateMassProperty directly on that rather than individual bodies. I could see at least two possible ways of obtaining the overridden masses from the Exporter:
- Find some way to access the ModelDoc2 object associated with each body in your bodies list and then pull the masses from those objects rather than the bodies themselves OR
- Rather than storing all Body2 objects to a List, store all the ModelDoc2 objects to a list (or store both).
The former would be a lot easier to adapt to your existing code, but I didn't see anything in the doc about accessing any parent information. I've never done any C# coding; is there any way to trace upwards to find parent objects up the ModelDoc2 or some other reference to the actual model from which the body originates? I saw a list of Component2 objects as well. Does this provide anything higher up like the ModelDoc2 reference?
Do you know why this is?
I don't work in the SolidWorks API regularly, so it's always possible that I miss something. However, after pouring through tutorials, documentation and forums, I have yet to find any suggested fix. The SW API and documentation often leaves me wanting.
do you think the overridden mass double is stored in a separate parameter than the non-overridden one
I have no strong ideas how SW does things internally. My strongest suspicion is that SW uses it's own internal API for its own features and supports the public API as a separate interface.
You are saying that if you simply included a line MyMassProp.AddBodies(someBody)
That is correct. Sometimes calling one function has undocumented and bewildering side affects on another. For example, instead of creating the mass property object once, adding bodies, and getting the mass, inertia and CoM in the same function, I do it separately. Last time I touched that code, calling getMass would cause the other function calls to be incorrect.
is there any rhyme or reason as to the numerical suffixes on the Soliworks API interfaces/methods
For backwards compatibility reasons, this is the approach they chose in their API. Instead of removing a function signature, they just increment the number.
You are saying that if you simply included a line MyMassProp.AddBodies(someBody) ths MyMassProp.Mass property would not longer be representative of the overridden mass they set via the SetOverrideMassValue() method?
That is the unfortunate truth. It always comes out as the non-overridden mass properties.
then it seems you would need the ModelDoc2 object associated with each body so you can run CreateMassProperty directly on that rather than individual bodies
This would require some trial and error, and I'm not entirely sure the ultimate result. Composing moment of inertias, masses and center of masses is doable, but the question I haven't looked into is how are MoIs and center of masses specified in the overridden properties. Is it clear to what reference frame they are taken?
The issue is that getting the MassProperties from a model doc (I believe) requires calling open on it, which is slow. Then when you get the mass properties from that model doc, it's properties are in reference to coordinate systems in that model document. Not impossible to handle, but this seems very error prone.
When looking at a modeldoc you can't go up in the tree, which has to do with SW model composability. Assembly documents know about its children, but the children model documents don't know about it's parents. You have to keep track of the tree yourself if you start getting information from within a model document.
Aye yai yai. Ok, understood.
I suppose it shouldn't surprise me that the API is just as finicky as the software itself. Thanks for the detailed run down. I guess my current conclusion is that it is easier to work with custom materials, and change the material density to match what is needed for the mass, rather than try to work around their API irregularities. If I ever feel otherwise I'll be sure to return here.
Interestingly it appears that if you run an export on an assembly with components that have mass properties overridden and your URDF export config contains an empty link, the empty link will assume the mass of the entire system with overridden properties included.
I haven't 100% verified this issue is causing my specific problem, but it would certainly impact me. Essentially my assembly mass totals ~47 kg, but if I sum the masses of the links (which all contain components with mass properties overridden) the sum of masses comes to ~40 kg. I'm fairly certain every component in my assy belongs to a link, so am heavily suspect this issue is the root cause. The two empty links pop out of the exporter at 47 kg when I think they should have 0 mass.
I wonder if investigating this behavior could provide some hints as to how to access overridden mass properties for other links.
I'm curious if there is a workaround for this problem (other than manually changing the mass parameter in the urdf file). By the way, this plugin is really useful!