ros-industrial / abb_librws

A C++ library for interfacing with ABB robot controllers supporting Robot Web Services
BSD 3-Clause "New" or "Revised" License
71 stars 61 forks source link

Implement a RAPID module builder/generator class #30

Open jontje opened 6 years ago

jontje commented 6 years ago

A RAPID module builder/generator would be quite useful. This could for example be used to execute a path in RAPID code.

Example: From a vector of abb:rws::JointTarget elements, and some additional specifications, it is straight forward to generate a RAPID module like this:

MODULE <module_name>
   CONST jointtarget jt1 := <values>;
   CONST jointtarget jt2 := <values>;
   ...

   PROC <path_name>()
       MoveAbsJ jt1, <speed>, <zone>, <tool>;
       MoveAbsJ jt2, <speed>, <zone>, <tool>;
       ...
   ENDPROC
ENDMODULE

RWS can then be used to transfer the module to the controller, load it into a RAPID task, and then request the execution of the path.

The class could also be expanded to generate other types of modules (e.g. Cartesian motions, or a specific process including control of a tool, etc.).

gavanderhoorn commented 6 years ago

Would it perhaps be an idea to host such utility classes in a different package / library?

Generating RAPID code is not necessarily something that one would think of as being part of the responsibility of this library (ie: abb_librws) which is supposed to provide an interface to RWS.

jontje commented 6 years ago

My main idea is to implement an abstract class (with some required methods), which can be passed to and handled by the upcoming RWSStateMachineInterface class.

The actual implementation of the code generation could then for example be made in other packages.

mjd3 commented 3 years ago

Hi @jontje thanks for this library! I am wondering what the sequence of calls would look like for running a custom RAPID module as you hint at here, since the current support from the state machine interface is fairly limited. Is modifying the RAPID code for the StateMachine Addin required for this? Right now, I am executing the following steps: 1) Generate a custom RAPID module (for example, the trajectory following code above) 2) Upload a file containing this module to the controller (using uploadFile) 3) Loading the module (using RWSStateMachineInterface::Services::RAPID::runModuleLoad) 4) Set the routine name (using RWSStateMachineInterface::Services::RAPID::setRoutineName) 5) Execute the routine (using RWSStateMachineInterface::Services::RAPID::signalRunRAPIDRoutine) However, this will not work as the custom routine cannot be found by the attemptSystemRoutine function within the State Machine. A workaround right now is to load the module, then uncomment the case for custom_routine in the State Machine code, but I am wondering if there is a better way to do this, or if there would be a way to easily add something on the RWS side to make this easier. I am happy to write a PR if so!

gavanderhoorn commented 3 years ago

Do #128 and #129 help here?

mjd3 commented 3 years ago

I'm not sure, but I don't think so; it seems to me like both of those load programs/modules into the task, but the enclosed routines still need to be called somehow? It seems like runModuleLoad would have the same effect. However, the issue I am facing is that the State Machine Interface does not seem to provide a way to call a specific routine once the module is loaded. So the transfer of the RAPID program/module and loading it into the task works with the current interface, but executing it is the problem. Hope that makes sense!

mjd3 commented 3 years ago

Ah actually it seems like the runCallByVar method is what I was missing here (allows a user to call a custom routine by name)! Figured it out eventually.