KaCanOpen
 All Classes Functions Variables Typedefs Enumerations Pages
joint_state_publisher.cpp
1 /*
2  * Copyright (c) 2015-2016, Thomas Keh
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "joint_state_publisher.h"
33 #include "utils.h"
34 #include "logger.h"
35 #include "profiles.h"
36 #include "sdo_error.h"
37 
38 #include "ros/ros.h"
39 #include "sensor_msgs/JointState.h"
40 
41 #include <string>
42 #include <stdexcept>
43 
44 namespace kaco {
45 
46 JointStatePublisher::JointStatePublisher(Device& device, int32_t position_0_degree,
47  int32_t position_360_degree, const std::string& position_actual_field, const std::string& topic_name)
48  : m_device(device), m_position_0_degree(position_0_degree),
49  m_position_360_degree(position_360_degree), m_position_actual_field(position_actual_field), m_topic_name(topic_name), m_initialized(false)
50 {
51 
52  const uint16_t profile = device.get_device_profile_number();
53 
54  if (profile != 402) {
55  throw std::runtime_error("JointStatePublisher can only be used with a CiA 402 device."
56  " You passed a device with profile number "+std::to_string(profile));
57  }
58 
59  const Value operation_mode = device.get_entry("Modes of operation display");
60 
61  // TODO: look into INTERPOLATED_POSITION_MODE
62  if (operation_mode != Profiles::constants.at(402).at("profile_position_mode")
63  && operation_mode != Profiles::constants.at(402).at("interpolated_position_mode")) {
64  throw std::runtime_error("[JointStatePublisher] Only position mode supported yet."
65  " Try device.set_entry(\"modes_of_operation\", device.get_constant(\"profile_position_mode\"));");
66  return;
67  }
68 
69  if (m_topic_name.empty()) {
70  uint8_t node_id = device.get_node_id();
71  m_topic_name = "device" + std::to_string(node_id) + "/get_joint_state";
72  }
73 
74 }
75 
77 
78  assert(!m_topic_name.empty());
79  DEBUG_LOG("Advertising "<<m_topic_name);
80  ros::NodeHandle nh;
81  m_publisher = nh.advertise<sensor_msgs::JointState>(m_topic_name, queue_size);
82  m_initialized = true;
83 
84 }
85 
87 
88  try {
89 
90  if (!m_initialized) {
91  throw std::runtime_error("[JointStatePublisher] publish() called before advertise().");
92  }
93 
94  sensor_msgs::JointState js;
95 
96  js.name.resize(1);
97  js.position.resize(1);
98 
99  // only position supported yet.
100  js.velocity.resize(0);
101  js.effort.resize(0);
102 
103  js.name[0] = m_topic_name;
104 
105  const int32_t pos = m_device.get_entry(m_position_actual_field);
106  js.header.stamp = ros::Time::now();
107  js.position[0] = pos_to_rad(pos);
108 
109  DEBUG_LOG("Sending JointState message");
110  DEBUG_DUMP(pos);
111  DEBUG_DUMP(js.position[0]);
112 
113  m_publisher.publish(js);
114 
115  } catch (const sdo_error& error) {
116  // TODO: only catch timeouts?
117  ERROR("Exception in JointStatePublisher::publish(): "<<error.what());
118  }
119 
120 }
121 
122 double JointStatePublisher::pos_to_rad(int32_t pos) const {
123  const double p = pos;
124  const double min = m_position_0_degree;
125  const double max = m_position_360_degree;
126  const double dist = max - min;
127  const double result = ((p-min)/dist)*2*pi();
128  return result;
129 }
130 
131 } // end namespace kaco
virtual const char * what() const noexceptoverride
Returns error description.
Definition: sdo_error.cpp:105
const Value & get_entry(const std::string &entry_name, const ReadAccessMethod access_method=ReadAccessMethod::use_default)
Gets the value of a dictionary entry by name internally. If there is no cached value or the entry is ...
Definition: device.cpp:102
JointStatePublisher(Device &device, int32_t position_0_degree, int32_t position_360_degree, const std::string &position_actual_field="Position actual value", const std::string &topic_name="")
Constructor.
This type of exception is thrown when there are problems while accessing devices via SDO...
Definition: sdo_error.h:48
uint16_t get_device_profile_number()
Returns the CiA profile number.
Definition: device.cpp:274
uint8_t get_node_id() const
Returns the node ID of the device.
Definition: device.cpp:74
This class represents a CanOpen slave device in the network.
Definition: device.h:83
This class contains a value to be stored in the object dictionary. The value can have one of the type...
Definition: value.h:53
static const std::map< uint16_t, std::map< std::string, const Value > > constants
Constants for CiA profiles. Type: map < profile number , map < operation name , constant value > > ...
Definition: profiles.h:60