Executing RtActivities

Single RtActivities can be executed directly in different ways. This section introduces the execution semantics of RtActivities. Means of creating more complex, real-time critical combinations of RtActivities can be found in section 1.5.


Methods controlling execution

Each RtActivity provides the following methods for controlling execution:

Figure 1.2 shows the internal lifecycle of an Activity (right part of the figure) and the behavior of the abovementioned methods (left part). The vertical lines indicate the execution time of the respective method: beginExecute() terminates once the Activity has reached its Running state. From this point on, endExecute() may be called and will terminate when the Activity has either reached Failed or the Maintaining/Completed. This last state can actually be one of two possible states, Maintaining and Completed. The semantics of those states will be explained later. As can be seen in the figure, execute() terminates under the same conditions like endExecute(). cancel(), however, only triggers cancelling when the Activity is Running and terminates quickly.


PIC
Figure 1.2: Lifecycle of an Activity


Behavior during execution

The execution process of an RtActivity can be considered atomic from the view of a Robotics API application, in the sense that in general it can not be influenced, except by cancelling it. When started, the RtActivity implementation creates a command that can be interpreted by the real-time capable Robot Control Core and sends this command to the RCC. Some RtActivities (e.g. Jogging) allow for on-line modification of the running RtActivity, but this can be considered an exception to the aforementioned general rule.

In the case of asynchronous execution of an RtActivity (via beginExecute()), special rules apply for the execution of further RtActivities while the first RtActivity is still running. The rest of this section will explain these rules using examples.

Devices that are independent of the device that is currently executing an RtActivity can be controlled completely in parallel. Independent here means that one device is not a part of of another controlled device (e.g., a robot cannot be controlled as a whole while one of its joints is controlled parallely, and vice versa). In the following example, two distinct robot arms are controlled in parallel:

// initialize Robots 
LWR lwrLeft = RoboticsRegistry.get("LwrLeft", LWR.class); 
LWR lwrRight = RoboticsRegistry.get("LwrRight", LWR.class); 
ParallelGripper gripperLeft = RoboticsRegistry.getSingle( 
    "Gripper@LwrLeft", ParallelGripper.class); 
 
// move left lwr, asynchronously 
MotionProgressActivity ptpLeft = lwrLeft.use(PtpInterface.class) 
    .ptp(new double[] { 0, 0, 0, 1, 1, 1, 1 }); 
ptpLeft.beginExecute(); 
 
// do some stuff while left lwr is moving 
double[] jointAnglesRight = lwrRight.getJointAngles(); 
for (int i = 0; i < jointAnglesRight.length; i++) { 
  jointAnglesRight[i] += 0.2d; 
} 
 
// right lwr will start moving in parallel 
MotionProgressActivity ptpRight = lwrRight.use(PtpInterface.class) 
    .ptp(jointAnglesRight); 
ptpRight.beginExecute(); 
 
// await end of both motions; 
// both variants are equivalent 
ptpLeft.endExecute(); 
lwrRight.use(PtpInterface.class).endExecute(); 
 
// as soon as robots stand still, close gripper of left robot 
gripperLeft.use(GrippingInterface.class).close().execute();

A second possible use of beginExecute() is continuous execution of multiple operations targeting the same device. For example, blending between robot motions is possible by executing a series of motion activities asynchronously and using special parameterization:

// initialize Robots 
LWR lwrLeft = RoboticsRegistry.get("LwrLeft", LWR.class); 
PtpInterface motionLeft = lwrLeft.use(PtpInterface.class); 
 
// first motion, asynchronously 
MotionProgressActivity firstPtpLeft = motionLeft.ptp(new double[] { 0, 
    0, 0, 1, 1, 1, 1 }, new BlendingParameter(0.7)); 
firstPtpLeft.beginExecute(); 
 
// second motion, will be created while first motion is still running, 
// and will take over at the specified blending condition 
MotionProgressActivity secondPtpLeft = motionLeft.ptp(new double[] { 0, 
    0, 0, -1, -1, -1, -1 }); 
secondPtpLeft.execute(); 
 
// third motion, will be created once second motion is complete (as 
// second motion was executed synchronously via execute()) 
MotionProgressActivity thirdPtpLeft = motionLeft.ptp(new double[] { 0, 
    0, 0, 1, 1, 1, 1 }); 
thirdPtpLeft.execute();

