Skip to content

Commit fb66319

Browse files
committed
Add ft_rtde_input_enable to ScriptCommandInterface
1 parent f8aeb87 commit fb66319

File tree

10 files changed

+185
-10
lines changed

10 files changed

+185
-10
lines changed

doc/architecture/script_command_interface.rst

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ At the time of writing the ``ScriptCommandInterface`` provides the following fun
2121
<https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/examples/tool_contact_example.cpp>`_
2222
for more information.
2323
- ``setFrictionCompensation()``: Set friction compensation for torque command.
24+
- ``ftRtdeInputEnable()``: Enable/disable FT RTDE input processing.
2425

2526
Communication protocol
2627
----------------------
@@ -50,6 +51,7 @@ The robot reads from the "script_command_socket" expecting a 32 bit integer repr
5051
- 5: startToolContact
5152
- 6: endToolContact
5253
- 7: setFrictionCompensation
54+
- 8: ftRtdeInputEnable
5355
1-27 data fields specific to the command
5456
===== =====
5557

@@ -132,11 +134,25 @@ The robot reads from the "script_command_socket" expecting a 32 bit integer repr
132134
1 friction_compensation_enabled enable/disable friction compensation for torque command.
133135
===== =====
134136

137+
.. table:: With ftRtdeInputEnable command. See script manual for details.
138+
:widths: auto
139+
140+
===== =====
141+
index meaning
142+
===== =====
143+
1 ft_rtde_input_enabled enable/disable FT RTDE input processing.
144+
2 sensor_mass in kg (floating point)
145+
3-5 sensor_mesurement_offset in m, displacement from the tool flange (3d floating point)
146+
6-9 sensor_cog in m, displacement from the tool flange (3d floating point)
147+
===== =====
148+
135149
.. note::
136150
In URScript the ``socket_read_binary_integer()`` function is used to read the data from the
137151
script command socket. The first index in that function's return value is the number of integers read,
138-
so the actual data starts at index 1. The indices in the table above are shifted by one when
139-
accessing the result array of the URScript function.
152+
so the actual data starts at index 1. The first data entry is always the command type, hence the
153+
indices in the table above are shifted by one when accessing the result array of the URScript
154+
function. E.g. reading the boolean value for friction compensation in the
155+
``setFrictionCompensation`` command would be done by accessing index 2 of the result array.
140156

141157
All floating point data is encoded into an integer representation and has to be divided by the
142158
``MULT_JOINTSTATE`` constant to get the actual floating point value. This constant is defined in

examples/external_fts_through_rtde.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <cstdio>
3232
#include <mutex>
3333

34+
#include "ur_client_library/control/script_command_interface.h"
3435
#include "ur_client_library/example_robot_wrapper.h"
3536
#include "ur_client_library/types.h"
3637

@@ -61,7 +62,7 @@ char getChar()
6162
const std::string DEFAULT_ROBOT_IP = "192.168.56.101";
6263
const std::string SCRIPT_FILE = "resources/external_control.urscript";
6364
const std::string OUTPUT_RECIPE = "examples/resources/rtde_output_recipe.txt";
64-
const std::string INPUT_RECIPE = "examples/resources/rtde_input_recipe.txt";
65+
const std::string INPUT_RECIPE = "examples/resources/rtde_input_only_ft.txt";
6566

6667
std::unique_ptr<urcl::ExampleRobotWrapper> g_my_robot;
6768
std::atomic<bool> g_RUNNING = true;
@@ -72,7 +73,8 @@ using namespace urcl;
7273

7374
void ftInputTui()
7475
{
75-
const std::string instructions = "Press x,y,z to increase the respective translational axes, a,b,c to increase the rotational axes, 0 for reset and q for quit.";
76+
const std::string instructions = "Press x,y,z to increase the respective translational axes, a,b,c to increase the "
77+
"rotational axes, 0 for reset and q for quit.";
7678
urcl::vector6d_t local_ft_vec = g_FT_VEC;
7779
while (g_RUNNING)
7880
{
@@ -235,8 +237,7 @@ int main(int argc, char* argv[])
235237
}
236238

237239
// Enable using the force-torque input through RTDE in the robot controller
238-
g_my_robot->getPrimaryClient()->sendScript("ft_rtde_input_enable(True)");
239-
240+
g_my_robot->getUrDriver()->ftRtdeInputEnable(true);
240241
// The RTDE thread sends the force-torque data to the robot and receives the wrench data from the
241242
// robot.
242243
std::thread rtde_thread(rtdeWorker, second_to_run);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
external_force_torque

examples/resources/rtde_input_recipe.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,3 @@ standard_analog_output_mask
1010
standard_analog_output_type
1111
standard_analog_output_0
1212
standard_analog_output_1
13-
external_force_torque

include/ur_client_library/control/script_command_interface.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,26 @@ class ScriptCommandInterface : public ReverseInterface
168168
*/
169169
bool setFrictionCompensation(const bool friction_compensation_enabled);
170170

171+
/*!
172+
* \brief Enable or disable RTDE input for the force torque sensor.
173+
*
174+
* When enabled, the force torque sensor values will be read from the RTDE input registers instead of the actual
175+
* sensor. This can be used to connect an external force torque sensor to the robot or to
176+
* simulate a force torque sensor when using URSim.
177+
*
178+
* \param enabled Whether to enable or disable RTDE input for the force torque sensor.
179+
* \param sensor_mass Mass of the force torque sensor in kilograms.
180+
* \param sensor_measuring_offset The offset of the force torque sensor in meters, a vector [x, y, z] specifying the
181+
* displacement from the tool flange frame.
182+
* \param sensor_cog The center of gravity of the force torque sensor in meters, a vector [x, y, z] specifying the
183+
* displacement from the tool flange frame.
184+
*
185+
* \returns True, if the write was performed successfully, false otherwise.
186+
*/
187+
bool ftRtdeInputEnable(const bool enabled, const double sensor_mass = 0.0,
188+
const vector3d_t& sensor_measuring_offset = { 0.0, 0.0, 0.0 },
189+
const vector3d_t& sensor_cog = { 0.0, 0.0, 0.0 });
190+
171191
/*!
172192
* \brief Returns whether a client/robot is connected to this server.
173193
*
@@ -206,6 +226,7 @@ class ScriptCommandInterface : public ReverseInterface
206226
START_TOOL_CONTACT = 5, ///< Start detecting tool contact
207227
END_TOOL_CONTACT = 6, ///< End detecting tool contact
208228
SET_FRICTION_COMPENSATION = 7, ///< Set friction compensation
229+
FT_RTDE_INPUT_ENABLE = 8, ///< Enable FT RTDE input
209230
};
210231

211232
/*!

include/ur_client_library/ur/ur_driver.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,26 @@ class UrDriver
726726
*/
727727
bool setFrictionCompensation(const bool friction_compensation_enabled);
728728

729+
/*!
730+
* \brief Enable or disable RTDE input for the force torque sensor.
731+
*
732+
* When enabled, the force torque sensor values will be read from the RTDE input registers instead of the actual
733+
* sensor. This can be used to connect an external force torque sensor to the robot or to
734+
* simulate a force torque sensor when using URSim.
735+
*
736+
* \param enabled Whether to enable or disable RTDE input for the force torque sensor.
737+
* \param sensor_mass Mass of the force torque sensor in kilograms.
738+
* \param sensor_measuring_offset The offset of the force torque sensor in meters, a vector [x, y, z] specifying the
739+
* displacement from the tool flange frame.
740+
* \param sensor_cog The center of gravity of the force torque sensor in meters, a vector [x, y, z] specifying the
741+
* displacement from the tool flange frame.
742+
*
743+
* \returns True, if the write was performed successfully, false otherwise.
744+
*/
745+
bool ftRtdeInputEnable(const bool enabled, const double sensor_mass = 0.0,
746+
const vector3d_t& sensor_measuring_offset = { 0.0, 0.0, 0.0 },
747+
const vector3d_t& sensor_cog = { 0.0, 0.0, 0.0 });
748+
729749
/*!
730750
* \brief Write a keepalive signal only.
731751
*

resources/external_control.urscript

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ END_FORCE_MODE = 4
5555
START_TOOL_CONTACT = 5
5656
END_TOOL_CONTACT = 6
5757
SET_FRICTION_COMPENSATION = 7
58+
FT_RTDE_INPUT_ENABLE = 8
5859
SCRIPT_COMMAND_DATA_DIMENSION = 28
5960

6061
FREEDRIVE_MODE_START = 1
@@ -788,6 +789,21 @@ thread script_commands():
788789
else:
789790
friction_compensation_enabled = True
790791
end
792+
elif command == FT_RTDE_INPUT_ENABLE:
793+
if raw_command[2] == 0:
794+
enabled = False
795+
else:
796+
enabled = True
797+
end
798+
sensor_mass = raw_command[3] / MULT_jointstate
799+
sensor_offset = [raw_command[4] / MULT_jointstate, raw_command[5] / MULT_jointstate, raw_command[6] / MULT_jointstate]
800+
sensor_cog = [raw_command[7] / MULT_jointstate, raw_command[8] / MULT_jointstate, raw_command[9] / MULT_jointstate]
801+
textmsg("calling ft_rtde_input_enable(",
802+
str_cat(enabled, str_cat(", ",
803+
str_cat(sensor_mass, str_cat(", ",
804+
str_cat(to_str(sensor_offset), str_cat(", ",
805+
str_cat(to_str(sensor_cog), ")"))))))))
806+
ft_rtde_input_enable(enabled, sensor_mass, sensor_offset, sensor_cog)
791807
end
792808
end
793809
end
@@ -917,4 +933,4 @@ socket_close("reverse_socket")
917933
socket_close("trajectory_socket")
918934
socket_close("script_command_socket")
919935

920-
# NODE_CONTROL_LOOP_ENDS
936+
# NODE_CONTROL_LOOP_ENDS

src/control/script_command_interface.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,45 @@ bool ScriptCommandInterface::setFrictionCompensation(const bool friction_compens
254254
return server_.write(client_fd_, buffer, sizeof(buffer), written);
255255
}
256256

257+
bool ScriptCommandInterface::ftRtdeInputEnable(const bool enabled, const double sensor_mass,
258+
const vector3d_t& sensor_measuring_offset, const vector3d_t& sensor_cog)
259+
{
260+
const int message_length = 9;
261+
uint8_t buffer[sizeof(int32_t) * MAX_MESSAGE_LENGTH];
262+
uint8_t* b_pos = buffer;
263+
264+
int32_t val = htobe32(toUnderlying(ScriptCommand::FT_RTDE_INPUT_ENABLE));
265+
b_pos += append(b_pos, val);
266+
267+
val = htobe32(enabled);
268+
b_pos += append(b_pos, val);
269+
270+
val = htobe32(static_cast<int32_t>(round(sensor_mass * MULT_JOINTSTATE)));
271+
b_pos += append(b_pos, val);
272+
273+
for (auto const& mass_component : sensor_measuring_offset)
274+
{
275+
val = htobe32(static_cast<int32_t>(round(mass_component * MULT_JOINTSTATE)));
276+
b_pos += append(b_pos, val);
277+
}
278+
279+
for (auto const& cog_component : sensor_cog)
280+
{
281+
val = htobe32(static_cast<int32_t>(round(cog_component * MULT_JOINTSTATE)));
282+
b_pos += append(b_pos, val);
283+
}
284+
285+
// writing zeros to allow usage with other script commands
286+
for (size_t i = message_length; i < MAX_MESSAGE_LENGTH; i++)
287+
{
288+
val = htobe32(0);
289+
b_pos += append(b_pos, val);
290+
}
291+
size_t written;
292+
293+
return server_.write(client_fd_, buffer, sizeof(buffer), written);
294+
}
295+
257296
bool ScriptCommandInterface::clientConnected()
258297
{
259298
return client_connected_;
@@ -321,4 +360,4 @@ bool ScriptCommandInterface::robotVersionSupportsCommandOrWarn(const VersionInfo
321360
}
322361

323362
} // namespace control
324-
} // namespace urcl
363+
} // namespace urcl

src/ur/ur_driver.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,20 @@ bool UrDriver::setFrictionCompensation(const bool friction_compensation_enabled)
539539
}
540540
}
541541

542+
bool UrDriver::ftRtdeInputEnable(const bool enabled, const double sensor_mass,
543+
const vector3d_t& sensor_measuring_offset, const vector3d_t& sensor_cog)
544+
{
545+
if (script_command_interface_->clientConnected())
546+
{
547+
return script_command_interface_->ftRtdeInputEnable(enabled, sensor_mass, sensor_measuring_offset, sensor_cog);
548+
}
549+
else
550+
{
551+
URCL_LOG_ERROR("Script command interface is not running. Unable to set ft_rtde_input_enable.");
552+
return 0;
553+
}
554+
}
555+
542556
bool UrDriver::writeKeepalive(const RobotReceiveTimeout& robot_receive_timeout)
543557
{
544558
vector6d_t* fake = nullptr;

tests/test_script_command_interface.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,57 @@ TEST_F(ScriptCommandInterfaceTest, test_set_friction_compensation)
426426
EXPECT_EQ(message_sum, expected_message_sum);
427427
}
428428

429+
TEST_F(ScriptCommandInterfaceTest, test_ft_rtde_input_enable)
430+
{
431+
// Wait for the client to connect to the server
432+
waitForClientConnection();
433+
434+
double sensor_mass = 1.42;
435+
vector3d_t sensor_measuring_offset = { 0.1, 0.2, 0.3 };
436+
vector3d_t sensor_cog = { 0.01, 0.02, 0.03 };
437+
script_command_interface_->ftRtdeInputEnable(true, sensor_mass, sensor_measuring_offset, sensor_cog);
438+
439+
int32_t command;
440+
std::vector<int32_t> message;
441+
client_->readMessage(command, message);
442+
443+
// 8 is ft rtde input enable
444+
int32_t expected_command = 8;
445+
EXPECT_EQ(command, expected_command);
446+
447+
// Test enabled
448+
bool received_enabled = static_cast<bool>(message[0]);
449+
450+
// Test sensor mass
451+
double received_sensor_mass = static_cast<double>(message[1]) / script_command_interface_->MULT_JOINTSTATE;
452+
EXPECT_EQ(received_sensor_mass, sensor_mass);
453+
454+
// Test sensor measuring offset
455+
vector3d_t received_sensor_measuring_offset;
456+
for (unsigned int i = 0; i < sensor_measuring_offset.size(); ++i)
457+
{
458+
received_sensor_measuring_offset[i] =
459+
static_cast<double>(message[2 + i]) / script_command_interface_->MULT_JOINTSTATE;
460+
EXPECT_EQ(received_sensor_measuring_offset[i], sensor_measuring_offset[i]);
461+
}
462+
463+
// Test sensor cog
464+
vector3d_t received_sensor_cog;
465+
for (unsigned int i = 0; i < sensor_cog.size(); ++i)
466+
{
467+
received_sensor_cog[i] = static_cast<double>(message[5 + i]) / script_command_interface_->MULT_JOINTSTATE;
468+
EXPECT_EQ(received_sensor_cog[i], sensor_cog[i]);
469+
}
470+
471+
// The rest of the message should be zero
472+
int32_t message_sum = std::accumulate(std::begin(message) + 8, std::end(message), 0);
473+
int32_t expected_message_sum = 0;
474+
EXPECT_EQ(message_sum, expected_message_sum);
475+
}
476+
429477
int main(int argc, char* argv[])
430478
{
431479
::testing::InitGoogleTest(&argc, argv);
432480

433481
return RUN_ALL_TESTS();
434-
}
482+
}

0 commit comments

Comments
 (0)