Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:
  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

How does the identity tracking/rebustness system work?

arthur_petersarthur_peters Member Posts: 19 ✭✭
I'm having a lot of trouble tracking entities through operations (which I need to do since I'm implementing a feature that performs split and transform operations). Each function related to tracking and queries has some documentation, however I was unable to find any documentation to tie it together so I can understand the system as a whole and really predict what it will do if I write any given code. So here is my understanding and then a bunch of questions. If people can correct me and/or answer my questions that would be great. And I hope the Onshape folks can improve the documentation based on this. I think a section on the tracking system as a whole would really help writing more complex features. I'm not looking for a "how-to" answer here. I'm looking to understand the semantics of entity tracking, so I need abstract descriptions.

OnShape's system for tracking entity identity has two components visible from Featurescript and one(-ish) visible from the part studio:
  1. Featurescript functions to provide Onshape with tracking information: setExternalDisambiguation, unstableIdComponent
  2. Featurescript functions to track entities through operations: startTrackingstartTrackingIdentity, makeRobustQuery, makeRobustQueriesBatched
  3. Features can take entities as parameters and those query specifications are robust to changes in previous features (as long as the features involved use #1 above correctly)
I think there are 3 ways a query can integrate with this system:
  • Robust queries always select by "identity".
  • Tracking queries select "new" entities that are created from existing entities.
  • Transient queries do not track at all and become invalid (evaluate an undefined set of entities) if anything is changed.
I think the selections the user does in the part studio are Robust in the sense above and therefor query parameters to features are also robust in this sense. Most query constructors are evaluated everytime they are used, so they will not be stable (their results will change), but will continue to be valid in the sense that they will contain all entities they should. The main exception is evaluateQuery which generates transient queries. Any query which is based on another transient query is also transient.

Questions

  1. What is entity identity? How is it transferred? Is it a single linage for each identity or is it a tree?
  2. What exactly to tracking queries do and how do the two kinds differ?
  3. What does setExternalDisambiguation do with respect to the concepts we are talking about here? Does it allow identity to be transferred through an otherwise unstable operation and if so how?
  4. I was able to track an object through a series of split operations with qUnion(startTracking(context, references1), makeRobustQuery(context, references1)). What exactly does this do? And why is both startTracking and makeRobustQuery apparently needed to pick up all elements resulting form breaking up the object? (If I don't include both parts, I seem to lose entities in some cases, and I cannot figure out the specific situations that cause it.)
  5. I created a test document to play with this and I while I wasn't able to create a good "minimal example" I did find one case that I cannot explain: https://cad.onshape.com/documents/59879a597ac78c2818ccc58b/w/acd9932bed67765dd5050341/e/e0890c6397964303c0914c94 The feature fails despite the user of makeRobustQuery. If I remove all the messing with the queries everything works fine. How is the parameter query different from a robust query created in the FeatureScript?

I know this is a lot. However, it's all interconnected so I thought talking about it together would be more effective than trying to split it up and only getting "how-to" answers, which is not what I want.

Thanks!!!






- Arthur (he/him)

Best Answers

  • Alex_KempenAlex_Kempen Member Posts: 248 EDU
    Answer ✓
    I am not intimately familiar with all of the methods used to give features robustness, but I can shed some light on setExternalDisambiguation and unstableIdComponent in particular.

    Here's an example of feature behavior when disambiguation is disabled. When an entity is deselected, the last mate connector always breaks as the id of each transform "shifts" up one, and the mate connectors jump around since each is referencing the underlying geometry, which is now shifted. If you consider how the code iterates through definition.locations, and what happens when an entity early on in definition.locations is deleted, this behavior should make some sense.

    Here's the same test but with disambiguation enabled. As you can see, the cylinder is now tied to the underlying sketch entity, so deleting any specific selection breaks only the corresponding mate connector. The references are also now stable, so the mate connectors do not "shift" unexpectedly to a different hole.

    The code for this example can be found here:
    https://cad.onshape.com/documents/4c21d0c3c89c0a81aadfdac6/w/a7ccf556a74ce09cd04151e0/e/e7738fbfea52f4fd375e07f9

    In brief, setExternalDisambiguation can be thought of as tying the specific unstableIdComponent to a specific query selection. So long as that specific query selection is present, the operations performed using that unstableIdComponent will behave expectedly. If the query is deleted or otherwise changes, its deletion will not affect other unstableIdComponents, as those ids are tied to different queries and thus are not affected.

    You might also find some value in this old thread I made which has a few helpful tips from @lana:
    https://forum.onshape.com/discussion/14827/difference-between-make-robust-query-and-set-external-disambiguation

    Hopefully, others can help fill in the gaps I'm not able to help with at this point in time - I would also love to learn more about makeRobustQuery and tracking queries in general.
    CS Student at UT Dallas
    Alex.Kempen@utdallas.edu
    Check out my FeatureScripts here:



  • lanalana Onshape Employees Posts: 706
    edited October 2021 Answer ✓
    @arthur_peters
    Answering 
    The documentation says that unstable Ids are treated as wildcards. What does that mean? Is a.*3 treated as qNthElement(qCreatedBy(a), 3) in queries? Or does it just get all children of a?
    first:
    If geometry produced by a.*3 operation is referenced by a downstream feature, we will consider topology produced by all operations with ids of format a.*<X>. E.g. geometry produced by operations a.*1 and a.*2  will be considered, but geometry produced by a.b will not. 
  • lanalana Onshape Employees Posts: 706
    Answer ✓

    1. What is entity identity? How is it transferred? Is it a single linage for each identity or is it a tree?
    Identity in Feature Script documentation is not a specific Onshape concept. It is what you would think of as the same piece of topology even if it is modified by several Onshape features. e.g. take a box and cut a hole starting at the top face. You will think of the top face identity as remaining the same,  however the face was modified and its transient id changed.  If you want to track the top face through this operation you can use startTrackingIdentity, if you want to track a particular face of the block and don't know if the hole affects it or not, use makeRobustQuery. The short answer is - it is a single lineage. If the block is cut so that the top face is split, its identity disappears. You can use startTracking to track the results of the split.
     

Answers

  • Alex_KempenAlex_Kempen Member Posts: 248 EDU
    Answer ✓
    I am not intimately familiar with all of the methods used to give features robustness, but I can shed some light on setExternalDisambiguation and unstableIdComponent in particular.

    Here's an example of feature behavior when disambiguation is disabled. When an entity is deselected, the last mate connector always breaks as the id of each transform "shifts" up one, and the mate connectors jump around since each is referencing the underlying geometry, which is now shifted. If you consider how the code iterates through definition.locations, and what happens when an entity early on in definition.locations is deleted, this behavior should make some sense.

    Here's the same test but with disambiguation enabled. As you can see, the cylinder is now tied to the underlying sketch entity, so deleting any specific selection breaks only the corresponding mate connector. The references are also now stable, so the mate connectors do not "shift" unexpectedly to a different hole.

    The code for this example can be found here:
    https://cad.onshape.com/documents/4c21d0c3c89c0a81aadfdac6/w/a7ccf556a74ce09cd04151e0/e/e7738fbfea52f4fd375e07f9

    In brief, setExternalDisambiguation can be thought of as tying the specific unstableIdComponent to a specific query selection. So long as that specific query selection is present, the operations performed using that unstableIdComponent will behave expectedly. If the query is deleted or otherwise changes, its deletion will not affect other unstableIdComponents, as those ids are tied to different queries and thus are not affected.

    You might also find some value in this old thread I made which has a few helpful tips from @lana:
    https://forum.onshape.com/discussion/14827/difference-between-make-robust-query-and-set-external-disambiguation

    Hopefully, others can help fill in the gaps I'm not able to help with at this point in time - I would also love to learn more about makeRobustQuery and tracking queries in general.
    CS Student at UT Dallas
    Alex.Kempen@utdallas.edu
    Check out my FeatureScripts here:



  • arthur_petersarthur_peters Member Posts: 19 ✭✭
    Thanks!!! This does verify some of my expectations. And helps a lot in my understanding why forEachEntity works the way it does.

    I take it from what you said that setExternalDisambiguation is conceptually replacing the unstable component of the Id with some identifier of the entities referenced by the query. I'm assuming it doesn't store the query since then if the query was invalidated by a change the maintained identity the tracking would break. By storing the identifier of the entities you are at least robust to identity preserving changes.

    I do have to wonder why the API is indirect like this instead of just allowing queries to be evaluated and added to an Id with some append_entity operation on Id. It seems like it would be clearer.

    - Arthur (he/him)
  • arthur_petersarthur_peters Member Posts: 19 ✭✭
    Oh I do have one question about unstable Ids:

    The documentation says that unstable Ids are treated as wildcards. What does that mean? Is a.*3 treated as qNthElement(qCreatedBy(a), 3) in queries? Or does it just get all children of a?
    - Arthur (he/him)
  • lanalana Onshape Employees Posts: 706
    edited October 2021 Answer ✓
    @arthur_peters
    Answering 
    The documentation says that unstable Ids are treated as wildcards. What does that mean? Is a.*3 treated as qNthElement(qCreatedBy(a), 3) in queries? Or does it just get all children of a?
    first:
    If geometry produced by a.*3 operation is referenced by a downstream feature, we will consider topology produced by all operations with ids of format a.*<X>. E.g. geometry produced by operations a.*1 and a.*2  will be considered, but geometry produced by a.b will not. 
  • lanalana Onshape Employees Posts: 706
    @Alex_Kempen
    Thank you for a good illustration of setExternalDisambiguation use.
  • lanalana Onshape Employees Posts: 706
    Answer ✓

    1. What is entity identity? How is it transferred? Is it a single linage for each identity or is it a tree?
    Identity in Feature Script documentation is not a specific Onshape concept. It is what you would think of as the same piece of topology even if it is modified by several Onshape features. e.g. take a box and cut a hole starting at the top face. You will think of the top face identity as remaining the same,  however the face was modified and its transient id changed.  If you want to track the top face through this operation you can use startTrackingIdentity, if you want to track a particular face of the block and don't know if the hole affects it or not, use makeRobustQuery. The short answer is - it is a single lineage. If the block is cut so that the top face is split, its identity disappears. You can use startTracking to track the results of the split.
     
  • arthur_petersarthur_peters Member Posts: 19 ✭✭
    lana said:

    1. What is entity identity? How is it transferred? Is it a single linage for each identity or is it a tree?
    Identity in Feature Script documentation is not a specific Onshape concept. It is what you would think of as the same piece of topology even if it is modified by several Onshape features. e.g. take a box and cut a hole starting at the top face. You will think of the top face identity as remaining the same,  however the face was modified and its transient id changed.  If you want to track the top face through this operation you can use startTrackingIdentity, if you want to track a particular face of the block and don't know if the hole affects it or not, use makeRobustQuery. The short answer is - it is a single lineage. If the block is cut so that the top face is split, its identity disappears. You can use startTracking to track the results of the split.
     

    This!!! This is the critical explanation I needed.
    • Identity is linear (not branching)
    • startTrackingIdentity tracks identity through a specific set of operations over a limited time. If API naming is consistent then this query will only include entities that really were updated, not those that were unchanged.
    • makeRobustQuery tracks identity in general ignoring the changed vs unchanged difference.
    • startTracking tracks dependencies which can be thought of as a branching generalization identities.
    As a side note, it sounds like startTracking and qDependency are very closely related. qDependency is the reverse of startTracking in a way, given that if you use startTracking on a query, then qDependency on the result of tracking would return something similar to the original query.


    - Arthur (he/him)
Sign In or Register to comment.