DashboardClient

For CB3 robots and PolyScope 5 the DashboardClient wraps the calls on the Dashboard server directly into C++ functions.

For PolyScope X the so-called Robot API released with PolyScope X 10.11.0 is used. It offers a subset of the Dashboard Server from previous software versions.

After connecting to the dashboard server by using the connect() function, dashboard calls can be done using the command...() functions such as commandCloseSafetyPopup(). These functions are blocking and will wait for the necessary action being done. This can involve querying another call to the dashboard server until the action is done. For example, commandPowerOn() will block until the robot reports “Robotmode: RUNNING” or the given timeout is reached.

The return value of those functions indicate whether or not the call was successful. If you want to get the call’s full response, use the command...WithResponse() calls, instead. They will return a response struct

Listing 3 urcl::DashboardResponse
struct DashboardResponse
{
  bool ok = false;
  std::string message;
  std::unordered_map<std::string, std::variant<std::string, int, bool, std::vector<ProgramInformation>>> data;
};

The data dictionary of that response struct is populated by each command individually. See the commands’ docstrings for details.

The dashboard_example.cpp shows how to use the dashboard client:

Listing 4 examples/dashboard_example.cpp
 81  auto my_dashboard = std::make_unique<DashboardClient>(robot_ip, policy);
 82  if (!my_dashboard->connect())
 83  {
 84    URCL_LOG_ERROR("Could not connect to dashboard");
 85    return 1;
 86  }
 87
 88  bool robot_in_remote_control = false;
 89  // CB3 doesn't have remote control
 90  if (version_information->major >= 5)
 91  {
 92    robot_in_remote_control = my_dashboard->commandIsInRemoteControl();
 93  }
 94
 95  // Bring the robot to a defined state being powered off.
 96  if (version_information->major < 10)
 97  {
 98    if (!my_dashboard->commandPowerOff())
 99    {
100      URCL_LOG_ERROR("Could not send power off");
101      return 1;
102    }
103    // Get the PolyScope version
104    std::string version;
105    my_dashboard->commandPolyscopeVersion(version);
106    URCL_LOG_INFO(version.c_str());
107
108    my_dashboard->commandCloseSafetyPopup();
109  }
110  else if (robot_in_remote_control)
111  {
112    // We're ignoring errors here since
113    // powering off an already powered off robot will return an error.
114    my_dashboard->commandPowerOff();
115  }
116
117  // Power it on
118  if (version_information->major < 10 || robot_in_remote_control)
119  {
120    if (!my_dashboard->commandPowerOn())
121    {
122      URCL_LOG_ERROR("Could not send Power on command");
123      return 1;
124    }
125
126    // Release the brakes
127    if (!my_dashboard->commandBrakeRelease())
128    {
129      URCL_LOG_ERROR("Could not send BrakeRelease command");
130      return 1;
131    }
132
133    // Load existing program
134    std::string program_file_name_to_be_loaded("wait_program.urp");
135    if (version_information->major >= 10)
136    {
137      // For PolyScope X, the program doesn't have an ending
138      program_file_name_to_be_loaded = "wait_program";
139    }
140    if (!my_dashboard->commandLoadProgram(program_file_name_to_be_loaded))
141    {
142      URCL_LOG_ERROR("Could not load %s program", program_file_name_to_be_loaded.c_str());
143      return 1;
144    }
145
146    std::this_thread::sleep_for(std::chrono::seconds(1));
147
148    // Play loaded program
149    if (!my_dashboard->commandPlay())
150    {
151      URCL_LOG_ERROR("Could not play program");
152      return 1;
153    }
154
155    // Pause running program
156    if (!my_dashboard->commandPause())
157    {
158      URCL_LOG_ERROR("Could not pause program");
159      return 1;
160    }
161
162    // Continue
163    if (version_information->major >= 10)
164    {
165      // For PolyScope X, the command is called "resume"
166      if (!my_dashboard->commandResume())
167      {
168        URCL_LOG_ERROR("Could not resume program");
169        return 1;
170      }
171    }
172    else
173    {
174      // For e-Series, the command is called "play"
175      if (!my_dashboard->commandPlay())
176      {
177        URCL_LOG_ERROR("Could not resume program");
178        return 1;
179      }
180    }
181
182    // Stop program
183    if (!my_dashboard->commandStop())
184    {
185      URCL_LOG_ERROR("Could not stop program");
186      return 1;
187    }
188
189    // Power it off
190    if (!my_dashboard->commandPowerOff())
191    {
192      URCL_LOG_ERROR("Could not send Power off command");
193      return 1;
194    }
195
196    if (version_information->major < 10)
197    {
198      // Flush the log
199      if (!my_dashboard->commandSaveLog())
200      {
201        URCL_LOG_ERROR("Could not send the save log command");
202        return 1;
203      }
204
205      // Make a raw request and save the response
206      std::string program_state = my_dashboard->sendAndReceive("programState");
207      URCL_LOG_INFO("Program state: %s", program_state.c_str());
208
209      // The response can be checked with a regular expression
210      bool success = my_dashboard->sendRequest("power off", "Powering off");
211      URCL_LOG_INFO("Power off command success: %d", success);
212    }
213  }
214
215  return 0;

CB 3 and PolyScope 5 only

All commands are blocking and will wait for the necessary action being done. The dashboard server’s response will be compared with an expected response. For example, when calling commandPowerOn(timeout), it is checked that the dashboard server is answering "Powering on" and then it is queried until the robot reports "Robotmode: IDLE" or until the timeout is reached. The example contains more commands that follow the same scheme.

If you want to send a query / command to the dashboard server and only want to receive the response, you can use the sendAndReceive() function:

Listing 5 examples/dashboard_example.cpp
205      // Make a raw request and save the response
206      std::string program_state = my_dashboard->sendAndReceive("programState");
207      URCL_LOG_INFO("Program state: %s", program_state.c_str());

For checking the response against an expected regular expression use sendRequest():

Listing 6 examples/dashboard_example.cpp
209      // The response can be checked with a regular expression
210      bool success = my_dashboard->sendRequest("power off", "Powering off");
211      URCL_LOG_INFO("Power off command success: %d", success);

PolyScope X only

Internally, the dashboard client makes calls against a RESTful (Representational State Transfer) API. Hence, all responses contain a JSON-encoded string of the received answer. For example, an answer to a pause request could be

{"state":"PAUSED","message":"Program state changed: PAUSED","details":"Pause successful"}