Skip to content

Commit

Permalink
Add trajectory_interface
Browse files Browse the repository at this point in the history
  • Loading branch information
fmauch committed Jun 2, 2021
1 parent afc8ad3 commit 53785d2
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 8 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_library(urcl SHARED
src/comm/tcp_server.cpp
src/control/reverse_interface.cpp
src/control/script_sender.cpp
src/control/trajectory_point_interface.cpp
src/primary/primary_package.cpp
src/primary/robot_message.cpp
src/primary/robot_state.cpp
Expand Down
3 changes: 2 additions & 1 deletion include/ur_client_library/comm/control_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ enum class ControlMode : int32_t
MODE_UNINITIALIZED = -1, ///< Startup default until another mode is sent to the script.
MODE_IDLE = 0, ///< Set when no controller is currently active controlling the robot.
MODE_SERVOJ = 1, ///< Set when servoj control is active.
MODE_SPEEDJ = 2 ///< Set when speedj control is active.
MODE_SPEEDJ = 2, ///< Set when speedj control is active.
MODE_FORWARD = 3 ///< Set when trajectory forwarding is active.
};
} // namespace comm
} // namespace urcl
Expand Down
34 changes: 27 additions & 7 deletions include/ur_client_library/control/reverse_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ namespace urcl
{
namespace control
{
/*!
* \brief Control messages for forwarding and aborting trajectories.
*/
enum class TrajectoryControlMessage : int32_t
{
TRAJECTORY_CANCEL = -1, ///< Represents command to cancel currently active trajectory.
TRAJECTORY_NOOP = 0, ///< Represents no new control command.
TRAJECTORY_START = 1, ///< Represents command to start a new trajectory.
};

/*!
* \brief The ReverseInterface class handles communication to the robot. It starts a server and
* waits for the robot to connect via its URCaps program.
Expand All @@ -61,7 +71,7 @@ class ReverseInterface
/*!
* \brief Disconnects possible clients so the reverse interface object can be safely destroyed.
*/
~ReverseInterface() = default;
virtual ~ReverseInterface() = default;

/*!
* \brief Writes needed information to the robot to be read by the URCaps program.
Expand All @@ -72,24 +82,34 @@ class ReverseInterface
*
* \returns True, if the write was performed successfully, false otherwise.
*/
bool write(const vector6d_t* positions, const comm::ControlMode control_mode = comm::ControlMode::MODE_IDLE);
virtual bool write(const vector6d_t* positions, const comm::ControlMode control_mode = comm::ControlMode::MODE_IDLE);

/*!
* \brief Writes needed information to the robot to be read by the URScript program.
*
* \param trajectory_action 1 if a trajectory is to be started, -1 if it should be stopped
* \param point_number The number of points of the trajectory to be executed
*
* \returns True, if the write was performed successfully, false otherwise.
*/
bool writeTrajectoryControlMessage(const TrajectoryControlMessage trajectory_action, const int point_number = 0);

/*!
* \brief Set the Keepalive count. This will set the number of allowed timeout reads on the robot.
*
* \param count Number of allowed timeout reads on the robot.
*/
void setKeepaliveCount(const uint32_t& count)
virtual void setKeepaliveCount(const uint32_t& count)
{
keepalive_count_ = count;
}

private:
void connectionCallback(const int filedescriptor);
protected:
virtual void connectionCallback(const int filedescriptor);

void disconnectionCallback(const int filedescriptor);
virtual void disconnectionCallback(const int filedescriptor);

void messageCallback(const int filedescriptor, char* buffer);
virtual void messageCallback(const int filedescriptor, char* buffer);

int client_fd_;
comm::TCPServer server_;
Expand Down
87 changes: 87 additions & 0 deletions include/ur_client_library/control/trajectory_point_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-

// -- BEGIN LICENSE BLOCK ----------------------------------------------
// Copyright 2021 FZI Forschungszentrum Informatik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -- END LICENSE BLOCK ------------------------------------------------

//----------------------------------------------------------------------
/*!\file
*
* \author Felix Exner mauch@fzi.de
* \date 2021-06-01
*
*/
//----------------------------------------------------------------------

#ifndef UR_CLIENT_LIBRARY_TRAJECTORY_INTERFACE_H_INCLUDED
#define UR_CLIENT_LIBRARY_TRAJECTORY_INTERFACE_H_INCLUDED

#include "ur_client_library/control/reverse_interface.h"
#include "ur_client_library/comm/control_mode.h"
#include "ur_client_library/types.h"
#include "ur_client_library/log.h"

namespace urcl
{
namespace control
{
/*!
* \brief The TrajectoryPointInterface class handles trajectory forwarding to the robot. Full
* trajectories are forwarded to the robot controller and are executed there.
*/
class TrajectoryPointInterface : public ReverseInterface
{
public:
static const int32_t MULT_TIME = 1000;
static const int32_t JOINT_POINT = 0;
static const int32_t CARTESIAN_POINT = 1;

TrajectoryPointInterface() = delete;
/*!
* \brief Creates a TrajectoryPointInterface object including a TCPServer.
*
* \param port Port the Server is started on
*/
TrajectoryPointInterface(uint32_t port);

/*!
* \brief Disconnects possible clients so the reverse interface object can be safely destroyed.
*/
virtual ~TrajectoryPointInterface() = default;


/*!
* \brief Writes needed information to the robot to be read by the URScript program.
*
* \param positions A vector of joint or cartesian targets for the robot
* \param time The goal time to reach the target
*
* \returns True, if the write was performed successfully, false otherwise.
*/
bool writeTrajectoryPoint(const vector6d_t* positions, const float goal_time, const float blend_radius,
const bool cartesian);

protected:
virtual void connectionCallback(const int filedescriptor) override;

virtual void disconnectionCallback(const int filedescriptor) override;

virtual void messageCallback(const int filedescriptor, char* buffer) override;
};

} // namespace control
} // namespace urcl

#endif // UR_CLIENT_LIBRARY_TRAJECTORY_INTERFACE_H_INCLUDED
25 changes: 25 additions & 0 deletions include/ur_client_library/ur/ur_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "ur_client_library/rtde/rtde_client.h"
#include "ur_client_library/control/reverse_interface.h"
#include "ur_client_library/control/trajectory_point_interface.h"
#include "ur_client_library/control/script_sender.h"
#include "ur_client_library/ur/tool_communication.h"
#include "ur_client_library/ur/version_information.h"
Expand Down Expand Up @@ -180,6 +181,29 @@ class UrDriver
*/
bool writeJointCommand(const vector6d_t& values, const comm::ControlMode control_mode);

/*!
* \brief Writes a trajectory point onto the dedicated socket.
*
* \param values Desired joint or cartesian positions
* \param goal_time Time for the robot to reach this point
* \param cartesian True, if the point sent is cartesian, false if joint-based
*
* \returns True on successful write.
*/
bool writeTrajectoryPoint(const vector6d_t& values, const bool cartesian, const float goal_time = 0.0,
const float blend_radius = 0.052);

/*!
* \brief Writes a control message in trajectory forward mode.
*
* \param trajectory_action The action to be taken, such as starting a new trajectory.
* \param point_number The number of points of a new trajectory to be sent.
*
* \returns True on successful write.
*/
bool writeTrajectoryControlMessage(const control::TrajectoryControlMessage trajectory_action,
const int point_number = 0);

/*!
* \brief Write a keepalive signal only.
*
Expand Down Expand Up @@ -272,6 +296,7 @@ class UrDriver
comm::INotifier notifier_;
std::unique_ptr<rtde_interface::RTDEClient> rtde_client_;
std::unique_ptr<control::ReverseInterface> reverse_interface_;
std::unique_ptr<control::TrajectoryPointInterface> trajectory_interface_;
std::unique_ptr<control::ScriptSender> script_sender_;
std::unique_ptr<comm::URStream<primary_interface::PrimaryPackage>> primary_stream_;
std::unique_ptr<comm::URStream<primary_interface::PrimaryPackage>> secondary_stream_;
Expand Down
35 changes: 35 additions & 0 deletions src/control/reverse_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,41 @@ bool ReverseInterface::write(const vector6d_t* positions, const comm::ControlMod
return server_.write(client_fd_, buffer, sizeof(buffer), written);
}

bool ReverseInterface::writeTrajectoryControlMessage(const TrajectoryControlMessage trajectory_action,
const int point_number)
{
if (client_fd_ == -1)
{
return false;
}
uint8_t buffer[sizeof(int32_t) * 8];
uint8_t* b_pos = buffer;

// The first element is always the keepalive signal.
int32_t val = htobe32(1);
b_pos += append(b_pos, val);

val = htobe32(toUnderlying(trajectory_action));
b_pos += append(b_pos, val);

val = htobe32(point_number);
b_pos += append(b_pos, val);

// writing zeros to allow usage in control loop with other control messages
for (size_t i = 0; i < 4; i++)
{
val = htobe32(0);
b_pos += append(b_pos, val);
}

val = htobe32(toUnderlying(comm::ControlMode::MODE_FORWARD));
b_pos += append(b_pos, val);

size_t written;

return server_.write(client_fd_, buffer, sizeof(buffer), written);
}

void ReverseInterface::connectionCallback(const int filedescriptor)
{
if (client_fd_ < 0)
Expand Down
113 changes: 113 additions & 0 deletions src/control/trajectory_point_interface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-

// -- BEGIN LICENSE BLOCK ----------------------------------------------
// Copyright 2021 FZI Forschungszentrum Informatik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -- END LICENSE BLOCK ------------------------------------------------

//----------------------------------------------------------------------
/*!\file
*
* \author Felix Exner mauch@fzi.de
* \date 2021-06-01
*
*/
//----------------------------------------------------------------------

#include <ur_client_library/control/trajectory_point_interface.h>

namespace urcl
{
namespace control
{
TrajectoryPointInterface::TrajectoryPointInterface(uint32_t port) : ReverseInterface(port, [](bool foo) { return foo; })
{
}

bool TrajectoryPointInterface::writeTrajectoryPoint(const vector6d_t* positions, const float goal_time,
const float blend_radius, const bool cartesian)
{
if (client_fd_ == -1)
{
return false;
}
uint8_t buffer[sizeof(int32_t) * 9];
uint8_t* b_pos = buffer;

if (positions != nullptr)
{
for (auto const& pos : *positions)
{
int32_t val = static_cast<int32_t>(pos * MULT_JOINTSTATE);
val = htobe32(val);
b_pos += append(b_pos, val);
}
}
else
{
b_pos += 6 * sizeof(int32_t);
}

int32_t val = static_cast<int32_t>(goal_time * MULT_TIME);
val = htobe32(val);
b_pos += append(b_pos, val);

val = static_cast<int32_t>(blend_radius * MULT_TIME);
val = htobe32(val);
b_pos += append(b_pos, val);

if (cartesian)
{
val = CARTESIAN_POINT;
}
else
{
val = JOINT_POINT;
}

val = htobe32(val);
b_pos += append(b_pos, val);

size_t written;

return server_.write(client_fd_, buffer, sizeof(buffer), written);
}

void TrajectoryPointInterface::connectionCallback(const int filedescriptor)
{
if (client_fd_ < 0)
{
URCL_LOG_DEBUG("Robot connected to trajectory interface.");
client_fd_ = filedescriptor;
}
else
{
URCL_LOG_ERROR("Connection request to TrajectoryPointInterface received while connection already established. Only one "
"connection is allowed at a time. Ignoring this request.");
}
}

void TrajectoryPointInterface::disconnectionCallback(const int filedescriptor)
{
URCL_LOG_DEBUG("Connection to trajectory interface dropped.", filedescriptor);
client_fd_ = -1;
}

void TrajectoryPointInterface::messageCallback(const int filedescriptor, char* buffer)
{
// TODO: Send up. This will be things like "finished trajectory"
URCL_LOG_INFO("Received message %s on TrajectoryPointInterface", buffer);
}
} // namespace control
} // namespace urcl
Loading

0 comments on commit 53785d2

Please sign in to comment.