00001
00002
00003 #include <stdio.h>
00004 #include <string.h>
00005 #include <fcntl.h>
00006 #include <sys/ioctl.h>
00007 #include <net/if.h>
00008 #include <linux/can.h>
00009 #include <linux/can/raw.h>
00010 #include <ros/ros.h>
00011 #include <geometry_msgs/Twist.h>
00012 #include <geometry_msgs/Point.h>
00013 #include <geometry_msgs/Quaternion.h>
00014 #include <nav_msgs/Odometry.h>
00015 #include <sensor_msgs/Joy.h>
00016 #include <std_msgs/Float32.h>
00017 #include <tf/transform_broadcaster.h>
00018 #include <boost/thread/thread.hpp>
00019 #include <boost/thread/mutex.hpp>
00020
00021
00022
00023 void publishJoyMsg();
00024 void publishOdomMsg();
00025 void publishVoltageMsg();
00026
00027
00028 int can_socket;
00029
00030 double battery_voltage = 0;
00031 double odom_orientation = 0;
00032 double odom_pos_x = 0;
00033 double odom_pos_y = 0;
00034
00035 uint8_t remote_buttons[8];
00036 uint8_t remote_analog[8];
00037
00038 ros::Publisher publisherOdom;
00039 ros::Publisher publisherJoy;
00040 ros::Publisher publisherVoltage;
00041
00042 boost::mutex ros_mutex;
00043 bool can_running = false;
00044
00045 int can_open(const char * device)
00046 {
00047 struct ifreq ifr;
00048 struct sockaddr_can addr;
00049
00050 can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
00051 if(can_socket < 0)
00052 {
00053 return (-1);
00054 }
00055 addr.can_family = AF_CAN;
00056 strcpy(ifr.ifr_name, device);
00057
00058 if (ioctl(can_socket, SIOCGIFINDEX, &ifr) < 0)
00059 {
00060 return (-2);
00061 }
00062 addr.can_ifindex = ifr.ifr_ifindex;
00063
00064
00065
00066 if (bind(can_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0)
00067 {
00068 return (-3);
00069 }
00070
00071 struct timeval tv;
00072 tv.tv_sec = 1;
00073 tv.tv_usec = 0;
00074 setsockopt(can_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
00075
00076 return 0;
00077 }
00078
00079 int can_send_frame(struct can_frame * frame)
00080 {
00081 int retval;
00082 retval = write(can_socket, frame, sizeof(struct can_frame));
00083 if (retval != sizeof(struct can_frame))
00084 {
00085 return (-1);
00086 }
00087 else
00088 {
00089 return (0);
00090 }
00091 }
00092
00093 int can_send_cmd_vel(double speed, double yawspeed, int modestate = 3)
00094 {
00095 struct can_frame msg_send;
00096
00097 msg_send.can_id = 200;
00098 msg_send.can_dlc = 5;
00099
00100 int int_speed = speed * 100;
00101 int int_yaw = yawspeed * 100;
00102 msg_send.data[0] = int_speed;
00103 msg_send.data[1] = int_speed >> 8;
00104 msg_send.data[2] = int_yaw;
00105 msg_send.data[3] = int_yaw >> 8;
00106 msg_send.data[4] = modestate;
00107
00108 can_send_frame(&msg_send);
00109 }
00110
00111
00112 void can_read_frames()
00113 {
00114 struct can_frame frame_rd;
00115 while(read(can_socket, &frame_rd, sizeof(struct can_frame))>0)
00116 {
00117
00118 if (frame_rd.can_id == 0x1E4)
00119 {
00120 for (int i = 0; i < 8; i++)
00121 remote_analog[i] = frame_rd.data[i];
00122 }
00123 else if(frame_rd.can_id == 0x2E4)
00124 {
00125 for (int i = 0; i < 8; i++)
00126 remote_buttons[i] = frame_rd.data[i];
00127 publishJoyMsg();
00128 }
00129 else if (frame_rd.can_id == 235)
00130 {
00131 battery_voltage = (frame_rd.data[1]|(frame_rd.data[2]<<8))*0.01;
00132 publishVoltageMsg();
00133 }
00134 else if (frame_rd.can_id == 236)
00135 {
00136 odom_pos_x = (frame_rd.data[0]|(frame_rd.data[1]<<8)|(frame_rd.data[2]<<16)|(frame_rd.data[3]<<24))*0.001;
00137 odom_pos_y = (frame_rd.data[4]|(frame_rd.data[5]<<8)|(frame_rd.data[6]<<16)|(frame_rd.data[7]<<24))*0.001;
00138 }
00139 else if (frame_rd.can_id == 237)
00140 {
00141 odom_orientation = (frame_rd.data[0]|(frame_rd.data[1]<<8)|(frame_rd.data[2]<<16)|(frame_rd.data[3]<<24))*0.001;
00142 publishOdomMsg();
00143 }
00144 }
00145 }
00146
00147 void publishOdomMsg()
00148 {
00149 static tf::TransformBroadcaster tf_br;
00150
00151 geometry_msgs::Quaternion odom_quaternion = tf::createQuaternionMsgFromYaw(odom_orientation);
00152
00153 nav_msgs::Odometry odom_msg;
00154 odom_msg.header.stamp = ros::Time::now();
00155 odom_msg.header.frame_id = "/odom";
00156 odom_msg.child_frame_id = "/base_link";
00157 odom_msg.pose.pose.position.x = odom_pos_x;
00158 odom_msg.pose.pose.position.y = odom_pos_y;
00159 odom_msg.pose.pose.orientation = odom_quaternion;
00160
00161
00162 double odom_covariance[] = {0.1, 0, 0, 0, 0, 0,
00163 0, 0.1, 0, 0, 0, 0,
00164 0, 0, 9999.0, 0, 0, 0,
00165 0, 0, 0, 0.6, 0, 0,
00166 0, 0, 0, 0, 0.6, 0,
00167 0, 0, 0, 0, 0, 0.1};
00168 for(int i=0; i<36; i++)
00169 {
00170 odom_msg.pose.covariance[i] = odom_covariance[i];
00171 }
00172
00173
00174 publisherOdom.publish(odom_msg);
00175
00176
00177 geometry_msgs::TransformStamped odom_trans;
00178 odom_trans.header.stamp = odom_msg.header.stamp;
00179 odom_trans.header.frame_id = odom_msg.header.frame_id;
00180 odom_trans.child_frame_id = odom_msg.child_frame_id;
00181
00182 odom_trans.transform.translation.x = odom_pos_x;
00183 odom_trans.transform.translation.y = odom_pos_y;
00184 odom_trans.transform.translation.z = 0.0;
00185 odom_trans.transform.rotation = odom_quaternion;
00186
00187 ros_mutex.lock();
00188 tf_br.sendTransform(odom_trans);
00189 ros_mutex.unlock();
00190 }
00191
00192 void publishVoltageMsg()
00193 {
00194 std_msgs::Float32 voltage_msg;
00195 voltage_msg.data = battery_voltage;
00196 ros_mutex.lock();
00197 publisherVoltage.publish(voltage_msg);
00198 ros_mutex.unlock();
00199 }
00200
00201 void publishJoyMsg()
00202 {
00203 sensor_msgs::Joy rc_msg;
00204
00205
00206 for(int i=0; i<=8; i++)
00207 {
00208 rc_msg.axes.push_back( (remote_analog[i] - 127) / 127.0);
00209 }
00210
00211
00212 for(int i=0; i<=8; i++)
00213 {
00214 for(int bit=0; bit<=8; bit++)
00215 {
00216 if(remote_buttons[i] & (1 << bit))
00217 rc_msg.buttons.push_back(bool(true));
00218 else
00219 rc_msg.buttons.push_back(bool(false));
00220 }
00221 }
00222 ros_mutex.lock();
00223 publisherJoy.publish(rc_msg);
00224 ros_mutex.unlock();
00225 }
00226
00227 void cmdVelCallback(const geometry_msgs::Twist::ConstPtr& msg)
00228 {
00229 ROS_DEBUG("received cmd_vel s=%f y=%f", msg->linear.x, msg->angular.z);
00230 can_send_cmd_vel(msg->linear.x, msg->angular.z);
00231 }
00232
00233 void can_task()
00234 {
00235 can_running = true;
00236 while(can_running)
00237 {
00238 can_read_frames();
00239 }
00240 }
00241
00242 int main(int argc, char **argv)
00243 {
00244 ros::init(argc, argv, "innok_heros_can_driver");
00245 ros::NodeHandle n;
00246 ros::Subscriber Sub = n.subscribe("cmd_vel", 10, cmdVelCallback);
00247
00248 publisherOdom = n.advertise<nav_msgs::Odometry>("odom", 20);
00249 publisherVoltage = n.advertise<std_msgs::Float32>("battery_voltage", 1);
00250 publisherJoy = n.advertise<sensor_msgs::Joy>("remote_joy", 1);
00251
00252 can_open("can0");
00253
00254 boost::thread can_thread(can_task);
00255
00256 while (ros::ok())
00257 {
00258 ros_mutex.lock();
00259 ros::spinOnce();
00260 ros_mutex.unlock();
00261 }
00262 can_running = false;
00263 can_thread.join();
00264 return 0;
00265 }