Send script example

This example shows how to send arbitrary URScript code to the robot using the PrimaryClient. It demonstrates both the blocking variant (sendScriptBlocking), which waits for execution feedback, and the non-blocking variant (sendScript), which only confirms that the script has been forwarded to the robot.

The full source code can be found in send_script.cpp.

Setting up the primary client

The example connects to the robot’s primary interface by creating a PrimaryClient. After starting the client, the robot’s brakes are released so that motion scripts can actually run, and the safety state is checked before any script is sent:

Listing 52 examples/send_script.cpp
19  auto notif = comm::INotifier();
20  auto client = primary_interface::PrimaryClient(robot_ip, notif);
21  client.start(10);
22
23  // --------------- INITIALIZATION END -------------------
24
25  // Make sure the robot is running
26  client.commandBrakeRelease();
27
28  if (!client.safetyModeAllowsExecution())
29  {
30    URCL_LOG_ERROR("Robot is not in a safety state where script execution is possible. Exiting.");
31    return 1;
32  }

Sending scripts with execution feedback

The sendScriptBlocking function uploads URScript code to the robot and waits until the robot reports the result of the execution. The given code can be a fully defined script (with its own def ... end block) or a snippet that will automatically be wrapped into a function on the client side. Comments and whitespace-only lines are stripped before the script is sent.

Listing 53 examples/send_script.cpp
36  const std::string fully_defined_script = R"""(
37# This is a fully defined script, function definition and all
38# All comments in this script will be stripped before sending the script to the robot
39
40# Any whitespace-only lines will also be removed
41def example_fun():
42  movej([0,-1.2,1.2,-0.1,1.57,0])
43  sleep(0.1)
44  current_pose = get_target_tcp_pose()
45  relative_move = p[0,-0.1,0,0,0,0]
46  movel(pose_trans(current_pose, relative_move), t=1)
47end)""";
48  client.sendScriptBlocking(fully_defined_script);

If you don’t provide a function definition, the library wraps the snippet in one for you. You can optionally pass a script_name (used in log messages on both the client and the robot) and a start_timeout that limits how long the call waits for the robot to confirm that the script has started. A timeout of 0 means “wait indefinitely”:

Listing 54 examples/send_script.cpp
51  client.sendScriptBlocking(R"(textmsg("Successful program execution"))");
52  // A script-function name can also be passed to the method
53  // A timeout can also be given to limit the wait for the passed function to start. If timeout = 0, it will
54  // wait indefinitely.
55  client.sendScriptBlocking(R"(textmsg("hello"))", "cool_function_name", std::chrono::milliseconds(0));

Secondary programs can also be uploaded through sendScriptBlocking. Since the robot does not report execution feedback for secondary programs, the call returns as soon as the script has been accepted. Note that secondary programs must be fully defined by the user (sec ... end):

Listing 55 examples/send_script.cpp
59  std::string secondary_script = R"(
60sec sec_script():
61  textmsg("Named secondary program")
62end
63)";
64  client.sendScriptBlocking(secondary_script);

Reporting bad script code

When a script contains errors (e.g. a typo or an undefined symbol), sendScriptBlocking will report this back to the caller. The example sends a script that uses an undefined variable current_pos instead of current_pose, and logs the result:

Listing 56 examples/send_script.cpp
67  const std::string bad_script_code = R"""(
68def bad_code():
69  current_pose = get_target_tcp_pose()
70  movel(current_pos) # note pose vs pos
71end)""";
72  URCL_LOG_INFO("Sending bad script code...");
73  try
74  {
75    client.sendScriptBlocking(bad_script_code);
76  }
77  catch (const RobotRuntimeException& exc)
78  {
79    URCL_LOG_INFO("Caught expected runtime exception from sendScriptBlocking");
80    URCL_LOG_INFO(exc.what());
81  }
82  catch (const UrException& exc)
83  {
84    URCL_LOG_ERROR("Caught unexpected exception from sendScriptBlocking");
85    URCL_LOG_ERROR(exc.what());
86  }

Sending scripts without feedback

For situations where execution feedback is not needed, sendScript can be used. It returns true as soon as the script has been transferred to the robot. The library performs no further checks, so faulty script code will not be reported back here:

Listing 57 examples/send_script.cpp
 88  // We can also send script code without any checks
 89  URCL_LOG_INFO("Executing motion without feedback");
 90  client.sendScript("movej([0.1,-0.9,0.9,0,0,0])");
 91  // But we won't know when that is done or even if our code was correct.
 92  // E.g. sending the bad script here will not give us any information
 93  // The return value will only tell us that the script code has been sent to the robot.
 94  URCL_LOG_INFO("Sending bad script code without feedback...");
 95  bool success = client.sendScript(bad_script_code);
 96  {
 97    std::stringstream ss;
 98    ss << "Bad code sent to robot successfully? " << std::boolalpha << success;
 99    URCL_LOG_INFO("%s", ss.str().c_str());
100  }