The first motion activity is created with a special parameter which indicates that the motion may be blended over into a subsequent motion at 70 percent of its progress. By executing this motion asynchronously, the program can start execution of a second motion while the first motion is still running. In this case, the second motion is started once the first motion reaches 70 percent of its execution time. From this point on, the second motion takes over control of the robot.

Note that in case two RtActivities are started asynchronously in quick succession, the second activity will in any case await termination of the first activity before starting. Thus, program flow will be delayed considerably by beginExecute() of the second activity. The next two examples illustrate this effect. In both examples, motionLeft and motionRight are PtpInterfaces of the left and right LWR, respectively.

Example 1 : right robot moving in parallel to first motion of left robot

// first motion of left lwr, asynchronously 
motionLeft.ptp(new double[] { 0, 0, 0, 1, 1, 1, 1 }).beginExecute(); 
 
// motion of right lwr, started right after *first* motion of left lwr was 
// started 
motionRight.ptp(new double[] { 1, 0, 1, 0, 1, 0, 1 }).beginExecute(); 
 
// second motion of left lwr, asynchronously 
motionLeft.ptp(new double[] { 0, 0, 0, -1, -1, -1, -1 }).beginExecute();

Example 2: right robot starts to move only once second motion of left robot has been started

// first motion of left lwr, asynchronously 
motionLeft.ptp(new double[] { 0, 0, 0, 1, 1, 1, 1 }).beginExecute(); 
 
// second motion of left lwr, asynchronously 
motionLeft.ptp(new double[] { 0, 0, 0, -1, -1, -1, -1 }).beginExecute(); 
 
// motion of right lwr, started after *second* motion of left lwr was 
// started 
motionRight.ptp(new double[] { 1, 0, 1, 0, 1, 0, 1 }).beginExecute();

Though all RtActivities are run asynchronously in both examples, the program flow is delayed by the second motion of the left LWR until the first motion has completed execution. Thus the motion of the right LWR is started at different times, depending on the position of the call to beginExecute() in the program.

An arbitray number of independent devices can be controlled truly parallel, though:

// motion of left lwr, asynchronously 
lwrLeft.use(PtpInterface.class) 
    .ptp(new double[] { 0, 0, 0, 1, 1, 1, 1 }).beginExecute(); 
 
// motion of right lwr, asynchronously 
lwrRight.use(PtpInterface.class) 
    .ptp(new double[] { 0, 0, 0, 1, 1, 1, 1 }).beginExecute(); 
 
// closing left gripper, asynchronously 
gripperLeft.use(GrippingInterface.class).close().beginExecute(); 
 
// closing right gripper, asynchronously 
gripperRight.use(GrippingInterface.class).close().beginExecute();

All four operations in this example are started in immediate succession. Note however, that there are no guarantees considering the exact timing of the execution. There might be slight, varying delays between the start of each of the operations. This is due to the execution semantics of Java and the network connection to the real-time Robot Control Core. If certain RtActivities require exact timing guarantees in between their execution, developers should use the mechanisms to combine the RtActivities that are provided by the Robotics API.

Note

Single RtActivities are executed in a real-time context, guaranteeing e.g. deterministic motion interpolation. When executing multiple RtActivities independently of each other in a robot program, no tight guarantees are provided for timing between those activities. Features like continuous motion execution may fail as well, leading to each motion operation to be completely executed (which must not cause collisions!). When timing between RtActivities is important, use explicit combinations of those activities!


The state Maintaining in Activities

When an Activity is in state Maintaining (see Fig. 1.2), it behaves for the most part like as if it were Completed (i.e., execute() and endExecute() will terminate). However, in this case the Activity can still actively control its devices and will use this to stabilize the device’s state. As an example, consider a robot motion Activity that aims to establish a contact force between the robot and some surface. This Activity will leave its running state once the force has been established. However, it will then enter Maintaining instead of Completed and will actively maintain the force that has been built up. An Activity for this robot that is executed subsequently has to be able to take over control of the robot and deal with force control itself, e.g. by releasing the force or actively maintaining it while performing other operations.

When an Activity is not able to take over the preceding Activity when it is in state Maintaining, the subsequent Activity will never be started, i.e. (begin)execute() will block forever.

Note

Some Activities will continue to actively control the device after their execution has terminated. Be sure to subsequently execute an Activity that is able to take over control of the device in this state. Consider the documentations of DeviceInterfaces to find out which combinations of Activities are valid.