PdsNode.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2017-2020, Dataspeed Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * 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
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Dataspeed Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 #include "PdsNode.h"
36 
37 namespace dataspeed_pds_lcm
38 {
39 
40 PdsNode::PdsNode(ros::NodeHandle &nh, ros::NodeHandle &priv_nh, lcm::LCM *lcm)
41 {
42  // Setup message synchronizers
46  sync_ros_slave1_->registerCallback(boost::bind(&PdsNode::recvSyncSlave1, this, _1, _2));
47  sync_ros_slave2_->registerCallback(boost::bind(&PdsNode::recvSyncSlave2, this, _1, _2, _3));
48  sync_ros_slave3_->registerCallback(boost::bind(&PdsNode::recvSyncSlave3, this, _1, _2, _3, _4));
49 
50  // Reduce synchronization delay
51  const ros::Duration SYNC_20_MS(0.006); // 30% of 20ms period
52  sync_ros_slave1_->setInterMessageLowerBound(0, SYNC_20_MS);
53  sync_ros_slave1_->setInterMessageLowerBound(1, SYNC_20_MS);
54  sync_ros_slave2_->setInterMessageLowerBound(0, SYNC_20_MS);
55  sync_ros_slave2_->setInterMessageLowerBound(1, SYNC_20_MS);
56  sync_ros_slave2_->setInterMessageLowerBound(2, SYNC_20_MS);
57  sync_ros_slave3_->setInterMessageLowerBound(0, SYNC_20_MS);
58  sync_ros_slave3_->setInterMessageLowerBound(1, SYNC_20_MS);
59  sync_ros_slave3_->setInterMessageLowerBound(2, SYNC_20_MS);
60  sync_ros_slave3_->setInterMessageLowerBound(3, SYNC_20_MS);
61 
62  // Setup Publishers
63  pub_status_ = nh.advertise<dataspeed_pds_msgs::Status>("status", 10);
64 
65  // Setup Subscribers
66  sub_relay_ = nh.subscribe("relay", 10, &PdsNode::recvRelay, this, ros::TransportHints().tcpNoDelay(true));
67  sub_mode_ = nh.subscribe("mode", 10, &PdsNode::recvMode, this, ros::TransportHints().tcpNoDelay(true));
68  sub_script_ = nh.subscribe("script", 10, &PdsNode::recvScript, this, ros::TransportHints().tcpNoDelay(true));
69 
70  // Hold onto the LCM handle
71  lcm_ = *lcm;
72 
73  // LCM Subscribers
74  lcm_.subscribe("STATUS", &PdsNode::lcmRecvStatus, this);
75 }
77 {
78  if (sync_ros_slave1_) {
79  delete sync_ros_slave1_;
80  sync_ros_slave1_ = NULL;
81  }
82  if (sync_ros_slave2_) {
83  delete sync_ros_slave2_;
84  sync_ros_slave2_ = NULL;
85  }
86  if (sync_ros_slave3_) {
87  delete sync_ros_slave3_;
88  sync_ros_slave3_ = NULL;
89  }
90 }
91 
92 void PdsNode::lcmRecvStatus(const lcm::ReceiveBuffer* buf, const std::string &chan, const status_t *lcm) {
93 #if 0
94  ROS_INFO("Received LCM message from channel '%s'", chan.c_str());
95 #endif
96 
97  // Timestamp
98  const ros::Time now = ros::Time::now();
99 
100  // Convert to ROS message
101  dataspeed_pds_msgs::Status msg;
102  msg.header.stamp = now;
103  msg.mode.mode = (uint8_t)lcm->mode;
104  msg.script.script = (uint8_t)lcm->script;
105  msg.chan.resize(12);
106  for (size_t i = 0; i < 12; i++) {
107  msg.chan[i].current = lcm->current[i];
108  msg.chan[i].status = lcm->status[i];
109  }
110  msg.master.inverter.request = (lcm->inverter_status & (1 << 0)) ? true : false;
111  msg.master.inverter.status = (lcm->inverter_status & (1 << 1)) ? true : false;
112  msg.master.inverter.overload = (lcm->inverter_status & (1 << 2)) ? true : false;
113  msg.master.inverter.overtemp = (lcm->inverter_status & (1 << 3)) ? true : false;
114  for (size_t i = 0; i < sizeof(lcm->board_temp)/sizeof(lcm->board_temp[0]); i++) {
115  msg.master.temp.internal[i] = lcm->board_temp[i];
116  }
117  for (size_t i = 0; i < sizeof(lcm->thermocouple)/sizeof(lcm->thermocouple[0]); i++) {
118  msg.master.temp.external[i] = lcm->thermocouple[i];
119  }
120  msg.master.voltage = lcm->voltage;
121 
122  // Publish for single unit, or forward to multi-unit synchronization
123  const dataspeed_pds_msgs::Status::ConstPtr ptr(new dataspeed_pds_msgs::Status(msg));
124  switch (lcm->unit_id) {
125  case MASTER:
126  sync_msg_master_.add(ptr);
127  if ((now - stamp_slave1_) > TIMEOUT) {
128  pub_status_.publish(msg);
129  }
130  break;
131  case SLAVE1:
132  stamp_slave1_ = now;
133  sync_msg_slave1_.add(ptr);
134  break;
135  case SLAVE2:
136  stamp_slave2_ = now;
137  sync_msg_slave2_.add(ptr);
138  break;
139  case SLAVE3:
140  stamp_slave3_ = now;
141  sync_msg_slave3_.add(ptr);
142  break;
143  }
144 }
145 
146 void PdsNode::recvRelay(const dataspeed_pds_msgs::Relay::ConstPtr &msg)
147 {
148  relay_request_t out;
149  out.channel = msg->channel;
150  out.request = msg->request;
151  lcm_.publish("RELAY", &out);
152 }
153 
154 void PdsNode::recvMode(const dataspeed_pds_msgs::Mode::ConstPtr &msg)
155 {
156  mode_t out;
157  out.mode = msg->mode;
158  lcm_.publish("MODE", &out);
159 }
160 
161 void PdsNode::recvScript(const dataspeed_pds_msgs::Script::ConstPtr &msg)
162 {
163  script_request_t out;
164  out.script = msg->script;
165  lcm_.publish("SCRIPT", &out);
166 }
167 
168 void PdsNode::recvSyncSlave1(const SyncPtr& master, const SyncPtr& slave1)
169 {
170  if ((ros::Time::now() - stamp_slave2_) > TIMEOUT) {
171  dataspeed_pds_msgs::Status msg = *master;
172  msg.chan.insert(msg.chan.end(), slave1->chan.begin(), slave1->chan.end());
173  msg.slave.push_back(slave1->master);
174  pub_status_.publish(msg);
175  }
176 }
177 void PdsNode::recvSyncSlave2(const SyncPtr& master, const SyncPtr& slave1, const SyncPtr& slave2)
178 {
179  if ((ros::Time::now() - stamp_slave3_) > TIMEOUT) {
180  dataspeed_pds_msgs::Status msg = *master;
181  msg.chan.insert(msg.chan.end(), slave1->chan.begin(), slave1->chan.end());
182  msg.chan.insert(msg.chan.end(), slave2->chan.begin(), slave2->chan.end());
183  msg.slave.push_back(slave1->master);
184  msg.slave.push_back(slave2->master);
185  pub_status_.publish(msg);
186  }
187 }
188 void PdsNode::recvSyncSlave3(const SyncPtr& master, const SyncPtr& slave1, const SyncPtr& slave2, const SyncPtr& slave3)
189 {
190  if (1) { // There is no slave4
191  dataspeed_pds_msgs::Status msg = *master;
192  msg.chan.insert(msg.chan.end(), slave1->chan.begin(), slave1->chan.end());
193  msg.chan.insert(msg.chan.end(), slave2->chan.begin(), slave2->chan.end());
194  msg.chan.insert(msg.chan.end(), slave3->chan.begin(), slave3->chan.end());
195  msg.slave.push_back(slave1->master);
196  msg.slave.push_back(slave2->master);
197  msg.slave.push_back(slave3->master);
198  pub_status_.publish(msg);
199  }
200 }
201 
202 } // namespace dataspeed_pds_lcm
203 
dataspeed_pds_lcm::PdsNode::stamp_slave2_
ros::Time stamp_slave2_
Definition: PdsNode.h:124
PdsNode.h
dataspeed_pds_lcm::PdsNode::sync_ros_slave3_
message_filters::Synchronizer< SyncPolicy3 > * sync_ros_slave3_
Definition: PdsNode.h:135
message_filters::Synchronizer
dataspeed_pds_lcm::PdsNode::sync_msg_slave2_
message_filters::PassThrough< SyncMsg > sync_msg_slave2_
Definition: PdsNode.h:138
dataspeed_pds_lcm::PdsNode::recvScript
void recvScript(const dataspeed_pds_msgs::Script::ConstPtr &msg)
Definition: PdsNode.cpp:193
dataspeed_pds_lcm::PdsNode::pub_status_
ros::Publisher pub_status_
Definition: PdsNode.h:120
dataspeed_pds_lcm::PdsNode::sub_script_
ros::Subscriber sub_script_
Definition: PdsNode.h:117
ros::TransportHints
dataspeed_pds_lcm::TIMEOUT
const ros::Duration TIMEOUT(0.5)
dataspeed_pds_lcm::SLAVE1
@ SLAVE1
Definition: PdsNode.h:127
dataspeed_pds_lcm::PdsNode::sub_mode_
ros::Subscriber sub_mode_
Definition: PdsNode.h:116
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
ros::TransportHints::tcpNoDelay
TransportHints & tcpNoDelay(bool nodelay=true)
dataspeed_pds_lcm::PdsNode::SyncPolicy3
message_filters::sync_policies::ApproximateTime< SyncMsg, SyncMsg, SyncMsg, SyncMsg > SyncPolicy3
Definition: PdsNode.h:132
dataspeed_pds_lcm::PdsNode::sync_msg_slave1_
message_filters::PassThrough< SyncMsg > sync_msg_slave1_
Definition: PdsNode.h:137
dataspeed_pds_lcm::PdsNode::lcm_
lcm::LCM lcm_
Definition: PdsNode.h:145
dataspeed_pds_lcm::PdsNode::recvSyncSlave1
void recvSyncSlave1(const SyncPtr &master, const SyncPtr &slave1)
Definition: PdsNode.cpp:200
dataspeed_pds_lcm::PdsNode::sub_relay_
ros::Subscriber sub_relay_
Definition: PdsNode.h:115
dataspeed_pds_lcm::SLAVE2
@ SLAVE2
Definition: PdsNode.h:128
dataspeed_pds_lcm::PdsNode::sync_msg_slave3_
message_filters::PassThrough< SyncMsg > sync_msg_slave3_
Definition: PdsNode.h:139
dataspeed_pds_lcm::PdsNode::SyncPolicy1
message_filters::sync_policies::ApproximateTime< SyncMsg, SyncMsg > SyncPolicy1
Definition: PdsNode.h:130
dataspeed_pds_lcm::PdsNode::sync_ros_slave2_
message_filters::Synchronizer< SyncPolicy2 > * sync_ros_slave2_
Definition: PdsNode.h:134
dataspeed_pds_lcm::PdsNode::recvSyncSlave2
void recvSyncSlave2(const SyncPtr &master, const SyncPtr &slave1, const SyncPtr &slave2)
Definition: PdsNode.cpp:209
dataspeed_pds_lcm::PdsNode::recvMode
void recvMode(const dataspeed_pds_msgs::Mode::ConstPtr &msg)
Definition: PdsNode.cpp:186
dataspeed_pds_lcm::PdsNode::~PdsNode
~PdsNode()
Definition: PdsNode.cpp:108
message_filters::PassThrough::add
void add(const EventType &evt)
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
dataspeed_pds_lcm::PdsNode::lcmRecvStatus
void lcmRecvStatus(const lcm::ReceiveBuffer *buf, const std::string &chan, const status_t *lcm)
Definition: PdsNode.cpp:124
dataspeed_pds_lcm::PdsNode::stamp_slave1_
ros::Time stamp_slave1_
Definition: PdsNode.h:123
ros::Time
dataspeed_pds_lcm
Definition: nodelet.cpp:40
dataspeed_pds_lcm::PdsNode::recvSyncSlave3
void recvSyncSlave3(const SyncPtr &master, const SyncPtr &slave1, const SyncPtr &slave2, const SyncPtr &slave3)
Definition: PdsNode.cpp:220
dataspeed_pds_lcm::SLAVE3
@ SLAVE3
Definition: PdsNode.h:129
dataspeed_pds_lcm::MASTER
@ MASTER
Definition: PdsNode.h:126
dataspeed_pds_lcm::PdsNode::recvRelay
void recvRelay(const dataspeed_pds_msgs::Relay::ConstPtr &msg)
Definition: PdsNode.cpp:178
ROS_INFO
#define ROS_INFO(...)
dataspeed_pds_lcm::PdsNode::stamp_slave3_
ros::Time stamp_slave3_
Definition: PdsNode.h:125
dataspeed_pds_lcm::PdsNode::PdsNode
PdsNode(ros::NodeHandle &node, ros::NodeHandle &priv_nh, lcm::LCM *lcm)
Definition: PdsNode.cpp:72
dataspeed_pds_lcm::PdsNode::SyncPolicy2
message_filters::sync_policies::ApproximateTime< SyncMsg, SyncMsg, SyncMsg > SyncPolicy2
Definition: PdsNode.h:131
ros::Duration
dataspeed_pds_lcm::PdsNode::sync_msg_master_
message_filters::PassThrough< SyncMsg > sync_msg_master_
Definition: PdsNode.h:136
dataspeed_pds_lcm::PdsNode::sync_ros_slave1_
message_filters::Synchronizer< SyncPolicy1 > * sync_ros_slave1_
Definition: PdsNode.h:133
ros::NodeHandle
ros::Time::now
static Time now()


dataspeed_pds_lcm
Author(s): Kevin Hallenbeck , Eric Myllyoja , Michael Lohrer
autogenerated on Wed Mar 2 2022 00:11:47