├── CMakeLists.txt ├── README.md ├── launch └── demo.launch ├── package.xml └── src └── mpu6050_serial_to_imu_node.cpp /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(imu_serial_node) 3 | 4 | 5 | find_package(catkin REQUIRED COMPONENTS 6 | roscpp 7 | geometry_msgs 8 | sensor_msgs 9 | serial 10 | std_msgs 11 | std_srvs 12 | tf 13 | ) 14 | 15 | 16 | include_directories( 17 | ${catkin_INCLUDE_DIRS} 18 | ) 19 | 20 | add_executable(imu_serial_node src/mpu6050_serial_to_imu_node.cpp) 21 | target_link_libraries(imu_serial_node ${catkin_LIBRARIES} ) 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | imu_serial_node 2 | = 3 | a simple ros serial node for imu, such as mpu 6050. 4 | 5 | you should change it by your serial Communication protocol. 6 | this package depend on serial: http://wiki.ros.org/rosserial/ 7 | 8 | #### Published Topics 9 | 10 | * **`imu`** ([sensor_msgs::Imu]) 11 | 12 | The resulting Imu orientation. 13 | 14 | #### Published TF Transforms 15 | 16 | * The resulting orientation is published as a tf transform, the frame names can be set using the parameters. 17 | 18 | 19 | #### Services 20 | 21 | * **`set_zero_orientation`** ([std_srvs/Empty]) 22 | 23 | This service sets the current orientation as the new zero orientation so that from now on only the difference to this orientation is sent. 24 | 25 | 26 | #### Parameters 27 | 28 | * **`port`** (string, default: "/dev/ttyACM0") 29 | 30 | The name of the serial port. 31 | 32 | * **`time_offset_in_seconds`** (double, default: 0.0) 33 | 34 | This sets an offset which is added to the header timestamp of the imu-topic and the TF transforms. This can be used to synchronise the IMUs orientation values to values of another sensor. 35 | 36 | 37 | * **`imu_frame_id`** (string, default: "imu_base") 38 | 39 | Sets the name of the base frame for imu messages. 40 | 41 | 42 | * **`tf_parent_frame_id`** (string, default: "imu_base") 43 | 44 | Sets the name of the parent frame in the tf transform. 45 | 46 | 47 | * **`tf_frame_id`** (string, default: "imu") 48 | 49 | Sets the name of the own frame in the tf transform. 50 | -------------------------------------------------------------------------------- /launch/demo.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | imu_serial_node 4 | 0.0.1 5 | The mpu6050_serial_to_imu package 6 | 7 | kint.zhao 8 | 9 | 10 | BSD 11 | 12 | 13 | catkin 14 | roscpp 15 | geometry_msgs 16 | sensor_msgs 17 | serial 18 | std_msgs 19 | std_srvs 20 | tf 21 | roscpp 22 | geometry_msgs 23 | sensor_msgs 24 | serial 25 | std_msgs 26 | std_srvs 27 | tf 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/mpu6050_serial_to_imu_node.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | bool zero_orientation_set = false; 13 | 14 | bool set_zero_orientation(std_srvs::Empty::Request&, 15 | std_srvs::Empty::Response&) 16 | { 17 | ROS_INFO("Zero Orientation Set."); 18 | zero_orientation_set = false; 19 | return true; 20 | } 21 | 22 | bool DecodeIMUData(double result[], unsigned char chrTemp[], unsigned char mode ) 23 | { 24 | int scale; 25 | if( chrTemp[1] = mode) 26 | { 27 | switch(mode) 28 | { 29 | case 0x51: scale = 16; //a 30 | break; 31 | case 0x52: scale = 16; //w 32 | break; 33 | case 0x53: scale = 2000;//angle 34 | break; 35 | } 36 | result[0] = (short(chrTemp[3]<<8|chrTemp[2]))/32768.0*scale; 37 | result[1] = (short(chrTemp[5]<<8|chrTemp[4]))/32768.0*scale; 38 | result[2] = (short(chrTemp[7]<<8|chrTemp[6]))/32768.0*scale; 39 | 40 | // double T = (short(chrTemp[9]<<8|chrTemp[8]))/340.0+36.25; 41 | printf("aresult = %4.3f\t%4.3f\t%4.3f\t\r\n",result[0],result[1],result[2]); 42 | return true; 43 | } 44 | return false; 45 | } 46 | 47 | int main(int argc, char** argv) 48 | { 49 | serial::Serial ser; 50 | std::string port; 51 | std::string tf_parent_frame_id; 52 | std::string tf_frame_id; 53 | std::string imu_frame_id; 54 | double time_offset_in_seconds; 55 | 56 | tf::Quaternion zero_orientation; 57 | 58 | ros::init(argc, argv, "imu_serial_node"); 59 | 60 | ros::NodeHandle private_node_handle("~"); 61 | private_node_handle.param("port", port, "/dev/ttyUSB0"); 62 | private_node_handle.param("tf_parent_frame_id", tf_parent_frame_id, "imu_base"); 63 | private_node_handle.param("tf_frame_id", tf_frame_id, "imu"); 64 | private_node_handle.param("imu_frame_id", imu_frame_id, "imu_base"); 65 | private_node_handle.param("time_offset_in_seconds", time_offset_in_seconds, 0.0); 66 | 67 | ros::NodeHandle nh; 68 | ros::Publisher imu_pub = nh.advertise("imu", 100); 69 | ros::ServiceServer service = nh.advertiseService("set_zero_orientation", set_zero_orientation); 70 | 71 | ros::Rate r(100); // 1000 hz 72 | 73 | unsigned char chrBuffer[1000]; 74 | unsigned char chrTemp[1000]; 75 | unsigned short usLength=0,usRxLength=0; 76 | 77 | while(ros::ok()) 78 | { 79 | try 80 | { 81 | if (ser.isOpen()) 82 | { 83 | // read string from serial device 84 | if(ser.available()) 85 | { 86 | usLength = ser.read(chrBuffer,33); 87 | if (usLength>0) 88 | { 89 | usRxLength += usLength; 90 | while (usRxLength >= 11) 91 | { 92 | memcpy(chrTemp,chrBuffer,usRxLength); 93 | if (!((chrTemp[0] == 0x55) & ((chrTemp[1] == 0x51) | (chrTemp[1] == 0x52) | (chrTemp[1] == 0x53)))) 94 | { 95 | for (int i = 1; i < usRxLength; i++) chrBuffer[i - 1] = chrBuffer[i]; 96 | usRxLength--; 97 | continue; 98 | } 99 | double* Angle; 100 | if(!DecodeIMUData(Angle, chrTemp, 0X53)) 101 | continue; 102 | 103 | tf::Quaternion orientation(Angle[2],Angle[1],Angle[0]); 104 | 105 | if (!zero_orientation_set) 106 | { 107 | zero_orientation = orientation; 108 | zero_orientation_set = true; 109 | } 110 | 111 | tf::Quaternion differential_rotation; 112 | differential_rotation = zero_orientation.inverse() * orientation; 113 | 114 | // calculate measurement time 115 | ros::Time measurement_time = ros::Time::now() + ros::Duration(time_offset_in_seconds); 116 | 117 | // publish imu message 118 | sensor_msgs::Imu imu; 119 | imu.header.stamp = measurement_time; 120 | imu.header.frame_id = imu_frame_id; 121 | 122 | quaternionTFToMsg(differential_rotation, imu.orientation); 123 | 124 | // i do not know the orientation covariance 125 | imu.orientation_covariance[0] = 1000000; 126 | imu.orientation_covariance[1] = 0; 127 | imu.orientation_covariance[2] = 0; 128 | imu.orientation_covariance[3] = 0; 129 | imu.orientation_covariance[4] = 1000000; 130 | imu.orientation_covariance[5] = 0; 131 | imu.orientation_covariance[6] = 0; 132 | imu.orientation_covariance[7] = 0; 133 | imu.orientation_covariance[8] = 0.000001; 134 | 135 | // angular velocity is not provided 136 | imu.angular_velocity_covariance[0] = -1; 137 | 138 | // linear acceleration is not provided 139 | imu.linear_acceleration_covariance[0] = -1; 140 | 141 | imu_pub.publish(imu); 142 | 143 | // publish tf transform 144 | static tf::TransformBroadcaster br; 145 | tf::Transform transform; 146 | transform.setRotation(differential_rotation); 147 | br.sendTransform(tf::StampedTransform(transform, measurement_time, tf_parent_frame_id, tf_frame_id)); 148 | 149 | for (int i = 11; i < usRxLength; i++) 150 | chrBuffer[i - 11] = chrBuffer[i]; 151 | usRxLength -= 11; 152 | } 153 | } 154 | } 155 | else // ser not available 156 | { 157 | 158 | } 159 | } 160 | else 161 | { 162 | // try and open the serial port 163 | try 164 | { 165 | ser.setPort(port); 166 | ser.setBaudrate(115200); 167 | serial::Timeout to = serial::Timeout::simpleTimeout(1000); 168 | ser.setTimeout(to); 169 | ser.open(); 170 | } 171 | catch (serial::IOException& e) 172 | { 173 | ROS_ERROR_STREAM("Unable to open serial port " << ser.getPort() << ". Trying again in 5 seconds."); 174 | ros::Duration(5).sleep(); 175 | } 176 | 177 | if(ser.isOpen()) 178 | { 179 | ROS_DEBUG_STREAM("Serial port " << ser.getPort() << " initialized."); 180 | } 181 | else 182 | { 183 | //ROS_INFO_STREAM("Could not initialize serial port."); 184 | } 185 | 186 | } 187 | } 188 | catch (serial::IOException& e) 189 | { 190 | ROS_ERROR_STREAM("Error reading from the serial port " << ser.getPort() << ". Closing connection."); 191 | ser.close(); 192 | } 193 | ros::spinOnce(); 194 | r.sleep(); 195 | } 196 | 197 | } 198 | 199 | --------------------------------------------------------------------------------