io_relay.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2016, Delft Robotics Institute
5  * Copyright (c) 2020, Southwest Research Institute
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * * Neither the name of the Southwest Research Institute, nor the names
17  * of its contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
34 #include <string>
35 #include <cstdint>
36 #include <limits>
37 #include <ros/ros.h>
38 #include <sstream>
39 
40 namespace motoman
41 {
42 namespace io_relay
43 {
44 
46 
47 bool MotomanIORelay::init(int default_port)
48 {
49  std::string ip;
50  int port;
51 
52  // override port with ROS param, if available
53  const std::string port_param_name = "~port";
54  // TODO( ): should really use a private NodeHandle here
55  if (!ros::param::param<int>(port_param_name, port, default_port))
56  {
57  ROS_WARN_STREAM_NAMED("io.init", "Failed to get '" << port_param_name
58  << "' parameter: using default (" << default_port << ")");
59  }
60  if (port < 0 || port > std::numeric_limits<uint16_t>::max())
61  {
62  ROS_FATAL_STREAM_NAMED("io.init", "Invalid value for port (" << port << "), "
63  "must be between 0 and " << std::numeric_limits<uint16_t>::max() << ".");
64  return false;
65  }
66 
67  const std::string robot_ip_param_name = "robot_ip_address";
68  if (!ros::param::get(robot_ip_param_name, ip) || ip.empty())
69  {
70  ROS_FATAL_STREAM_NAMED("io.init", "Invalid IP address: please set the '"
71  << robot_ip_param_name << "' parameter");
72  return false;
73  }
74 
75  char* ip_addr = strdup(ip.c_str()); // connection.init() requires "char*", not "const char*"
76  if (!default_tcp_connection_.init(ip_addr, port))
77  {
78  ROS_FATAL_NAMED("io.init", "Failed to initialize TcpClient");
79  return false;
80  }
81  free(ip_addr);
82 
83  ROS_DEBUG_STREAM_NAMED("io.init", "I/O relay attempting to connect to: tcp://" << ip << ":" << port);
85  {
86  ROS_FATAL_NAMED("io.init", "Failed to connect");
87  return false;
88  }
89 
91  {
92  ROS_FATAL_NAMED("io.init", "Failed to initialize MotomanIoCtrl");
93  return false;
94  }
95 
96  this->srv_read_single_io = this->node_.advertiseService("read_single_io",
98  this->srv_write_single_io = this->node_.advertiseService("write_single_io",
100 
101  return true;
102 }
103 
104 // Service to read a single IO
106  motoman_msgs::ReadSingleIO::Request &req,
107  motoman_msgs::ReadSingleIO::Response &res)
108 {
109  shared_int io_val = -1;
110  std::string err_msg;
111 
112  // send message and release mutex as soon as possible
113  this->mutex_.lock();
114  bool result = io_ctrl_.readSingleIO(req.address, io_val, err_msg);
115  this->mutex_.unlock();
116 
117  if (!result)
118  {
119  res.success = false;
120 
121  // provide caller with failure indication
122  // TODO( ): should we also return the result code?
123  std::stringstream message;
124  message << "Read failed (address: " << req.address << "): " << err_msg;
125  res.message = message.str();
126  ROS_ERROR_STREAM_NAMED("io.read", res.message);
127 
128  return true;
129  }
130 
131  ROS_DEBUG_STREAM_NAMED("io.read", "Address " << req.address << ", value: " << io_val);
132 
133  // no failure, so no need for an additional message
134  res.value = io_val;
135  res.success = true;
136  return true;
137 }
138 
139 
140 // Service to write Single IO
142  motoman_msgs::WriteSingleIO::Request &req,
143  motoman_msgs::WriteSingleIO::Response &res)
144 {
145  std::string err_msg;
146 
147  // send message and release mutex as soon as possible
148  this->mutex_.lock();
149  bool result = io_ctrl_.writeSingleIO(req.address, req.value, err_msg);
150  this->mutex_.unlock();
151 
152  if (!result)
153  {
154  res.success = false;
155 
156  // provide caller with failure indication
157  // TODO( ): should we also return the result code?
158  std::stringstream message;
159  message << "Write failed (address: " << req.address << "): " << err_msg;
160  res.message = message.str();
161  ROS_ERROR_STREAM_NAMED("io.write", res.message);
162 
163  return true;
164  }
165 
166  ROS_DEBUG_STREAM_NAMED("io.write", "Element " << req.address << " set to: " << req.value);
167 
168  // no failure, so no need for an additional message
169  res.success = true;
170  return true;
171 }
172 
173 } // namespace io_relay
174 } // namespace motoman
175 
ros::ServiceServer srv_write_single_io
Definition: io_relay.h:66
bool readSingleIoCB(motoman_msgs::ReadSingleIO::Request &req, motoman_msgs::ReadSingleIO::Response &res)
Definition: io_relay.cpp:105
bool init(char *buff, int port_num)
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
bool readSingleIO(industrial::shared_types::shared_int address, industrial::shared_types::shared_int &value, std::string &err_msg)
Reads a single IO point on the controller.
Definition: io_ctrl.cpp:68
bool init(int default_port)
Class initializer.
Definition: io_relay.cpp:47
io_ctrl::MotomanIoCtrl io_ctrl_
Definition: io_relay.h:63
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool init(SmplMsgConnection *connection)
Definition: io_ctrl.cpp:62
ROSCPP_DECL bool get(const std::string &key, std::string &s)
#define ROS_FATAL_STREAM_NAMED(name, args)
SmResultType result
#define ROS_FATAL_NAMED(name,...)
bool writeSingleIO(industrial::shared_types::shared_int address, industrial::shared_types::shared_int value, std::string &err_msg)
Writes to a single IO point on the controller.
Definition: io_ctrl.cpp:89
bool writeSingleIoCB(motoman_msgs::WriteSingleIO::Request &req, motoman_msgs::WriteSingleIO::Response &res)
Definition: io_relay.cpp:141
ros::ServiceServer srv_read_single_io
Definition: io_relay.h:65
#define ROS_WARN_STREAM_NAMED(name, args)


motoman_driver
Author(s): Jeremy Zoss (Southwest Research Institute), Ted Miller (MotoROS) (Yaskawa Motoman), Eric Marcil (MotoROS) (Yaskawa Motoman)
autogenerated on Sat May 8 2021 02:27:43