-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial OpenRPC docs - with state subscription #5
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only change needed, Which may or may not be required in this project is that jog speed is usually set by a separate register not in the parameters of the jog command.
In a way though we are creating a new standard and may want this to be a feature now.
Putting it in the jog command makes sense to me but either way seems fine! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a tool for editing these files? The format seems extremely verbose...
For comparison, an example of ROS's format (which doesn't cover the same information admittedly, but it's a similar use-case): http://docs.ros.org/en/melodic/api/sensor_msgs/html/msg/JointState.html
{ | ||
"type": "object", | ||
"properties": { | ||
"jointIndex": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps redundant if we're doing an array of these? I can't see a lot of uses for reading back just one joint at a time.
"type": "object", | ||
"properties": { | ||
"jointIndex": { | ||
"type": "integer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what the spec says about this but should we define ints etc with exact widths, eg a 32-bit integer? It's probably not too much of an issue to just define integer as 64-bit signed in all cases, but maybe we'd want to pack from/unpack to specific types on the motion controller side (ie C, C++ or Rust)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON schema does not allow for this. We need to map keys to memory space on the controller anyway, so we probably can specify the type for C / Rust in the same lookup table we use for memory mapping?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we actually could just add our own keyword if we wanted.
{
"type": "object",
"properties": {
"jointIndex": {
"type": "integer",
"data-type": "u8",
}
}
}
{ | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/jointPosition" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like being able to reference stuff in like this, seems useful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somewhere we need to include unit information. Presumably this is in μm for linear joints, but not sure what we'd be doing angular joints in? I'd maybe lean towards making it a double and using radians
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think defining the units in the name of the data type would be a good idea. For example jointPositionRadians
I didn't know what the unit was and none of this was meant to be finalized data types, just simple examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually if you are trying to look at raw motor positions. (which is really just for troubleshooting and calibrating) You would just get the step count from origin. Knowing the current radians of a motor that may fully rotate 20 to 30 times in the joints full range of motion is not as useful as you might think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see us needing both values - the raw positions seems useful for calibration/troubleshooting as you mention, the joint position in radians would be the easiest way to display a 3D representation of the robot though I think.
"type": "object", | ||
"properties": { | ||
"robotOnline": { | ||
"type": "boolean" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like it's going to be an enum, since we could have a lot of potential states - eg drives offline
, estop
, teach
/manual
, active-paused
, run
etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can define an enum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have to be careful about this. Most operators manuals for industrial robots have a state chapter (including error states) that are dozens of pages long. This could be daunting to write out on an enum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the robotOnline was literally just put in as an example value. The point of this was just to establish a format that people like you can use to develop the details
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point on the enum getting pretty big - I can see us maybe having a hierarchy of states, eg the main state is error, the substate is error-hardware-overcurrent and there's also an associated error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thoughts maybe the state is just presented as a string (for showing to the user) and anything that needs to make decisions checks state flags which the controller toggles based on the state, eg jog_enabled
, has_error
- that keeps the state logic more contained inside the controller
@@ -0,0 +1,15 @@ | |||
{ | |||
"name": "getActiveSubscriptions", | |||
"description": "Get a list of state keys for which the client is currently subscribed to value changes", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very useful
"type": "boolean" | ||
}, | ||
"jointPositions": { | ||
"$ref": "#/components/schemas/jointPositions" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd keep this separate from the controller state - the complete controller state does include joint positions, but it also includes a lot of other values and I think we need to be able to pick and choose. Also it just seems cleaner to keep things separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the getState method provides the ability to include or exclude keys. You can also call the getPosition method to get just that. The reason that all state items are also included in a state object is so that there is a place to list all of the state parameters and it is a mechanism for transmitting any changes to state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a way to generalize the API. So we dont' necessarily have to create methods for every parameter that gets added to state. If you add a new key to state, it can automatically be subscribed to.
}, | ||
{ | ||
"name": "direction", | ||
"description": "Direction to jog the joint.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably you could just specify a negative velocity rather than having this be separate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. That makes sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to be careful with the velocity field. There are other factors that contribute to the final velocity of the jog. Most of these factors are determined in the safety circuit. For example if a specific safety switch is open (like a person gate) than the max jog speed of the robot is radically lowered and would be outside of whatever value you sent to the API.
In that respect. I believe the velocity value should instead be a percentage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that would depend on what you expected to happen if something changed the maximum permissible speed while the robot was moving, for example if the control setpoint is 20% and robot is moving at 20mm/s then the safety system changes the limit from 100mm/s to 50mm/s, would you expect the robot to drop back to 10mm/s or remain constant at 20mm/s.
We'd probably also want a separate absolute interface for use with external control systems (ROS etc) - perhaps that would be enabled in addition to the jog interface if the client has an extra permission enabled, since it shouldn't be accessible from the UI as it'd be operational in run mode instead of teach/manual mode.
See here: https://github.com/open-rpc/inspector |
That inspector tool seems to be exactly what I was looking for - I'll see if I can use it to convert the examples in #6 to OpenRPC format later today |
Each method and schema is organized in its own file and compiled with the tool I created open-rpc-compiler into a single openrpc.json representing the complete API
A state schema is defined that is the basis of subsriptions.