kvaser_can_bridge.cpp
Go to the documentation of this file.
1 /*
2 * Unpublished Copyright (c) 2009-2017 AutonomouStuff, LLC, All Rights Reserved.
3 *
4 * This file is part of the Kvaser ROS 1.0 driver which is released under the MIT license.
5 * See file LICENSE included with this software or go to https://opensource.org/licenses/MIT for full license details.
6 */
7 
8 #include <thread>
9 #include <mutex>
10 #include <chrono>
11 
12 #include <ros/ros.h>
13 #include <kvaser_interface.h>
14 #include <can_msgs/Frame.h>
15 
16 using namespace AS::CAN;
17 
18 int bit_rate = 500000;
19 int hardware_id = 0;
20 int circuit_id = 0;
21 bool global_keep_going = true;
22 std::mutex keep_going_mut;
25 
26 void can_read()
27 {
28  long id;
29  uint8_t msg[8];
30  unsigned int size;
31  bool extended;
32  unsigned long t;
33 
34  const std::chrono::milliseconds loop_pause = std::chrono::milliseconds(10);
35  bool keep_going = true;
36 
37  //Set local to global value before looping.
38  keep_going_mut.lock();
39  keep_going = global_keep_going;
40  keep_going_mut.unlock();
41 
42  return_statuses ret;
43 
44  while (keep_going)
45  {
46  std::chrono::system_clock::time_point next_time = std::chrono::system_clock::now();
47  next_time += loop_pause;
48 
49  if (!can_reader.is_open())
50  {
51  ret = can_reader.open(hardware_id, circuit_id, bit_rate, false);
52 
53  if (ret != OK)
54  ROS_ERROR_THROTTLE(0.5, "Kvaser CAN Interface - Error opening reader: %d - %s", ret, return_status_desc(ret).c_str());
55  }
56  else
57  {
58  while ((ret = can_reader.read(&id, msg, &size, &extended, &t)) == OK)
59  {
60  can_msgs::Frame can_pub_msg;
61  can_pub_msg.header.frame_id = "0";
62  can_pub_msg.id = id;
63  can_pub_msg.dlc = size;
64  std::copy(msg, msg + 8, can_pub_msg.data.begin());
65  can_pub_msg.header.stamp = ros::Time::now();
66  can_tx_pub.publish(can_pub_msg);
67  }
68 
69  if (ret != NO_MESSAGES_RECEIVED)
70  ROS_WARN_THROTTLE(0.5, "Kvaser CAN Interface - Error reading CAN message: %d - %s", ret, return_status_desc(ret).c_str());
71  }
72 
73  std::this_thread::sleep_until(next_time);
74 
75  //Set local to global immediately before next loop.
76  keep_going_mut.lock();
77  keep_going = global_keep_going;
78  keep_going_mut.unlock();
79  }
80 
81  if (can_reader.is_open())
82  {
83  ret = can_reader.close();
84 
85  if (ret != OK)
86  ROS_ERROR_THROTTLE(0.5, "Kvaser CAN Interface - Error closing reader: %d - %s", ret, return_status_desc(ret).c_str());
87  }
88 }
89 
90 void can_rx_callback(const can_msgs::Frame::ConstPtr& msg)
91 {
92  return_statuses ret;
93 
94  if (!can_writer.is_open())
95  {
96  // Open the channel.
97  ret = can_writer.open(hardware_id, circuit_id, bit_rate, false);
98 
99  if (ret != OK)
100  {
101  ROS_ERROR_THROTTLE(0.5, "Kvaser CAN Interface - Error opening writer: %d - %s", ret, return_status_desc(ret).c_str());
102  }
103  }
104 
105  if (can_writer.is_open())
106  {
107  ret = can_writer.write(msg->id, const_cast<unsigned char*>(&(msg->data[0])), msg->dlc, msg->is_extended);
108 
109  if (ret != OK)
110  ROS_WARN_THROTTLE(0.5, "Kvaser CAN Interface - CAN send error: %d - %s", ret, return_status_desc(ret).c_str());
111  }
112 }
113 
114 int main(int argc, char** argv)
115 {
116  bool exit = false;
117 
118  // ROS initialization
119  ros::init(argc, argv, "kvaser_can_bridge");
120  ros::NodeHandle n;
121  ros::NodeHandle priv("~");
122  ros::AsyncSpinner spinner(1);
123 
124  can_tx_pub = n.advertise<can_msgs::Frame>("can_tx", 500);
125 
126  ros::Subscriber can_rx_sub = n.subscribe("can_rx", 500, can_rx_callback);
127 
128  // Wait for time to be valid
129  while (ros::Time::now().nsec == 0);
130 
131  if (priv.getParam("can_hardware_id", hardware_id))
132  {
133  ROS_INFO("Kvaser CAN Interface - Got hardware_id: %d", hardware_id);
134 
135  if (hardware_id <= 0)
136  {
137  ROS_ERROR("Kvaser CAN Interface - CAN hardware ID is invalid.");
138  exit = true;
139  }
140  }
141 
142  if (priv.getParam("can_circuit_id", circuit_id))
143  {
144  ROS_INFO("Kvaser CAN Interface - Got can_circuit_id: %d", circuit_id);
145 
146  if (circuit_id < 0)
147  {
148  ROS_ERROR("Kvaser CAN Interface - Circuit ID is invalid.");
149  exit = true;
150  }
151  }
152 
153  if (priv.getParam("can_bit_rate", bit_rate))
154  {
155  ROS_INFO("Kvaser CAN Interface - Got bit_rate: %d", bit_rate);
156 
157  if (bit_rate < 0)
158  {
159  ROS_ERROR("Kvaser CAN Interface - Bit Rate is invalid.");
160  exit = true;
161  }
162  }
163 
164  if (exit)
165  return 0;
166 
167  // Start CAN receiving thread.
168  std::thread can_read_thread(can_read);
169 
170  spinner.start();
171 
173 
174  return_statuses ret = can_writer.close();
175 
176  if (ret != OK)
177  ROS_ERROR("Kvaser CAN Interface - Error closing writer: %d - %s", ret, return_status_desc(ret).c_str());
178 
179  keep_going_mut.lock();
180  global_keep_going = false;
181  keep_going_mut.unlock();
182 
183  can_read_thread.join();
184 
185  return 0;
186 }
bool global_keep_going
#define ROS_WARN_THROTTLE(rate,...)
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
KvaserCan can_writer
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
return_statuses close()
Definition: linuxcan.cpp:141
int main(int argc, char **argv)
int hardware_id
void can_read()
#define ROS_ERROR_THROTTLE(rate,...)
void can_rx_callback(const can_msgs::Frame::ConstPtr &msg)
#define ROS_INFO(...)
int bit_rate
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
return_statuses open(const int &hardware_id, const int &circuit_id, const int &bitrate, const bool &echo_on=true)
Definition: linuxcan.cpp:32
std::mutex keep_going_mut
int circuit_id
bool getParam(const std::string &key, std::string &s) const
static Time now()
return_statuses read(long *id, unsigned char *msg, unsigned int *size, bool *extended, unsigned long *time)
Definition: linuxcan.cpp:161
#define ROS_ERROR(...)
KvaserCan can_reader
ROSCPP_DECL void waitForShutdown()
ros::Publisher can_tx_pub
return_statuses write(const long &id, unsigned char *msg, const unsigned int &size, const bool &extended)
Definition: linuxcan.cpp:216
std::string return_status_desc(const return_statuses &ret)
Definition: utils.cpp:10


kvaser_interface
Author(s): Joshua Whitley , Daniel Stanek
autogenerated on Wed Jun 19 2019 19:36:17