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
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:
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:
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():
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"}