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 do I get the position and orientation of a mate connector in a PartStudio using the REST API?

James_BordersJames_Borders Member Posts: 2 PRO
edited September 2021 in Community Support
I'd like to be able to query the "location" (position and orientation) of mate connectors in both PartStudios and Assemblies. I believe I know how to do this for assemblies. However, it seems much different for PartStudios. I am able to "see" mate connectors in a PartStudio using the "Get Feature List" API call, however, the information returned in that result is not very direct. That is, it essentially tells me how the user created the mate connector (e.g. what the user chose in the mate connector dialog, like the origin entity, whether to realign or move, and by how much). I suppose it's possible for me to compute the mate connector's location by parsing out, for example, the geometry ID in the "originQuery" and then making some other API call to get the details of that geometry, but I'm guessing (hoping) there's a more direct way to do this.

I currently have what seems like a hacky solution to this, which uses an "Evaluate FeatureScript" API call to pull out the mate connector's location info, but this can't be the best or right way to do this. To give a little more context, in my hacky solution below, I'm really interested in the location of one mate connector (specified by its feature ID) relative to another mate connector (specified by the "base_feature_id" argument):
def get_mate_connector_info(onshape, document_id, workspace_id, element_id,
                            base_feature_id, feature_id):
  '''
  Get mate connector info.
  '''
  print("GetMateConnectorInfo")
  path = (f'/api/partstudios/d/{document_id}/w/{workspace_id}/'
          f'e/{element_id}/featurescript')
  body = {
      "script": f'''
function(context is Context, queries) {{
  var base_csys = evMateConnector(context, {{'mateConnector': qBodyType(qCreatedBy(makeId("{base_feature_id}")), BodyType.MATE_CONNECTOR)}});
  var fiducial_csys = evMateConnector(context, {{'mateConnector': qBodyType(qCreatedBy(makeId("{feature_id}")), BodyType.MATE_CONNECTOR)}});
  var world_T_base = toWorld(base_csys);
  var world_T_fiducial = toWorld(fiducial_csys);
  var base_T_fiducial = inverse(world_T_base) * world_T_fiducial;
  return {{
    "linear": [
      base_T_fiducial.linear[0][0],
      base_T_fiducial.linear[0][1],
      base_T_fiducial.linear[0][2],
      base_T_fiducial.linear[1][0],
      base_T_fiducial.linear[1][1],
      base_T_fiducial.linear[1][2],
      base_T_fiducial.linear[2][0],
      base_T_fiducial.linear[2][1],
      base_T_fiducial.linear[2][2],
    ],
    "translation": [
      base_T_fiducial.translation[0] / meter,
      base_T_fiducial.translation[1] / meter,
      base_T_fiducial.translation[2] / meter,
    ],
  }};
}}
      ''',
      "queries": []
  }
  query = None
  headers = None
  result = onshape.request('POST', path, query, headers, body)
  if DEBUG:
    print(json.dumps(result.json(), indent=2))
  try:
    values = result.json().get("result").get("message").get("value")
  except KeyError:
    print("Failed parsing response.")
    return None
  rpy = None
  translation = None
  for value in values:
    message = value.get("message")
    if message.get("key").get("message").get("value") == "linear":
      linear_values = message.get("value").get("message").get("value")
      if len(linear_values) != 9:
        raise ValueError("linear component does not have 9 values.")
      rotation = Rotation.from_matrix([
          [
              linear_values[0].get("message").get("value"),
              linear_values[1].get("message").get("value"),
              linear_values[2].get("message").get("value")
          ],
          [
              linear_values[3].get("message").get("value"),
              linear_values[4].get("message").get("value"),
              linear_values[5].get("message").get("value")
          ],
          [
              linear_values[6].get("message").get("value"),
              linear_values[7].get("message").get("value"),
              linear_values[8].get("message").get("value")
          ]
      ])
      rpy = rotation.as_euler('xyz')
    elif message.get("key").get("message").get("value") == "translation":
      translation_values = message.get("value").get("message").get("value")
      if len(translation_values) != 3:
        raise ValueError("translation component does not have 3 values.")
      translation = np.zeros(3)
      translation[0] = translation_values[0].get("message").get("value")
      translation[1] = translation_values[1].get("message").get("value")
      translation[2] = translation_values[2].get("message").get("value")
  return {
      "rpy": rpy,
      "translation": translation,
  }



Answers

  • ethan_keller924ethan_keller924 Member, csevp Posts: 39 EDU
    Hi @James_Borders,
    The only method we have for accessing that info is indeed through the "Evaluate FeatureScript" API call as you have done. It would be possible for us to make a dedicated endpoint for that, but in general we like to leave any calls that could be done with a little custom FS to this endpoint - otherwise we'd end up supporting way too many use cases. What is the issue with using your custom FS script? Happy to help fine tune that as needed :smile:

  • chadstoltzfuschadstoltzfus Member, Developers, csevp Posts: 130 PRO
    Typically what I like to do is do as much queries, computations, and variable creation as possible in Part Studios, then using a custom feature that parses any information needed and assign that to a FeatureScript variable. That way, I can just use the "Evaluate FeatureScript" API call to grab the computed variables. Another benefit of this is I can parse/print data in whatever format I want in the FeatureScript variable so I don't have to mess around with the JSON response too much. 
    Applications Developer at Premier Custom Built
    chadstoltzfus@premiercb.com
Sign In or Register to comment.