diff --git a/Robot_Development/catkin_ws/CMakeLists.txt b/Robot_Development/catkin_ws/CMakeLists.txt new file mode 120000 index 0000000000000000000000000000000000000000..581e61db89fce59006b1ceb2d208d9f3e5fbcb5e --- /dev/null +++ b/Robot_Development/catkin_ws/CMakeLists.txt @@ -0,0 +1 @@ +/opt/ros/kinetic/share/catkin/cmake/toplevel.cmake \ No newline at end of file diff --git a/Robot_Development/catkin_ws/lane_demo/CMakeLists.txt b/Robot_Development/catkin_ws/lane_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..07b7f8379226146209aa725e4992ef2b9e854397 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/CMakeLists.txt @@ -0,0 +1,204 @@ +cmake_minimum_required(VERSION 2.8.3) +project(lane_demo) + +## Compile as C++11, supported in ROS Kinetic and newer +# add_compile_options(-std=c++11) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED COMPONENTS + roscpp + rospy + std_msgs +) + +## System dependencies are found with CMake's conventions +# find_package(Boost REQUIRED COMPONENTS system) + + +## Uncomment this if the package has a setup.py. This macro ensures +## modules and global scripts declared therein get installed +## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html +# catkin_python_setup() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +## To declare and build messages, services or actions from within this +## package, follow these steps: +## * Let MSG_DEP_SET be the set of packages whose message types you use in +## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). +## * In the file package.xml: +## * add a build_depend tag for "message_generation" +## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET +## * If MSG_DEP_SET isn't empty the following dependency has been pulled in +## but can be declared for certainty nonetheless: +## * add a exec_depend tag for "message_runtime" +## * In this file (CMakeLists.txt): +## * add "message_generation" and every package in MSG_DEP_SET to +## find_package(catkin REQUIRED COMPONENTS ...) +## * add "message_runtime" and every package in MSG_DEP_SET to +## catkin_package(CATKIN_DEPENDS ...) +## * uncomment the add_*_files sections below as needed +## and list every .msg/.srv/.action file to be processed +## * uncomment the generate_messages entry below +## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) + +## Generate messages in the 'msg' folder +# add_message_files( +# FILES +# Message1.msg +# Message2.msg +# ) + +## Generate services in the 'srv' folder +# add_service_files( +# FILES +# Service1.srv +# Service2.srv +# ) + +## Generate actions in the 'action' folder +# add_action_files( +# FILES +# Action1.action +# Action2.action +# ) + +## Generate added messages and services with any dependencies listed here +# generate_messages( +# DEPENDENCIES +# std_msgs +# ) + +################################################ +## Declare ROS dynamic reconfigure parameters ## +################################################ + +## To declare and build dynamic reconfigure parameters within this +## package, follow these steps: +## * In the file package.xml: +## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" +## * In this file (CMakeLists.txt): +## * add "dynamic_reconfigure" to +## find_package(catkin REQUIRED COMPONENTS ...) +## * uncomment the "generate_dynamic_reconfigure_options" section below +## and list every .cfg file to be processed + +## Generate dynamic reconfigure parameters in the 'cfg' folder +# generate_dynamic_reconfigure_options( +# cfg/DynReconf1.cfg +# cfg/DynReconf2.cfg +# ) + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if your package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES lane_demo +# CATKIN_DEPENDS roscpp rospy std_msgs +# DEPENDS system_lib +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +include_directories( +# include + include <lane_demo/src/Detection.h> + ${catkin_INCLUDE_DIRS} +) + +## Declare a C++ library +# add_library(${PROJECT_NAME} +# src/${PROJECT_NAME}/lane_demo.cpp +# ) + +## Add cmake target dependencies of the library +## as an example, code may need to be generated before libraries +## either from message generation or dynamic reconfigure +# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Declare a C++ executable +## With catkin_make all packages are built within a single CMake context +## The recommended prefix ensures that target names across packages don't collide +# add_executable(${PROJECT_NAME}_node src/lane_demo_node.cpp) + +## Rename C++ executable without prefix +## The above recommended prefix causes long target names, the following renames the +## target back to the shorter version for ease of user use +## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" +# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") + +## Add cmake target dependencies of the executable +## same as for the library above +# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Specify libraries to link a library or executable target against +# target_link_libraries(${PROJECT_NAME}_node +# ${catkin_LIBRARIES} +# ) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_lane_demo.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) +add_executable(lane_demo src/lane_demo.cpp) +target_link_libraries(lane_demo ${catkin_LIBRARIES}) +set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") + diff --git a/Robot_Development/catkin_ws/lane_demo/Detection.h b/Robot_Development/catkin_ws/lane_demo/Detection.h new file mode 100644 index 0000000000000000000000000000000000000000..066e4c10f4ee06c46d833d05b52c4139040f3232 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/Detection.h @@ -0,0 +1,131 @@ +#include<iostream> +#include<sstream> +#include<string> +#include<iterator> +#include<map> + +using namespace std; + +class Detection { +public: + string _name; + float _prob; + int _cx; + int _cy; + int _w; + int _h; + + Detection() { + + } + Detection(string name, float prob, int cx,int cy, int w, int h) { + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + } + Detection(string serialization) { + string whitespace = removeSpaces(serialization); + cout << whitespace << endl; + string unbraced = whitespace.substr(1, whitespace.length()-2); + cout << unbraced << endl; + string arr[5]; + cout << "OMG OMG OMG OMG " << serialization << endl; + + string str1 = unbraced; + string str2 = "name:"; + string str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "prob:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cx:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cy:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "w:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "h:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + cout << str1 << endl; + + string name = str1.substr(0,str1.find(',')); + cout << name << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + float prob = stof(str1.substr(0,str1.find(','))); + cout << prob << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cx = stoi(str1.substr(0,str1.find(','))); + cout << cx << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cy = stoi(str1.substr(0,str1.find(','))); + cout << cy << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int w = stoi(str1.substr(0,str1.find(','))); + cout << w << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int h = stoi(str1.substr(0,str1.find(','))); + cout << h << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + + } + string removeSpaces(string str) + { + string s = ""; + // To keep track of non-space character count + int count = 0; + + // Traverse the given string. If current character + // is not space, then place it at index 'count++' + for (int i = 0; i < str.length() ; i++) + if (str.at(i) != ' ') + s = s + str.at(i); + // incremented + return s; + } + + template <size_t N> + void splitString(string (&arr)[N], string str) + { + int n = 0; + istringstream iss(str); + for (auto it = istream_iterator<string>(iss); it != istream_iterator<string>() && n < N; ++it, ++n) + arr[n] = *it; + } + + string to_string() { + string s0 = "name:" + _name + ","; + string s1 = "prob:" + std::to_string(_prob) + ","; + string s2 = "cx:" + std::to_string(_cx) + ","; + string s3 = "cy:" + std::to_string(_cy) + ","; + string s4 = "w:" + std::to_string(_w) + ","; + string s5 = "h:" + std::to_string(_h) + ","; + string s = s0 + s1 + s2 + s3 + s4 + s5; + return s; + } +}; + diff --git a/Robot_Development/catkin_ws/lane_demo/package.xml b/Robot_Development/catkin_ws/lane_demo/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..d0a10c03d42892615a9be67a69b78bc2c4d2f6ef --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/package.xml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<package format="2"> + <name>lane_demo</name> + <version>0.0.0</version> + <description>The lane_demo package</description> + + <!-- One maintainer tag required, multiple allowed, one person per tag --> + <!-- Example: --> + <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> + <maintainer email="nvidia@todo.todo">nvidia</maintainer> + + + <!-- One license tag required, multiple allowed, one license per tag --> + <!-- Commonly used license strings: --> + <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> + <license>TODO</license> + + + <!-- Url tags are optional, but multiple are allowed, one per tag --> + <!-- Optional attribute type can be: website, bugtracker, or repository --> + <!-- Example: --> + <!-- <url type="website">http://wiki.ros.org/lane_demo</url> --> + + + <!-- Author tags are optional, multiple are allowed, one per tag --> + <!-- Authors do not have to be maintainers, but could be --> + <!-- Example: --> + <!-- <author email="jane.doe@example.com">Jane Doe</author> --> + + + <!-- The *depend tags are used to specify dependencies --> + <!-- Dependencies can be catkin packages or system dependencies --> + <!-- Examples: --> + <!-- Use depend as a shortcut for packages that are both build and exec dependencies --> + <!-- <depend>roscpp</depend> --> + <!-- Note that this is equivalent to the following: --> + <!-- <build_depend>roscpp</build_depend> --> + <!-- <exec_depend>roscpp</exec_depend> --> + <!-- Use build_depend for packages you need at compile time: --> + <!-- <build_depend>message_generation</build_depend> --> + <!-- Use build_export_depend for packages you need in order to build against this package: --> + <!-- <build_export_depend>message_generation</build_export_depend> --> + <!-- Use buildtool_depend for build tool packages: --> + <!-- <buildtool_depend>catkin</buildtool_depend> --> + <!-- Use exec_depend for packages you need at runtime: --> + <!-- <exec_depend>message_runtime</exec_depend> --> + <!-- Use test_depend for packages you need only for testing: --> + <!-- <test_depend>gtest</test_depend> --> + <!-- Use doc_depend for packages you need only for building documentation: --> + <!-- <doc_depend>doxygen</doc_depend> --> + <buildtool_depend>catkin</buildtool_depend> + <build_depend>roscpp</build_depend> + <build_depend>rospy</build_depend> + <build_depend>std_msgs</build_depend> + <build_export_depend>roscpp</build_export_depend> + <build_export_depend>rospy</build_export_depend> + <build_export_depend>std_msgs</build_export_depend> + <exec_depend>roscpp</exec_depend> + <exec_depend>rospy</exec_depend> + <exec_depend>std_msgs</exec_depend> + + + <!-- The export tag contains other, unspecified, tags --> + <export> + <!-- Other tools can request additional information be placed here --> + + </export> +</package> diff --git a/Robot_Development/catkin_ws/lane_demo/src/Detection.cpp.bak b/Robot_Development/catkin_ws/lane_demo/src/Detection.cpp.bak new file mode 100644 index 0000000000000000000000000000000000000000..79b5eaaf09f2dc3dd5b9efa771567107d2e3911a --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/src/Detection.cpp.bak @@ -0,0 +1,125 @@ +#include<iostream> +#include"Detection.h" +#include<sstream> +#include<string> +#include<iterator> +#include<map> + +using namespace std; + +class Detection { +public: + Detection() { + cout << "boop" << endl; + } + Detection(string name, float prob, int cx,int cy, int w, int h) { + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + } + Detection(string serialization) { + cout << "OMG OMG OMG OMG " << serialization << endl; + string whitespace = removeSpaces(serialization); + cout << whitespace << endl; + string unbraced = whitespace.substr(1, whitespace.length()-2); + cout << unbraced << endl; + string arr[5]; + + string str1 = unbraced; + string str2 = "name:"; + string str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "prob:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cx:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cy:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "w:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "h:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + cout << str1 << endl; + + string name = str1.substr(0,str1.find(',')); + cout << name << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + float prob = stof(str1.substr(0,str1.find(','))); + cout << prob << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cx = stoi(str1.substr(0,str1.find(','))); + cout << cx << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cy = stoi(str1.substr(0,str1.find(','))); + cout << cy << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int w = stoi(str1.substr(0,str1.find(','))); + cout << w << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int h = stoi(str1.substr(0,str1.find(','))); + cout << h << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + + } + string removeSpaces(string str) + { + string s = ""; + // To keep track of non-space character count + int count = 0; + + // Traverse the given string. If current character + // is not space, then place it at index 'count++' + for (int i = 0; i < str.length() ; i++) + if (str.at(i) != ' ') + s = s + str.at(i); + // incremented + return s; + } + + template <size_t N> + void splitString(string (&arr)[N], string str) + { + int n = 0; + istringstream iss(str); + for (auto it = istream_iterator<string>(iss); it != istream_iterator<string>() && n < N; ++it, ++n) + arr[n] = *it; + } + + string to_string() { + string s0 = "name:" + _name + ","; + string s1 = "prob:" + std::to_string(_prob) + ","; + string s2 = "cx:" + std::to_string(_cx) + ","; + string s3 = "cy:" + std::to_string(_cy) + ","; + string s4 = "w:" + std::to_string(_w) + ","; + string s5 = "h:" + std::to_string(_h) + ","; + string s = s0 + s1 + s2 + s3 + s4 + s5; + return s; + } +}; + diff --git a/Robot_Development/catkin_ws/lane_demo/src/Detection.h b/Robot_Development/catkin_ws/lane_demo/src/Detection.h new file mode 100644 index 0000000000000000000000000000000000000000..d49d1ce369bce07cdf74e0b9ae02b9aaffb46667 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/src/Detection.h @@ -0,0 +1,124 @@ +#include<iostream> +#include<sstream> +#include<string> +#include<iterator> +#include<map> + +using namespace std; + +class Detection { +public: + string _name; + float _prob; + int _cx; + int _cy; + int _w; + int _h; + + Detection() { + + } + Detection(string name, float prob, int cx,int cy, int w, int h) { + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + } + Detection(string serialization) { + string whitespace = removeSpaces(serialization); + //cout << whitespace << endl; + string unbraced = whitespace.substr(1, whitespace.length()-2); + //cout << unbraced << endl; + string arr[5]; + + string str1 = unbraced; + string str2 = "name:"; + string str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "prob:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cx:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cy:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "w:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "h:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + //cout << str1 << endl; + + string name = str1.substr(0,str1.find(',')); + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + float prob = stof(str1.substr(0,str1.find(','))); + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cx = stoi(str1.substr(0,str1.find(','))); + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cy = stoi(str1.substr(0,str1.find(','))); + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int w = stoi(str1.substr(0,str1.find(','))); + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int h = stoi(str1.substr(0,str1.find(','))); + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + + } + string removeSpaces(string str) + { + string s = ""; + // To keep track of non-space character count + int count = 0; + + // Traverse the given string. If current character + // is not space, then place it at index 'count++' + for (int i = 0; i < str.length() ; i++) + if (str.at(i) != ' ') + s = s + str.at(i); + // incremented + return s; + } + + template <size_t N> + void splitString(string (&arr)[N], string str) + { + int n = 0; + istringstream iss(str); + for (auto it = istream_iterator<string>(iss); it != istream_iterator<string>() && n < N; ++it, ++n) + arr[n] = *it; + } + + string to_string() { + string s0 = "name:" + _name + ","; + string s1 = "prob:" + std::to_string(_prob) + ","; + string s2 = "cx:" + std::to_string(_cx) + ","; + string s3 = "cy:" + std::to_string(_cy) + ","; + string s4 = "w:" + std::to_string(_w) + ","; + string s5 = "h:" + std::to_string(_h) + ","; + string s = s0 + s1 + s2 + s3 + s4 + s5; + return s; + } +}; + diff --git a/Robot_Development/catkin_ws/lane_demo/src/Detection.h.bak1 b/Robot_Development/catkin_ws/lane_demo/src/Detection.h.bak1 new file mode 100644 index 0000000000000000000000000000000000000000..291814c11d2aea59dae4efca903aa9fc8435ea27 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/src/Detection.h.bak1 @@ -0,0 +1,27 @@ +#include<iostream> +#include<sstream> +#include<string> +#include<iterator> +#include<map> + +using namespace std; + +class Detection { +public: + string _name; + float _prob; + int _cx; + int _cy; + int _w; + int _h; + Detection(); + Detection(string name, float prob, int cx,int cy, int w, int h); + Detection(string serialization); + string removeSpaces(string str); + + template <size_t N> + void splitString(string (&arr)[N], string str); + + string to_string(); +}; + diff --git a/Robot_Development/catkin_ws/lane_demo/src/bad.list b/Robot_Development/catkin_ws/lane_demo/src/bad.list new file mode 100644 index 0000000000000000000000000000000000000000..f696b64096353d97a47c30f2ca24ced6f99b255a --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/src/bad.list @@ -0,0 +1,4560 @@ +data/labels/32_0.png +data/labels/33_0.png +data/labels/34_0.png +data/labels/35_0.png +data/labels/36_0.png +data/labels/37_0.png +data/labels/38_0.png +data/labels/39_0.png +data/labels/40_0.png +data/labels/41_0.png +data/labels/42_0.png +data/labels/43_0.png +data/labels/44_0.png +data/labels/45_0.png +data/labels/46_0.png +data/labels/47_0.png +data/labels/48_0.png +data/labels/49_0.png +data/labels/50_0.png +data/labels/51_0.png +data/labels/52_0.png +data/labels/53_0.png +data/labels/54_0.png +data/labels/55_0.png +data/labels/56_0.png +data/labels/57_0.png +data/labels/58_0.png +data/labels/59_0.png +data/labels/60_0.png +data/labels/61_0.png +data/labels/62_0.png +data/labels/63_0.png +data/labels/64_0.png +data/labels/65_0.png +data/labels/66_0.png +data/labels/67_0.png +data/labels/68_0.png +data/labels/69_0.png +data/labels/70_0.png +data/labels/71_0.png +data/labels/72_0.png +data/labels/73_0.png +data/labels/74_0.png +data/labels/75_0.png +data/labels/76_0.png +data/labels/77_0.png +data/labels/78_0.png +data/labels/79_0.png +data/labels/80_0.png +data/labels/81_0.png +data/labels/82_0.png +data/labels/83_0.png +data/labels/84_0.png +data/labels/85_0.png +data/labels/86_0.png +data/labels/87_0.png +data/labels/88_0.png +data/labels/89_0.png +data/labels/90_0.png +data/labels/91_0.png +data/labels/92_0.png +data/labels/93_0.png +data/labels/94_0.png +data/labels/95_0.png +data/labels/96_0.png +data/labels/97_0.png +data/labels/98_0.png +data/labels/99_0.png +data/labels/100_0.png +data/labels/101_0.png +data/labels/102_0.png +data/labels/103_0.png +data/labels/104_0.png +data/labels/105_0.png +data/labels/106_0.png +data/labels/107_0.png +data/labels/108_0.png +data/labels/109_0.png +data/labels/110_0.png +data/labels/111_0.png +data/labels/112_0.png +data/labels/113_0.png +data/labels/114_0.png +data/labels/115_0.png +data/labels/116_0.png +data/labels/117_0.png +data/labels/118_0.png +data/labels/119_0.png +data/labels/120_0.png +data/labels/121_0.png +data/labels/122_0.png +data/labels/123_0.png +data/labels/124_0.png +data/labels/125_0.png +data/labels/126_0.png +data/labels/32_1.png +data/labels/33_1.png +data/labels/34_1.png +data/labels/35_1.png +data/labels/36_1.png +data/labels/37_1.png +data/labels/38_1.png +data/labels/39_1.png +data/labels/40_1.png +data/labels/41_1.png +data/labels/42_1.png +data/labels/43_1.png +data/labels/44_1.png +data/labels/45_1.png +data/labels/46_1.png +data/labels/47_1.png +data/labels/48_1.png +data/labels/49_1.png +data/labels/50_1.png +data/labels/51_1.png +data/labels/52_1.png +data/labels/53_1.png +data/labels/54_1.png +data/labels/55_1.png +data/labels/56_1.png +data/labels/57_1.png +data/labels/58_1.png +data/labels/59_1.png +data/labels/60_1.png +data/labels/61_1.png +data/labels/62_1.png +data/labels/63_1.png +data/labels/64_1.png +data/labels/65_1.png +data/labels/66_1.png +data/labels/67_1.png +data/labels/68_1.png +data/labels/69_1.png +data/labels/70_1.png +data/labels/71_1.png +data/labels/72_1.png +data/labels/73_1.png +data/labels/74_1.png +data/labels/75_1.png +data/labels/76_1.png +data/labels/77_1.png +data/labels/78_1.png +data/labels/79_1.png +data/labels/80_1.png +data/labels/81_1.png +data/labels/82_1.png +data/labels/83_1.png +data/labels/84_1.png +data/labels/85_1.png +data/labels/86_1.png +data/labels/87_1.png +data/labels/88_1.png +data/labels/89_1.png +data/labels/90_1.png +data/labels/91_1.png +data/labels/92_1.png +data/labels/93_1.png +data/labels/94_1.png +data/labels/95_1.png +data/labels/96_1.png +data/labels/97_1.png +data/labels/98_1.png +data/labels/99_1.png +data/labels/100_1.png +data/labels/101_1.png +data/labels/102_1.png +data/labels/103_1.png +data/labels/104_1.png +data/labels/105_1.png +data/labels/106_1.png +data/labels/107_1.png +data/labels/108_1.png +data/labels/109_1.png +data/labels/110_1.png +data/labels/111_1.png +data/labels/112_1.png +data/labels/113_1.png +data/labels/114_1.png +data/labels/115_1.png +data/labels/116_1.png +data/labels/117_1.png +data/labels/118_1.png +data/labels/119_1.png +data/labels/120_1.png +data/labels/121_1.png +data/labels/122_1.png +data/labels/123_1.png +data/labels/124_1.png +data/labels/125_1.png +data/labels/126_1.png +data/labels/32_2.png +data/labels/33_2.png +data/labels/34_2.png +data/labels/35_2.png +data/labels/36_2.png +data/labels/37_2.png +data/labels/38_2.png +data/labels/39_2.png +data/labels/40_2.png +data/labels/41_2.png +data/labels/42_2.png +data/labels/43_2.png +data/labels/44_2.png +data/labels/45_2.png +data/labels/46_2.png +data/labels/47_2.png +data/labels/48_2.png +data/labels/49_2.png +data/labels/50_2.png +data/labels/51_2.png +data/labels/52_2.png +data/labels/53_2.png +data/labels/54_2.png +data/labels/55_2.png +data/labels/56_2.png +data/labels/57_2.png +data/labels/58_2.png +data/labels/59_2.png +data/labels/60_2.png +data/labels/61_2.png +data/labels/62_2.png +data/labels/63_2.png +data/labels/64_2.png +data/labels/65_2.png +data/labels/66_2.png +data/labels/67_2.png +data/labels/68_2.png +data/labels/69_2.png +data/labels/70_2.png +data/labels/71_2.png +data/labels/72_2.png +data/labels/73_2.png +data/labels/74_2.png +data/labels/75_2.png +data/labels/76_2.png +data/labels/77_2.png +data/labels/78_2.png +data/labels/79_2.png +data/labels/80_2.png +data/labels/81_2.png +data/labels/82_2.png +data/labels/83_2.png +data/labels/84_2.png +data/labels/85_2.png +data/labels/86_2.png +data/labels/87_2.png +data/labels/88_2.png +data/labels/89_2.png +data/labels/90_2.png +data/labels/91_2.png +data/labels/92_2.png +data/labels/93_2.png +data/labels/94_2.png +data/labels/95_2.png +data/labels/96_2.png +data/labels/97_2.png +data/labels/98_2.png +data/labels/99_2.png +data/labels/100_2.png +data/labels/101_2.png +data/labels/102_2.png +data/labels/103_2.png +data/labels/104_2.png +data/labels/105_2.png +data/labels/106_2.png +data/labels/107_2.png +data/labels/108_2.png +data/labels/109_2.png +data/labels/110_2.png +data/labels/111_2.png +data/labels/112_2.png +data/labels/113_2.png +data/labels/114_2.png +data/labels/115_2.png +data/labels/116_2.png +data/labels/117_2.png +data/labels/118_2.png +data/labels/119_2.png +data/labels/120_2.png +data/labels/121_2.png +data/labels/122_2.png +data/labels/123_2.png +data/labels/124_2.png +data/labels/125_2.png +data/labels/126_2.png +data/labels/32_3.png +data/labels/33_3.png +data/labels/34_3.png +data/labels/35_3.png +data/labels/36_3.png +data/labels/37_3.png +data/labels/38_3.png +data/labels/39_3.png +data/labels/40_3.png +data/labels/41_3.png +data/labels/42_3.png +data/labels/43_3.png +data/labels/44_3.png +data/labels/45_3.png +data/labels/46_3.png +data/labels/47_3.png +data/labels/48_3.png +data/labels/49_3.png +data/labels/50_3.png +data/labels/51_3.png +data/labels/52_3.png +data/labels/53_3.png +data/labels/54_3.png +data/labels/55_3.png +data/labels/56_3.png +data/labels/57_3.png +data/labels/58_3.png +data/labels/59_3.png +data/labels/60_3.png +data/labels/61_3.png +data/labels/62_3.png +data/labels/63_3.png +data/labels/64_3.png +data/labels/65_3.png +data/labels/66_3.png +data/labels/67_3.png +data/labels/68_3.png +data/labels/69_3.png +data/labels/70_3.png +data/labels/71_3.png +data/labels/72_3.png +data/labels/73_3.png +data/labels/74_3.png +data/labels/75_3.png +data/labels/76_3.png +data/labels/77_3.png +data/labels/78_3.png +data/labels/79_3.png +data/labels/80_3.png +data/labels/81_3.png +data/labels/82_3.png +data/labels/83_3.png +data/labels/84_3.png +data/labels/85_3.png +data/labels/86_3.png +data/labels/87_3.png +data/labels/88_3.png +data/labels/89_3.png +data/labels/90_3.png +data/labels/91_3.png +data/labels/92_3.png +data/labels/93_3.png +data/labels/94_3.png +data/labels/95_3.png +data/labels/96_3.png +data/labels/97_3.png +data/labels/98_3.png +data/labels/99_3.png +data/labels/100_3.png +data/labels/101_3.png +data/labels/102_3.png +data/labels/103_3.png +data/labels/104_3.png +data/labels/105_3.png +data/labels/106_3.png +data/labels/107_3.png +data/labels/108_3.png +data/labels/109_3.png +data/labels/110_3.png +data/labels/111_3.png +data/labels/112_3.png +data/labels/113_3.png +data/labels/114_3.png +data/labels/115_3.png +data/labels/116_3.png +data/labels/117_3.png +data/labels/118_3.png +data/labels/119_3.png +data/labels/120_3.png +data/labels/121_3.png +data/labels/122_3.png +data/labels/123_3.png +data/labels/124_3.png +data/labels/125_3.png +data/labels/126_3.png +data/labels/32_4.png +data/labels/33_4.png +data/labels/34_4.png +data/labels/35_4.png +data/labels/36_4.png +data/labels/37_4.png +data/labels/38_4.png +data/labels/39_4.png +data/labels/40_4.png +data/labels/41_4.png +data/labels/42_4.png +data/labels/43_4.png +data/labels/44_4.png +data/labels/45_4.png +data/labels/46_4.png +data/labels/47_4.png +data/labels/48_4.png +data/labels/49_4.png +data/labels/50_4.png +data/labels/51_4.png +data/labels/52_4.png +data/labels/53_4.png +data/labels/54_4.png +data/labels/55_4.png +data/labels/56_4.png +data/labels/57_4.png +data/labels/58_4.png +data/labels/59_4.png +data/labels/60_4.png +data/labels/61_4.png +data/labels/62_4.png +data/labels/63_4.png +data/labels/64_4.png +data/labels/65_4.png +data/labels/66_4.png +data/labels/67_4.png +data/labels/68_4.png +data/labels/69_4.png +data/labels/70_4.png +data/labels/71_4.png +data/labels/72_4.png +data/labels/73_4.png +data/labels/74_4.png +data/labels/75_4.png +data/labels/76_4.png +data/labels/77_4.png +data/labels/78_4.png +data/labels/79_4.png +data/labels/80_4.png +data/labels/81_4.png +data/labels/82_4.png +data/labels/83_4.png +data/labels/84_4.png +data/labels/85_4.png +data/labels/86_4.png +data/labels/87_4.png +data/labels/88_4.png +data/labels/89_4.png +data/labels/90_4.png +data/labels/91_4.png +data/labels/92_4.png +data/labels/93_4.png +data/labels/94_4.png +data/labels/95_4.png +data/labels/96_4.png +data/labels/97_4.png +data/labels/98_4.png +data/labels/99_4.png +data/labels/100_4.png +data/labels/101_4.png +data/labels/102_4.png +data/labels/103_4.png +data/labels/104_4.png +data/labels/105_4.png +data/labels/106_4.png +data/labels/107_4.png +data/labels/108_4.png +data/labels/109_4.png +data/labels/110_4.png +data/labels/111_4.png +data/labels/112_4.png +data/labels/113_4.png +data/labels/114_4.png +data/labels/115_4.png +data/labels/116_4.png +data/labels/117_4.png +data/labels/118_4.png +data/labels/119_4.png +data/labels/120_4.png +data/labels/121_4.png +data/labels/122_4.png +data/labels/123_4.png +data/labels/124_4.png +data/labels/125_4.png +data/labels/126_4.png +data/labels/32_5.png +data/labels/33_5.png +data/labels/34_5.png +data/labels/35_5.png +data/labels/36_5.png +data/labels/37_5.png +data/labels/38_5.png +data/labels/39_5.png +data/labels/40_5.png +data/labels/41_5.png +data/labels/42_5.png +data/labels/43_5.png +data/labels/44_5.png +data/labels/45_5.png +data/labels/46_5.png +data/labels/47_5.png +data/labels/48_5.png +data/labels/49_5.png +data/labels/50_5.png +data/labels/51_5.png +data/labels/52_5.png +data/labels/53_5.png +data/labels/54_5.png +data/labels/55_5.png +data/labels/56_5.png +data/labels/57_5.png +data/labels/58_5.png +data/labels/59_5.png +data/labels/60_5.png +data/labels/61_5.png +data/labels/62_5.png +data/labels/63_5.png +data/labels/64_5.png +data/labels/65_5.png +data/labels/66_5.png +data/labels/67_5.png +data/labels/68_5.png +data/labels/69_5.png +data/labels/70_5.png +data/labels/71_5.png +data/labels/72_5.png +data/labels/73_5.png +data/labels/74_5.png +data/labels/75_5.png +data/labels/76_5.png +data/labels/77_5.png +data/labels/78_5.png +data/labels/79_5.png +data/labels/80_5.png +data/labels/81_5.png +data/labels/82_5.png +data/labels/83_5.png +data/labels/84_5.png +data/labels/85_5.png +data/labels/86_5.png +data/labels/87_5.png +data/labels/88_5.png +data/labels/89_5.png +data/labels/90_5.png +data/labels/91_5.png +data/labels/92_5.png +data/labels/93_5.png +data/labels/94_5.png +data/labels/95_5.png +data/labels/96_5.png +data/labels/97_5.png +data/labels/98_5.png +data/labels/99_5.png +data/labels/100_5.png +data/labels/101_5.png +data/labels/102_5.png +data/labels/103_5.png +data/labels/104_5.png +data/labels/105_5.png +data/labels/106_5.png +data/labels/107_5.png +data/labels/108_5.png +data/labels/109_5.png +data/labels/110_5.png +data/labels/111_5.png +data/labels/112_5.png +data/labels/113_5.png +data/labels/114_5.png +data/labels/115_5.png +data/labels/116_5.png +data/labels/117_5.png +data/labels/118_5.png +data/labels/119_5.png +data/labels/120_5.png +data/labels/121_5.png +data/labels/122_5.png +data/labels/123_5.png +data/labels/124_5.png +data/labels/125_5.png +data/labels/126_5.png +data/labels/32_6.png +data/labels/33_6.png +data/labels/34_6.png +data/labels/35_6.png +data/labels/36_6.png +data/labels/37_6.png +data/labels/38_6.png +data/labels/39_6.png +data/labels/40_6.png +data/labels/41_6.png +data/labels/42_6.png +data/labels/43_6.png +data/labels/44_6.png +data/labels/45_6.png +data/labels/46_6.png +data/labels/47_6.png +data/labels/48_6.png +data/labels/49_6.png +data/labels/50_6.png +data/labels/51_6.png +data/labels/52_6.png +data/labels/53_6.png +data/labels/54_6.png +data/labels/55_6.png +data/labels/56_6.png +data/labels/57_6.png +data/labels/58_6.png +data/labels/59_6.png +data/labels/60_6.png +data/labels/61_6.png +data/labels/62_6.png +data/labels/63_6.png +data/labels/64_6.png +data/labels/65_6.png +data/labels/66_6.png +data/labels/67_6.png +data/labels/68_6.png +data/labels/69_6.png +data/labels/70_6.png +data/labels/71_6.png +data/labels/72_6.png +data/labels/73_6.png +data/labels/74_6.png +data/labels/75_6.png +data/labels/76_6.png +data/labels/77_6.png +data/labels/78_6.png +data/labels/79_6.png +data/labels/80_6.png +data/labels/81_6.png +data/labels/82_6.png +data/labels/83_6.png +data/labels/84_6.png +data/labels/85_6.png +data/labels/86_6.png +data/labels/87_6.png +data/labels/88_6.png +data/labels/89_6.png +data/labels/90_6.png +data/labels/91_6.png +data/labels/92_6.png +data/labels/93_6.png +data/labels/94_6.png +data/labels/95_6.png +data/labels/96_6.png +data/labels/97_6.png +data/labels/98_6.png +data/labels/99_6.png +data/labels/100_6.png +data/labels/101_6.png +data/labels/102_6.png +data/labels/103_6.png +data/labels/104_6.png +data/labels/105_6.png +data/labels/106_6.png +data/labels/107_6.png +data/labels/108_6.png +data/labels/109_6.png +data/labels/110_6.png +data/labels/111_6.png +data/labels/112_6.png +data/labels/113_6.png +data/labels/114_6.png +data/labels/115_6.png +data/labels/116_6.png +data/labels/117_6.png +data/labels/118_6.png +data/labels/119_6.png +data/labels/120_6.png +data/labels/121_6.png +data/labels/122_6.png +data/labels/123_6.png +data/labels/124_6.png +data/labels/125_6.png +data/labels/126_6.png +data/labels/32_7.png +data/labels/33_7.png +data/labels/34_7.png +data/labels/35_7.png +data/labels/36_7.png +data/labels/37_7.png +data/labels/38_7.png +data/labels/39_7.png +data/labels/40_7.png +data/labels/41_7.png +data/labels/42_7.png +data/labels/43_7.png +data/labels/44_7.png +data/labels/45_7.png +data/labels/46_7.png +data/labels/47_7.png +data/labels/48_7.png +data/labels/49_7.png +data/labels/50_7.png +data/labels/51_7.png +data/labels/52_7.png +data/labels/53_7.png +data/labels/54_7.png +data/labels/55_7.png +data/labels/56_7.png +data/labels/57_7.png +data/labels/58_7.png +data/labels/59_7.png +data/labels/60_7.png +data/labels/61_7.png +data/labels/62_7.png +data/labels/63_7.png +data/labels/64_7.png +data/labels/65_7.png +data/labels/66_7.png +data/labels/67_7.png +data/labels/68_7.png +data/labels/69_7.png +data/labels/70_7.png +data/labels/71_7.png +data/labels/72_7.png +data/labels/73_7.png +data/labels/74_7.png +data/labels/75_7.png +data/labels/76_7.png +data/labels/77_7.png +data/labels/78_7.png +data/labels/79_7.png +data/labels/80_7.png +data/labels/81_7.png +data/labels/82_7.png +data/labels/83_7.png +data/labels/84_7.png +data/labels/85_7.png +data/labels/86_7.png +data/labels/87_7.png +data/labels/88_7.png +data/labels/89_7.png +data/labels/90_7.png +data/labels/91_7.png +data/labels/92_7.png +data/labels/93_7.png +data/labels/94_7.png +data/labels/95_7.png +data/labels/96_7.png +data/labels/97_7.png +data/labels/98_7.png +data/labels/99_7.png +data/labels/100_7.png +data/labels/101_7.png +data/labels/102_7.png +data/labels/103_7.png +data/labels/104_7.png +data/labels/105_7.png +data/labels/106_7.png +data/labels/107_7.png +data/labels/108_7.png +data/labels/109_7.png +data/labels/110_7.png +data/labels/111_7.png +data/labels/112_7.png +data/labels/113_7.png +data/labels/114_7.png +data/labels/115_7.png +data/labels/116_7.png +data/labels/117_7.png +data/labels/118_7.png +data/labels/119_7.png +data/labels/120_7.png +data/labels/121_7.png +data/labels/122_7.png +data/labels/123_7.png +data/labels/124_7.png +data/labels/125_7.png +data/labels/126_7.png +data/labels/32_0.png +data/labels/33_0.png +data/labels/34_0.png +data/labels/35_0.png +data/labels/36_0.png +data/labels/37_0.png +data/labels/38_0.png +data/labels/39_0.png +data/labels/40_0.png +data/labels/41_0.png +data/labels/42_0.png +data/labels/43_0.png +data/labels/44_0.png +data/labels/45_0.png +data/labels/46_0.png +data/labels/47_0.png +data/labels/48_0.png +data/labels/49_0.png +data/labels/50_0.png +data/labels/51_0.png +data/labels/52_0.png +data/labels/53_0.png +data/labels/54_0.png +data/labels/55_0.png +data/labels/56_0.png +data/labels/57_0.png +data/labels/58_0.png +data/labels/59_0.png +data/labels/60_0.png +data/labels/61_0.png +data/labels/62_0.png +data/labels/63_0.png +data/labels/64_0.png +data/labels/65_0.png +data/labels/66_0.png +data/labels/67_0.png +data/labels/68_0.png +data/labels/69_0.png +data/labels/70_0.png +data/labels/71_0.png +data/labels/72_0.png +data/labels/73_0.png +data/labels/74_0.png +data/labels/75_0.png +data/labels/76_0.png +data/labels/77_0.png +data/labels/78_0.png +data/labels/79_0.png +data/labels/80_0.png +data/labels/81_0.png +data/labels/82_0.png +data/labels/83_0.png +data/labels/84_0.png +data/labels/85_0.png +data/labels/86_0.png +data/labels/87_0.png +data/labels/88_0.png +data/labels/89_0.png +data/labels/90_0.png +data/labels/91_0.png +data/labels/92_0.png +data/labels/93_0.png +data/labels/94_0.png +data/labels/95_0.png +data/labels/96_0.png +data/labels/97_0.png +data/labels/98_0.png +data/labels/99_0.png +data/labels/100_0.png +data/labels/101_0.png +data/labels/102_0.png +data/labels/103_0.png +data/labels/104_0.png +data/labels/105_0.png +data/labels/106_0.png +data/labels/107_0.png +data/labels/108_0.png +data/labels/109_0.png +data/labels/110_0.png +data/labels/111_0.png +data/labels/112_0.png +data/labels/113_0.png +data/labels/114_0.png +data/labels/115_0.png +data/labels/116_0.png +data/labels/117_0.png +data/labels/118_0.png +data/labels/119_0.png +data/labels/120_0.png +data/labels/121_0.png +data/labels/122_0.png +data/labels/123_0.png +data/labels/124_0.png +data/labels/125_0.png +data/labels/126_0.png +data/labels/32_1.png +data/labels/33_1.png +data/labels/34_1.png +data/labels/35_1.png +data/labels/36_1.png +data/labels/37_1.png +data/labels/38_1.png +data/labels/39_1.png +data/labels/40_1.png +data/labels/41_1.png +data/labels/42_1.png +data/labels/43_1.png +data/labels/44_1.png +data/labels/45_1.png +data/labels/46_1.png +data/labels/47_1.png +data/labels/48_1.png +data/labels/49_1.png +data/labels/50_1.png +data/labels/51_1.png +data/labels/52_1.png +data/labels/53_1.png +data/labels/54_1.png +data/labels/55_1.png +data/labels/56_1.png +data/labels/57_1.png +data/labels/58_1.png +data/labels/59_1.png +data/labels/60_1.png +data/labels/61_1.png +data/labels/62_1.png +data/labels/63_1.png +data/labels/64_1.png +data/labels/65_1.png +data/labels/66_1.png +data/labels/67_1.png +data/labels/68_1.png +data/labels/69_1.png +data/labels/70_1.png +data/labels/71_1.png +data/labels/72_1.png +data/labels/73_1.png +data/labels/74_1.png +data/labels/75_1.png +data/labels/76_1.png +data/labels/77_1.png +data/labels/78_1.png +data/labels/79_1.png +data/labels/80_1.png +data/labels/81_1.png +data/labels/82_1.png +data/labels/83_1.png +data/labels/84_1.png +data/labels/85_1.png +data/labels/86_1.png +data/labels/87_1.png +data/labels/88_1.png +data/labels/89_1.png +data/labels/90_1.png +data/labels/91_1.png +data/labels/92_1.png +data/labels/93_1.png +data/labels/94_1.png +data/labels/95_1.png +data/labels/96_1.png +data/labels/97_1.png +data/labels/98_1.png +data/labels/99_1.png +data/labels/100_1.png +data/labels/101_1.png +data/labels/102_1.png +data/labels/103_1.png +data/labels/104_1.png +data/labels/105_1.png +data/labels/106_1.png +data/labels/107_1.png +data/labels/108_1.png +data/labels/109_1.png +data/labels/110_1.png +data/labels/111_1.png +data/labels/112_1.png +data/labels/113_1.png +data/labels/114_1.png +data/labels/115_1.png +data/labels/116_1.png +data/labels/117_1.png +data/labels/118_1.png +data/labels/119_1.png +data/labels/120_1.png +data/labels/121_1.png +data/labels/122_1.png +data/labels/123_1.png +data/labels/124_1.png +data/labels/125_1.png +data/labels/126_1.png +data/labels/32_2.png +data/labels/33_2.png +data/labels/34_2.png +data/labels/35_2.png +data/labels/36_2.png +data/labels/37_2.png +data/labels/38_2.png +data/labels/39_2.png +data/labels/40_2.png +data/labels/41_2.png +data/labels/42_2.png +data/labels/43_2.png +data/labels/44_2.png +data/labels/45_2.png +data/labels/46_2.png +data/labels/47_2.png +data/labels/48_2.png +data/labels/49_2.png +data/labels/50_2.png +data/labels/51_2.png +data/labels/52_2.png +data/labels/53_2.png +data/labels/54_2.png +data/labels/55_2.png +data/labels/56_2.png +data/labels/57_2.png +data/labels/58_2.png +data/labels/59_2.png +data/labels/60_2.png +data/labels/61_2.png +data/labels/62_2.png +data/labels/63_2.png +data/labels/64_2.png +data/labels/65_2.png +data/labels/66_2.png +data/labels/67_2.png +data/labels/68_2.png +data/labels/69_2.png +data/labels/70_2.png +data/labels/71_2.png +data/labels/72_2.png +data/labels/73_2.png +data/labels/74_2.png +data/labels/75_2.png +data/labels/76_2.png +data/labels/77_2.png +data/labels/78_2.png +data/labels/79_2.png +data/labels/80_2.png +data/labels/81_2.png +data/labels/82_2.png +data/labels/83_2.png +data/labels/84_2.png +data/labels/85_2.png +data/labels/86_2.png +data/labels/87_2.png +data/labels/88_2.png +data/labels/89_2.png +data/labels/90_2.png +data/labels/91_2.png +data/labels/92_2.png +data/labels/93_2.png +data/labels/94_2.png +data/labels/95_2.png +data/labels/96_2.png +data/labels/97_2.png +data/labels/98_2.png +data/labels/99_2.png +data/labels/100_2.png +data/labels/101_2.png +data/labels/102_2.png +data/labels/103_2.png +data/labels/104_2.png +data/labels/105_2.png +data/labels/106_2.png +data/labels/107_2.png +data/labels/108_2.png +data/labels/109_2.png +data/labels/110_2.png +data/labels/111_2.png +data/labels/112_2.png +data/labels/113_2.png +data/labels/114_2.png +data/labels/115_2.png +data/labels/116_2.png +data/labels/117_2.png +data/labels/118_2.png +data/labels/119_2.png +data/labels/120_2.png +data/labels/121_2.png +data/labels/122_2.png +data/labels/123_2.png +data/labels/124_2.png +data/labels/125_2.png +data/labels/126_2.png +data/labels/32_3.png +data/labels/33_3.png +data/labels/34_3.png +data/labels/35_3.png +data/labels/36_3.png +data/labels/37_3.png +data/labels/38_3.png +data/labels/39_3.png +data/labels/40_3.png +data/labels/41_3.png +data/labels/42_3.png +data/labels/43_3.png +data/labels/44_3.png +data/labels/45_3.png +data/labels/46_3.png +data/labels/47_3.png +data/labels/48_3.png +data/labels/49_3.png +data/labels/50_3.png +data/labels/51_3.png +data/labels/52_3.png +data/labels/53_3.png +data/labels/54_3.png +data/labels/55_3.png +data/labels/56_3.png +data/labels/57_3.png +data/labels/58_3.png +data/labels/59_3.png +data/labels/60_3.png +data/labels/61_3.png +data/labels/62_3.png +data/labels/63_3.png +data/labels/64_3.png +data/labels/65_3.png +data/labels/66_3.png +data/labels/67_3.png +data/labels/68_3.png +data/labels/69_3.png +data/labels/70_3.png +data/labels/71_3.png +data/labels/72_3.png +data/labels/73_3.png +data/labels/74_3.png +data/labels/75_3.png +data/labels/76_3.png +data/labels/77_3.png +data/labels/78_3.png +data/labels/79_3.png +data/labels/80_3.png +data/labels/81_3.png +data/labels/82_3.png +data/labels/83_3.png +data/labels/84_3.png +data/labels/85_3.png +data/labels/86_3.png +data/labels/87_3.png +data/labels/88_3.png +data/labels/89_3.png +data/labels/90_3.png +data/labels/91_3.png +data/labels/92_3.png +data/labels/93_3.png +data/labels/94_3.png +data/labels/95_3.png +data/labels/96_3.png +data/labels/97_3.png +data/labels/98_3.png +data/labels/99_3.png +data/labels/100_3.png +data/labels/101_3.png +data/labels/102_3.png +data/labels/103_3.png +data/labels/104_3.png +data/labels/105_3.png +data/labels/106_3.png +data/labels/107_3.png +data/labels/108_3.png +data/labels/109_3.png +data/labels/110_3.png +data/labels/111_3.png +data/labels/112_3.png +data/labels/113_3.png +data/labels/114_3.png +data/labels/115_3.png +data/labels/116_3.png +data/labels/117_3.png +data/labels/118_3.png +data/labels/119_3.png +data/labels/120_3.png +data/labels/121_3.png +data/labels/122_3.png +data/labels/123_3.png +data/labels/124_3.png +data/labels/125_3.png +data/labels/126_3.png +data/labels/32_4.png +data/labels/33_4.png +data/labels/34_4.png +data/labels/35_4.png +data/labels/36_4.png +data/labels/37_4.png +data/labels/38_4.png +data/labels/39_4.png +data/labels/40_4.png +data/labels/41_4.png +data/labels/42_4.png +data/labels/43_4.png +data/labels/44_4.png +data/labels/45_4.png +data/labels/46_4.png +data/labels/47_4.png +data/labels/48_4.png +data/labels/49_4.png +data/labels/50_4.png +data/labels/51_4.png +data/labels/52_4.png +data/labels/53_4.png +data/labels/54_4.png +data/labels/55_4.png +data/labels/56_4.png +data/labels/57_4.png +data/labels/58_4.png +data/labels/59_4.png +data/labels/60_4.png +data/labels/61_4.png +data/labels/62_4.png +data/labels/63_4.png +data/labels/64_4.png +data/labels/65_4.png +data/labels/66_4.png +data/labels/67_4.png +data/labels/68_4.png +data/labels/69_4.png +data/labels/70_4.png +data/labels/71_4.png +data/labels/72_4.png +data/labels/73_4.png +data/labels/74_4.png +data/labels/75_4.png +data/labels/76_4.png +data/labels/77_4.png +data/labels/78_4.png +data/labels/79_4.png +data/labels/80_4.png +data/labels/81_4.png +data/labels/82_4.png +data/labels/83_4.png +data/labels/84_4.png +data/labels/85_4.png +data/labels/86_4.png +data/labels/87_4.png +data/labels/88_4.png +data/labels/89_4.png +data/labels/90_4.png +data/labels/91_4.png +data/labels/92_4.png +data/labels/93_4.png +data/labels/94_4.png +data/labels/95_4.png +data/labels/96_4.png +data/labels/97_4.png +data/labels/98_4.png +data/labels/99_4.png +data/labels/100_4.png +data/labels/101_4.png +data/labels/102_4.png +data/labels/103_4.png +data/labels/104_4.png +data/labels/105_4.png +data/labels/106_4.png +data/labels/107_4.png +data/labels/108_4.png +data/labels/109_4.png +data/labels/110_4.png +data/labels/111_4.png +data/labels/112_4.png +data/labels/113_4.png +data/labels/114_4.png +data/labels/115_4.png +data/labels/116_4.png +data/labels/117_4.png +data/labels/118_4.png +data/labels/119_4.png +data/labels/120_4.png +data/labels/121_4.png +data/labels/122_4.png +data/labels/123_4.png +data/labels/124_4.png +data/labels/125_4.png +data/labels/126_4.png +data/labels/32_5.png +data/labels/33_5.png +data/labels/34_5.png +data/labels/35_5.png +data/labels/36_5.png +data/labels/37_5.png +data/labels/38_5.png +data/labels/39_5.png +data/labels/40_5.png +data/labels/41_5.png +data/labels/42_5.png +data/labels/43_5.png +data/labels/44_5.png +data/labels/45_5.png +data/labels/46_5.png +data/labels/47_5.png +data/labels/48_5.png +data/labels/49_5.png +data/labels/50_5.png +data/labels/51_5.png +data/labels/52_5.png +data/labels/53_5.png +data/labels/54_5.png +data/labels/55_5.png +data/labels/56_5.png +data/labels/57_5.png +data/labels/58_5.png +data/labels/59_5.png +data/labels/60_5.png +data/labels/61_5.png +data/labels/62_5.png +data/labels/63_5.png +data/labels/64_5.png +data/labels/65_5.png +data/labels/66_5.png +data/labels/67_5.png +data/labels/68_5.png +data/labels/69_5.png +data/labels/70_5.png +data/labels/71_5.png +data/labels/72_5.png +data/labels/73_5.png +data/labels/74_5.png +data/labels/75_5.png +data/labels/76_5.png +data/labels/77_5.png +data/labels/78_5.png +data/labels/79_5.png +data/labels/80_5.png +data/labels/81_5.png +data/labels/82_5.png +data/labels/83_5.png +data/labels/84_5.png +data/labels/85_5.png +data/labels/86_5.png +data/labels/87_5.png +data/labels/88_5.png +data/labels/89_5.png +data/labels/90_5.png +data/labels/91_5.png +data/labels/92_5.png +data/labels/93_5.png +data/labels/94_5.png +data/labels/95_5.png +data/labels/96_5.png +data/labels/97_5.png +data/labels/98_5.png +data/labels/99_5.png +data/labels/100_5.png +data/labels/101_5.png +data/labels/102_5.png +data/labels/103_5.png +data/labels/104_5.png +data/labels/105_5.png +data/labels/106_5.png +data/labels/107_5.png +data/labels/108_5.png +data/labels/109_5.png +data/labels/110_5.png +data/labels/111_5.png +data/labels/112_5.png +data/labels/113_5.png +data/labels/114_5.png +data/labels/115_5.png +data/labels/116_5.png +data/labels/117_5.png +data/labels/118_5.png +data/labels/119_5.png +data/labels/120_5.png +data/labels/121_5.png +data/labels/122_5.png +data/labels/123_5.png +data/labels/124_5.png +data/labels/125_5.png +data/labels/126_5.png +data/labels/32_6.png +data/labels/33_6.png +data/labels/34_6.png +data/labels/35_6.png +data/labels/36_6.png +data/labels/37_6.png +data/labels/38_6.png +data/labels/39_6.png +data/labels/40_6.png +data/labels/41_6.png +data/labels/42_6.png +data/labels/43_6.png +data/labels/44_6.png +data/labels/45_6.png +data/labels/46_6.png +data/labels/47_6.png +data/labels/48_6.png +data/labels/49_6.png +data/labels/50_6.png +data/labels/51_6.png +data/labels/52_6.png +data/labels/53_6.png +data/labels/54_6.png +data/labels/55_6.png +data/labels/56_6.png +data/labels/57_6.png +data/labels/58_6.png +data/labels/59_6.png +data/labels/60_6.png +data/labels/61_6.png +data/labels/62_6.png +data/labels/63_6.png +data/labels/64_6.png +data/labels/65_6.png +data/labels/66_6.png +data/labels/67_6.png +data/labels/68_6.png +data/labels/69_6.png +data/labels/70_6.png +data/labels/71_6.png +data/labels/72_6.png +data/labels/73_6.png +data/labels/74_6.png +data/labels/75_6.png +data/labels/76_6.png +data/labels/77_6.png +data/labels/78_6.png +data/labels/79_6.png +data/labels/80_6.png +data/labels/81_6.png +data/labels/82_6.png +data/labels/83_6.png +data/labels/84_6.png +data/labels/85_6.png +data/labels/86_6.png +data/labels/87_6.png +data/labels/88_6.png +data/labels/89_6.png +data/labels/90_6.png +data/labels/91_6.png +data/labels/92_6.png +data/labels/93_6.png +data/labels/94_6.png +data/labels/95_6.png +data/labels/96_6.png +data/labels/97_6.png +data/labels/98_6.png +data/labels/99_6.png +data/labels/100_6.png +data/labels/101_6.png +data/labels/102_6.png +data/labels/103_6.png +data/labels/104_6.png +data/labels/105_6.png +data/labels/106_6.png +data/labels/107_6.png +data/labels/108_6.png +data/labels/109_6.png +data/labels/110_6.png +data/labels/111_6.png +data/labels/112_6.png +data/labels/113_6.png +data/labels/114_6.png +data/labels/115_6.png +data/labels/116_6.png +data/labels/117_6.png +data/labels/118_6.png +data/labels/119_6.png +data/labels/120_6.png +data/labels/121_6.png +data/labels/122_6.png +data/labels/123_6.png +data/labels/124_6.png +data/labels/125_6.png +data/labels/126_6.png +data/labels/32_7.png +data/labels/33_7.png +data/labels/34_7.png +data/labels/35_7.png +data/labels/36_7.png +data/labels/37_7.png +data/labels/38_7.png +data/labels/39_7.png +data/labels/40_7.png +data/labels/41_7.png +data/labels/42_7.png +data/labels/43_7.png +data/labels/44_7.png +data/labels/45_7.png +data/labels/46_7.png +data/labels/47_7.png +data/labels/48_7.png +data/labels/49_7.png +data/labels/50_7.png +data/labels/51_7.png +data/labels/52_7.png +data/labels/53_7.png +data/labels/54_7.png +data/labels/55_7.png +data/labels/56_7.png +data/labels/57_7.png +data/labels/58_7.png +data/labels/59_7.png +data/labels/60_7.png +data/labels/61_7.png +data/labels/62_7.png +data/labels/63_7.png +data/labels/64_7.png +data/labels/65_7.png +data/labels/66_7.png +data/labels/67_7.png +data/labels/68_7.png +data/labels/69_7.png +data/labels/70_7.png +data/labels/71_7.png +data/labels/72_7.png +data/labels/73_7.png +data/labels/74_7.png +data/labels/75_7.png +data/labels/76_7.png +data/labels/77_7.png +data/labels/78_7.png +data/labels/79_7.png +data/labels/80_7.png +data/labels/81_7.png +data/labels/82_7.png +data/labels/83_7.png +data/labels/84_7.png +data/labels/85_7.png +data/labels/86_7.png +data/labels/87_7.png +data/labels/88_7.png +data/labels/89_7.png +data/labels/90_7.png +data/labels/91_7.png +data/labels/92_7.png +data/labels/93_7.png +data/labels/94_7.png +data/labels/95_7.png +data/labels/96_7.png +data/labels/97_7.png +data/labels/98_7.png +data/labels/99_7.png +data/labels/100_7.png +data/labels/101_7.png +data/labels/102_7.png +data/labels/103_7.png +data/labels/104_7.png +data/labels/105_7.png +data/labels/106_7.png +data/labels/107_7.png +data/labels/108_7.png +data/labels/109_7.png +data/labels/110_7.png +data/labels/111_7.png +data/labels/112_7.png +data/labels/113_7.png +data/labels/114_7.png +data/labels/115_7.png +data/labels/116_7.png +data/labels/117_7.png +data/labels/118_7.png +data/labels/119_7.png +data/labels/120_7.png +data/labels/121_7.png +data/labels/122_7.png +data/labels/123_7.png +data/labels/124_7.png +data/labels/125_7.png +data/labels/126_7.png +data/labels/32_0.png +data/labels/33_0.png +data/labels/34_0.png +data/labels/35_0.png +data/labels/36_0.png +data/labels/37_0.png +data/labels/38_0.png +data/labels/39_0.png +data/labels/40_0.png +data/labels/41_0.png +data/labels/42_0.png +data/labels/43_0.png +data/labels/44_0.png +data/labels/45_0.png +data/labels/46_0.png +data/labels/47_0.png +data/labels/48_0.png +data/labels/49_0.png +data/labels/50_0.png +data/labels/51_0.png +data/labels/52_0.png +data/labels/53_0.png +data/labels/54_0.png +data/labels/55_0.png +data/labels/56_0.png +data/labels/57_0.png +data/labels/58_0.png +data/labels/59_0.png +data/labels/60_0.png +data/labels/61_0.png +data/labels/62_0.png +data/labels/63_0.png +data/labels/64_0.png +data/labels/65_0.png +data/labels/66_0.png +data/labels/67_0.png +data/labels/68_0.png +data/labels/69_0.png +data/labels/70_0.png +data/labels/71_0.png +data/labels/72_0.png +data/labels/73_0.png +data/labels/74_0.png +data/labels/75_0.png +data/labels/76_0.png +data/labels/77_0.png +data/labels/78_0.png +data/labels/79_0.png +data/labels/80_0.png +data/labels/81_0.png +data/labels/82_0.png +data/labels/83_0.png +data/labels/84_0.png +data/labels/85_0.png +data/labels/86_0.png +data/labels/87_0.png +data/labels/88_0.png +data/labels/89_0.png +data/labels/90_0.png +data/labels/91_0.png +data/labels/92_0.png +data/labels/93_0.png +data/labels/94_0.png +data/labels/95_0.png +data/labels/96_0.png +data/labels/97_0.png +data/labels/98_0.png +data/labels/99_0.png +data/labels/100_0.png +data/labels/101_0.png +data/labels/102_0.png +data/labels/103_0.png +data/labels/104_0.png +data/labels/105_0.png +data/labels/106_0.png +data/labels/107_0.png +data/labels/108_0.png +data/labels/109_0.png +data/labels/110_0.png +data/labels/111_0.png +data/labels/112_0.png +data/labels/113_0.png +data/labels/114_0.png +data/labels/115_0.png +data/labels/116_0.png +data/labels/117_0.png +data/labels/118_0.png +data/labels/119_0.png +data/labels/120_0.png +data/labels/121_0.png +data/labels/122_0.png +data/labels/123_0.png +data/labels/124_0.png +data/labels/125_0.png +data/labels/126_0.png +data/labels/32_1.png +data/labels/33_1.png +data/labels/34_1.png +data/labels/35_1.png +data/labels/36_1.png +data/labels/37_1.png +data/labels/38_1.png +data/labels/39_1.png +data/labels/40_1.png +data/labels/41_1.png +data/labels/42_1.png +data/labels/43_1.png +data/labels/44_1.png +data/labels/45_1.png +data/labels/46_1.png +data/labels/47_1.png +data/labels/48_1.png +data/labels/49_1.png +data/labels/50_1.png +data/labels/51_1.png +data/labels/52_1.png +data/labels/53_1.png +data/labels/54_1.png +data/labels/55_1.png +data/labels/56_1.png +data/labels/57_1.png +data/labels/58_1.png +data/labels/59_1.png +data/labels/60_1.png +data/labels/61_1.png +data/labels/62_1.png +data/labels/63_1.png +data/labels/64_1.png +data/labels/65_1.png +data/labels/66_1.png +data/labels/67_1.png +data/labels/68_1.png +data/labels/69_1.png +data/labels/70_1.png +data/labels/71_1.png +data/labels/72_1.png +data/labels/73_1.png +data/labels/74_1.png +data/labels/75_1.png +data/labels/76_1.png +data/labels/77_1.png +data/labels/78_1.png +data/labels/79_1.png +data/labels/80_1.png +data/labels/81_1.png +data/labels/82_1.png +data/labels/83_1.png +data/labels/84_1.png +data/labels/85_1.png +data/labels/86_1.png +data/labels/87_1.png +data/labels/88_1.png +data/labels/89_1.png +data/labels/90_1.png +data/labels/91_1.png +data/labels/92_1.png +data/labels/93_1.png +data/labels/94_1.png +data/labels/95_1.png +data/labels/96_1.png +data/labels/97_1.png +data/labels/98_1.png +data/labels/99_1.png +data/labels/100_1.png +data/labels/101_1.png +data/labels/102_1.png +data/labels/103_1.png +data/labels/104_1.png +data/labels/105_1.png +data/labels/106_1.png +data/labels/107_1.png +data/labels/108_1.png +data/labels/109_1.png +data/labels/110_1.png +data/labels/111_1.png +data/labels/112_1.png +data/labels/113_1.png +data/labels/114_1.png +data/labels/115_1.png +data/labels/116_1.png +data/labels/117_1.png +data/labels/118_1.png +data/labels/119_1.png +data/labels/120_1.png +data/labels/121_1.png +data/labels/122_1.png +data/labels/123_1.png +data/labels/124_1.png +data/labels/125_1.png +data/labels/126_1.png +data/labels/32_2.png +data/labels/33_2.png +data/labels/34_2.png +data/labels/35_2.png +data/labels/36_2.png +data/labels/37_2.png +data/labels/38_2.png +data/labels/39_2.png +data/labels/40_2.png +data/labels/41_2.png +data/labels/42_2.png +data/labels/43_2.png +data/labels/44_2.png +data/labels/45_2.png +data/labels/46_2.png +data/labels/47_2.png +data/labels/48_2.png +data/labels/49_2.png +data/labels/50_2.png +data/labels/51_2.png +data/labels/52_2.png +data/labels/53_2.png +data/labels/54_2.png +data/labels/55_2.png +data/labels/56_2.png +data/labels/57_2.png +data/labels/58_2.png +data/labels/59_2.png +data/labels/60_2.png +data/labels/61_2.png +data/labels/62_2.png +data/labels/63_2.png +data/labels/64_2.png +data/labels/65_2.png +data/labels/66_2.png +data/labels/67_2.png +data/labels/68_2.png +data/labels/69_2.png +data/labels/70_2.png +data/labels/71_2.png +data/labels/72_2.png +data/labels/73_2.png +data/labels/74_2.png +data/labels/75_2.png +data/labels/76_2.png +data/labels/77_2.png +data/labels/78_2.png +data/labels/79_2.png +data/labels/80_2.png +data/labels/81_2.png +data/labels/82_2.png +data/labels/83_2.png +data/labels/84_2.png +data/labels/85_2.png +data/labels/86_2.png +data/labels/87_2.png +data/labels/88_2.png +data/labels/89_2.png +data/labels/90_2.png +data/labels/91_2.png +data/labels/92_2.png +data/labels/93_2.png +data/labels/94_2.png +data/labels/95_2.png +data/labels/96_2.png +data/labels/97_2.png +data/labels/98_2.png +data/labels/99_2.png +data/labels/100_2.png +data/labels/101_2.png +data/labels/102_2.png +data/labels/103_2.png +data/labels/104_2.png +data/labels/105_2.png +data/labels/106_2.png +data/labels/107_2.png +data/labels/108_2.png +data/labels/109_2.png +data/labels/110_2.png +data/labels/111_2.png +data/labels/112_2.png +data/labels/113_2.png +data/labels/114_2.png +data/labels/115_2.png +data/labels/116_2.png +data/labels/117_2.png +data/labels/118_2.png +data/labels/119_2.png +data/labels/120_2.png +data/labels/121_2.png +data/labels/122_2.png +data/labels/123_2.png +data/labels/124_2.png +data/labels/125_2.png +data/labels/126_2.png +data/labels/32_3.png +data/labels/33_3.png +data/labels/34_3.png +data/labels/35_3.png +data/labels/36_3.png +data/labels/37_3.png +data/labels/38_3.png +data/labels/39_3.png +data/labels/40_3.png +data/labels/41_3.png +data/labels/42_3.png +data/labels/43_3.png +data/labels/44_3.png +data/labels/45_3.png +data/labels/46_3.png +data/labels/47_3.png +data/labels/48_3.png +data/labels/49_3.png +data/labels/50_3.png +data/labels/51_3.png +data/labels/52_3.png +data/labels/53_3.png +data/labels/54_3.png +data/labels/55_3.png +data/labels/56_3.png +data/labels/57_3.png +data/labels/58_3.png +data/labels/59_3.png +data/labels/60_3.png +data/labels/61_3.png +data/labels/62_3.png +data/labels/63_3.png +data/labels/64_3.png +data/labels/65_3.png +data/labels/66_3.png +data/labels/67_3.png +data/labels/68_3.png +data/labels/69_3.png +data/labels/70_3.png +data/labels/71_3.png +data/labels/72_3.png +data/labels/73_3.png +data/labels/74_3.png +data/labels/75_3.png +data/labels/76_3.png +data/labels/77_3.png +data/labels/78_3.png +data/labels/79_3.png +data/labels/80_3.png +data/labels/81_3.png +data/labels/82_3.png +data/labels/83_3.png +data/labels/84_3.png +data/labels/85_3.png +data/labels/86_3.png +data/labels/87_3.png +data/labels/88_3.png +data/labels/89_3.png +data/labels/90_3.png +data/labels/91_3.png +data/labels/92_3.png +data/labels/93_3.png +data/labels/94_3.png +data/labels/95_3.png +data/labels/96_3.png +data/labels/97_3.png +data/labels/98_3.png +data/labels/99_3.png +data/labels/100_3.png +data/labels/101_3.png +data/labels/102_3.png +data/labels/103_3.png +data/labels/104_3.png +data/labels/105_3.png +data/labels/106_3.png +data/labels/107_3.png +data/labels/108_3.png +data/labels/109_3.png +data/labels/110_3.png +data/labels/111_3.png +data/labels/112_3.png +data/labels/113_3.png +data/labels/114_3.png +data/labels/115_3.png +data/labels/116_3.png +data/labels/117_3.png +data/labels/118_3.png +data/labels/119_3.png +data/labels/120_3.png +data/labels/121_3.png +data/labels/122_3.png +data/labels/123_3.png +data/labels/124_3.png +data/labels/125_3.png +data/labels/126_3.png +data/labels/32_4.png +data/labels/33_4.png +data/labels/34_4.png +data/labels/35_4.png +data/labels/36_4.png +data/labels/37_4.png +data/labels/38_4.png +data/labels/39_4.png +data/labels/40_4.png +data/labels/41_4.png +data/labels/42_4.png +data/labels/43_4.png +data/labels/44_4.png +data/labels/45_4.png +data/labels/46_4.png +data/labels/47_4.png +data/labels/48_4.png +data/labels/49_4.png +data/labels/50_4.png +data/labels/51_4.png +data/labels/52_4.png +data/labels/53_4.png +data/labels/54_4.png +data/labels/55_4.png +data/labels/56_4.png +data/labels/57_4.png +data/labels/58_4.png +data/labels/59_4.png +data/labels/60_4.png +data/labels/61_4.png +data/labels/62_4.png +data/labels/63_4.png +data/labels/64_4.png +data/labels/65_4.png +data/labels/66_4.png +data/labels/67_4.png +data/labels/68_4.png +data/labels/69_4.png +data/labels/70_4.png +data/labels/71_4.png +data/labels/72_4.png +data/labels/73_4.png +data/labels/74_4.png +data/labels/75_4.png +data/labels/76_4.png +data/labels/77_4.png +data/labels/78_4.png +data/labels/79_4.png +data/labels/80_4.png +data/labels/81_4.png +data/labels/82_4.png +data/labels/83_4.png +data/labels/84_4.png +data/labels/85_4.png +data/labels/86_4.png +data/labels/87_4.png +data/labels/88_4.png +data/labels/89_4.png +data/labels/90_4.png +data/labels/91_4.png +data/labels/92_4.png +data/labels/93_4.png +data/labels/94_4.png +data/labels/95_4.png +data/labels/96_4.png +data/labels/97_4.png +data/labels/98_4.png +data/labels/99_4.png +data/labels/100_4.png +data/labels/101_4.png +data/labels/102_4.png +data/labels/103_4.png +data/labels/104_4.png +data/labels/105_4.png +data/labels/106_4.png +data/labels/107_4.png +data/labels/108_4.png +data/labels/109_4.png +data/labels/110_4.png +data/labels/111_4.png +data/labels/112_4.png +data/labels/113_4.png +data/labels/114_4.png +data/labels/115_4.png +data/labels/116_4.png +data/labels/117_4.png +data/labels/118_4.png +data/labels/119_4.png +data/labels/120_4.png +data/labels/121_4.png +data/labels/122_4.png +data/labels/123_4.png +data/labels/124_4.png +data/labels/125_4.png +data/labels/126_4.png +data/labels/32_5.png +data/labels/33_5.png +data/labels/34_5.png +data/labels/35_5.png +data/labels/36_5.png +data/labels/37_5.png +data/labels/38_5.png +data/labels/39_5.png +data/labels/40_5.png +data/labels/41_5.png +data/labels/42_5.png +data/labels/43_5.png +data/labels/44_5.png +data/labels/45_5.png +data/labels/46_5.png +data/labels/47_5.png +data/labels/48_5.png +data/labels/49_5.png +data/labels/50_5.png +data/labels/51_5.png +data/labels/52_5.png +data/labels/53_5.png +data/labels/54_5.png +data/labels/55_5.png +data/labels/56_5.png +data/labels/57_5.png +data/labels/58_5.png +data/labels/59_5.png +data/labels/60_5.png +data/labels/61_5.png +data/labels/62_5.png +data/labels/63_5.png +data/labels/64_5.png +data/labels/65_5.png +data/labels/66_5.png +data/labels/67_5.png +data/labels/68_5.png +data/labels/69_5.png +data/labels/70_5.png +data/labels/71_5.png +data/labels/72_5.png +data/labels/73_5.png +data/labels/74_5.png +data/labels/75_5.png +data/labels/76_5.png +data/labels/77_5.png +data/labels/78_5.png +data/labels/79_5.png +data/labels/80_5.png +data/labels/81_5.png +data/labels/82_5.png +data/labels/83_5.png +data/labels/84_5.png +data/labels/85_5.png +data/labels/86_5.png +data/labels/87_5.png +data/labels/88_5.png +data/labels/89_5.png +data/labels/90_5.png +data/labels/91_5.png +data/labels/92_5.png +data/labels/93_5.png +data/labels/94_5.png +data/labels/95_5.png +data/labels/96_5.png +data/labels/97_5.png +data/labels/98_5.png +data/labels/99_5.png +data/labels/100_5.png +data/labels/101_5.png +data/labels/102_5.png +data/labels/103_5.png +data/labels/104_5.png +data/labels/105_5.png +data/labels/106_5.png +data/labels/107_5.png +data/labels/108_5.png +data/labels/109_5.png +data/labels/110_5.png +data/labels/111_5.png +data/labels/112_5.png +data/labels/113_5.png +data/labels/114_5.png +data/labels/115_5.png +data/labels/116_5.png +data/labels/117_5.png +data/labels/118_5.png +data/labels/119_5.png +data/labels/120_5.png +data/labels/121_5.png +data/labels/122_5.png +data/labels/123_5.png +data/labels/124_5.png +data/labels/125_5.png +data/labels/126_5.png +data/labels/32_6.png +data/labels/33_6.png +data/labels/34_6.png +data/labels/35_6.png +data/labels/36_6.png +data/labels/37_6.png +data/labels/38_6.png +data/labels/39_6.png +data/labels/40_6.png +data/labels/41_6.png +data/labels/42_6.png +data/labels/43_6.png +data/labels/44_6.png +data/labels/45_6.png +data/labels/46_6.png +data/labels/47_6.png +data/labels/48_6.png +data/labels/49_6.png +data/labels/50_6.png +data/labels/51_6.png +data/labels/52_6.png +data/labels/53_6.png +data/labels/54_6.png +data/labels/55_6.png +data/labels/56_6.png +data/labels/57_6.png +data/labels/58_6.png +data/labels/59_6.png +data/labels/60_6.png +data/labels/61_6.png +data/labels/62_6.png +data/labels/63_6.png +data/labels/64_6.png +data/labels/65_6.png +data/labels/66_6.png +data/labels/67_6.png +data/labels/68_6.png +data/labels/69_6.png +data/labels/70_6.png +data/labels/71_6.png +data/labels/72_6.png +data/labels/73_6.png +data/labels/74_6.png +data/labels/75_6.png +data/labels/76_6.png +data/labels/77_6.png +data/labels/78_6.png +data/labels/79_6.png +data/labels/80_6.png +data/labels/81_6.png +data/labels/82_6.png +data/labels/83_6.png +data/labels/84_6.png +data/labels/85_6.png +data/labels/86_6.png +data/labels/87_6.png +data/labels/88_6.png +data/labels/89_6.png +data/labels/90_6.png +data/labels/91_6.png +data/labels/92_6.png +data/labels/93_6.png +data/labels/94_6.png +data/labels/95_6.png +data/labels/96_6.png +data/labels/97_6.png +data/labels/98_6.png +data/labels/99_6.png +data/labels/100_6.png +data/labels/101_6.png +data/labels/102_6.png +data/labels/103_6.png +data/labels/104_6.png +data/labels/105_6.png +data/labels/106_6.png +data/labels/107_6.png +data/labels/108_6.png +data/labels/109_6.png +data/labels/110_6.png +data/labels/111_6.png +data/labels/112_6.png +data/labels/113_6.png +data/labels/114_6.png +data/labels/115_6.png +data/labels/116_6.png +data/labels/117_6.png +data/labels/118_6.png +data/labels/119_6.png +data/labels/120_6.png +data/labels/121_6.png +data/labels/122_6.png +data/labels/123_6.png +data/labels/124_6.png +data/labels/125_6.png +data/labels/126_6.png +data/labels/32_7.png +data/labels/33_7.png +data/labels/34_7.png +data/labels/35_7.png +data/labels/36_7.png +data/labels/37_7.png +data/labels/38_7.png +data/labels/39_7.png +data/labels/40_7.png +data/labels/41_7.png +data/labels/42_7.png +data/labels/43_7.png +data/labels/44_7.png +data/labels/45_7.png +data/labels/46_7.png +data/labels/47_7.png +data/labels/48_7.png +data/labels/49_7.png +data/labels/50_7.png +data/labels/51_7.png +data/labels/52_7.png +data/labels/53_7.png +data/labels/54_7.png +data/labels/55_7.png +data/labels/56_7.png +data/labels/57_7.png +data/labels/58_7.png +data/labels/59_7.png +data/labels/60_7.png +data/labels/61_7.png +data/labels/62_7.png +data/labels/63_7.png +data/labels/64_7.png +data/labels/65_7.png +data/labels/66_7.png +data/labels/67_7.png +data/labels/68_7.png +data/labels/69_7.png +data/labels/70_7.png +data/labels/71_7.png +data/labels/72_7.png +data/labels/73_7.png +data/labels/74_7.png +data/labels/75_7.png +data/labels/76_7.png +data/labels/77_7.png +data/labels/78_7.png +data/labels/79_7.png +data/labels/80_7.png +data/labels/81_7.png +data/labels/82_7.png +data/labels/83_7.png +data/labels/84_7.png +data/labels/85_7.png +data/labels/86_7.png +data/labels/87_7.png +data/labels/88_7.png +data/labels/89_7.png +data/labels/90_7.png +data/labels/91_7.png +data/labels/92_7.png +data/labels/93_7.png +data/labels/94_7.png +data/labels/95_7.png +data/labels/96_7.png +data/labels/97_7.png +data/labels/98_7.png +data/labels/99_7.png +data/labels/100_7.png +data/labels/101_7.png +data/labels/102_7.png +data/labels/103_7.png +data/labels/104_7.png +data/labels/105_7.png +data/labels/106_7.png +data/labels/107_7.png +data/labels/108_7.png +data/labels/109_7.png +data/labels/110_7.png +data/labels/111_7.png +data/labels/112_7.png +data/labels/113_7.png +data/labels/114_7.png +data/labels/115_7.png +data/labels/116_7.png +data/labels/117_7.png +data/labels/118_7.png +data/labels/119_7.png +data/labels/120_7.png +data/labels/121_7.png +data/labels/122_7.png +data/labels/123_7.png +data/labels/124_7.png +data/labels/125_7.png +data/labels/126_7.png +data/labels/32_0.png +data/labels/33_0.png +data/labels/34_0.png +data/labels/35_0.png +data/labels/36_0.png +data/labels/37_0.png +data/labels/38_0.png +data/labels/39_0.png +data/labels/40_0.png +data/labels/41_0.png +data/labels/42_0.png +data/labels/43_0.png +data/labels/44_0.png +data/labels/45_0.png +data/labels/46_0.png +data/labels/47_0.png +data/labels/48_0.png +data/labels/49_0.png +data/labels/50_0.png +data/labels/51_0.png +data/labels/52_0.png +data/labels/53_0.png +data/labels/54_0.png +data/labels/55_0.png +data/labels/56_0.png +data/labels/57_0.png +data/labels/58_0.png +data/labels/59_0.png +data/labels/60_0.png +data/labels/61_0.png +data/labels/62_0.png +data/labels/63_0.png +data/labels/64_0.png +data/labels/65_0.png +data/labels/66_0.png +data/labels/67_0.png +data/labels/68_0.png +data/labels/69_0.png +data/labels/70_0.png +data/labels/71_0.png +data/labels/72_0.png +data/labels/73_0.png +data/labels/74_0.png +data/labels/75_0.png +data/labels/76_0.png +data/labels/77_0.png +data/labels/78_0.png +data/labels/79_0.png +data/labels/80_0.png +data/labels/81_0.png +data/labels/82_0.png +data/labels/83_0.png +data/labels/84_0.png +data/labels/85_0.png +data/labels/86_0.png +data/labels/87_0.png +data/labels/88_0.png +data/labels/89_0.png +data/labels/90_0.png +data/labels/91_0.png +data/labels/92_0.png +data/labels/93_0.png +data/labels/94_0.png +data/labels/95_0.png +data/labels/96_0.png +data/labels/97_0.png +data/labels/98_0.png +data/labels/99_0.png +data/labels/100_0.png +data/labels/101_0.png +data/labels/102_0.png +data/labels/103_0.png +data/labels/104_0.png +data/labels/105_0.png +data/labels/106_0.png +data/labels/107_0.png +data/labels/108_0.png +data/labels/109_0.png +data/labels/110_0.png +data/labels/111_0.png +data/labels/112_0.png +data/labels/113_0.png +data/labels/114_0.png +data/labels/115_0.png +data/labels/116_0.png +data/labels/117_0.png +data/labels/118_0.png +data/labels/119_0.png +data/labels/120_0.png +data/labels/121_0.png +data/labels/122_0.png +data/labels/123_0.png +data/labels/124_0.png +data/labels/125_0.png +data/labels/126_0.png +data/labels/32_1.png +data/labels/33_1.png +data/labels/34_1.png +data/labels/35_1.png +data/labels/36_1.png +data/labels/37_1.png +data/labels/38_1.png +data/labels/39_1.png +data/labels/40_1.png +data/labels/41_1.png +data/labels/42_1.png +data/labels/43_1.png +data/labels/44_1.png +data/labels/45_1.png +data/labels/46_1.png +data/labels/47_1.png +data/labels/48_1.png +data/labels/49_1.png +data/labels/50_1.png +data/labels/51_1.png +data/labels/52_1.png +data/labels/53_1.png +data/labels/54_1.png +data/labels/55_1.png +data/labels/56_1.png +data/labels/57_1.png +data/labels/58_1.png +data/labels/59_1.png +data/labels/60_1.png +data/labels/61_1.png +data/labels/62_1.png +data/labels/63_1.png +data/labels/64_1.png +data/labels/65_1.png +data/labels/66_1.png +data/labels/67_1.png +data/labels/68_1.png +data/labels/69_1.png +data/labels/70_1.png +data/labels/71_1.png +data/labels/72_1.png +data/labels/73_1.png +data/labels/74_1.png +data/labels/75_1.png +data/labels/76_1.png +data/labels/77_1.png +data/labels/78_1.png +data/labels/79_1.png +data/labels/80_1.png +data/labels/81_1.png +data/labels/82_1.png +data/labels/83_1.png +data/labels/84_1.png +data/labels/85_1.png +data/labels/86_1.png +data/labels/87_1.png +data/labels/88_1.png +data/labels/89_1.png +data/labels/90_1.png +data/labels/91_1.png +data/labels/92_1.png +data/labels/93_1.png +data/labels/94_1.png +data/labels/95_1.png +data/labels/96_1.png +data/labels/97_1.png +data/labels/98_1.png +data/labels/99_1.png +data/labels/100_1.png +data/labels/101_1.png +data/labels/102_1.png +data/labels/103_1.png +data/labels/104_1.png +data/labels/105_1.png +data/labels/106_1.png +data/labels/107_1.png +data/labels/108_1.png +data/labels/109_1.png +data/labels/110_1.png +data/labels/111_1.png +data/labels/112_1.png +data/labels/113_1.png +data/labels/114_1.png +data/labels/115_1.png +data/labels/116_1.png +data/labels/117_1.png +data/labels/118_1.png +data/labels/119_1.png +data/labels/120_1.png +data/labels/121_1.png +data/labels/122_1.png +data/labels/123_1.png +data/labels/124_1.png +data/labels/125_1.png +data/labels/126_1.png +data/labels/32_2.png +data/labels/33_2.png +data/labels/34_2.png +data/labels/35_2.png +data/labels/36_2.png +data/labels/37_2.png +data/labels/38_2.png +data/labels/39_2.png +data/labels/40_2.png +data/labels/41_2.png +data/labels/42_2.png +data/labels/43_2.png +data/labels/44_2.png +data/labels/45_2.png +data/labels/46_2.png +data/labels/47_2.png +data/labels/48_2.png +data/labels/49_2.png +data/labels/50_2.png +data/labels/51_2.png +data/labels/52_2.png +data/labels/53_2.png +data/labels/54_2.png +data/labels/55_2.png +data/labels/56_2.png +data/labels/57_2.png +data/labels/58_2.png +data/labels/59_2.png +data/labels/60_2.png +data/labels/61_2.png +data/labels/62_2.png +data/labels/63_2.png +data/labels/64_2.png +data/labels/65_2.png +data/labels/66_2.png +data/labels/67_2.png +data/labels/68_2.png +data/labels/69_2.png +data/labels/70_2.png +data/labels/71_2.png +data/labels/72_2.png +data/labels/73_2.png +data/labels/74_2.png +data/labels/75_2.png +data/labels/76_2.png +data/labels/77_2.png +data/labels/78_2.png +data/labels/79_2.png +data/labels/80_2.png +data/labels/81_2.png +data/labels/82_2.png +data/labels/83_2.png +data/labels/84_2.png +data/labels/85_2.png +data/labels/86_2.png +data/labels/87_2.png +data/labels/88_2.png +data/labels/89_2.png +data/labels/90_2.png +data/labels/91_2.png +data/labels/92_2.png +data/labels/93_2.png +data/labels/94_2.png +data/labels/95_2.png +data/labels/96_2.png +data/labels/97_2.png +data/labels/98_2.png +data/labels/99_2.png +data/labels/100_2.png +data/labels/101_2.png +data/labels/102_2.png +data/labels/103_2.png +data/labels/104_2.png +data/labels/105_2.png +data/labels/106_2.png +data/labels/107_2.png +data/labels/108_2.png +data/labels/109_2.png +data/labels/110_2.png +data/labels/111_2.png +data/labels/112_2.png +data/labels/113_2.png +data/labels/114_2.png +data/labels/115_2.png +data/labels/116_2.png +data/labels/117_2.png +data/labels/118_2.png +data/labels/119_2.png +data/labels/120_2.png +data/labels/121_2.png +data/labels/122_2.png +data/labels/123_2.png +data/labels/124_2.png +data/labels/125_2.png +data/labels/126_2.png +data/labels/32_3.png +data/labels/33_3.png +data/labels/34_3.png +data/labels/35_3.png +data/labels/36_3.png +data/labels/37_3.png +data/labels/38_3.png +data/labels/39_3.png +data/labels/40_3.png +data/labels/41_3.png +data/labels/42_3.png +data/labels/43_3.png +data/labels/44_3.png +data/labels/45_3.png +data/labels/46_3.png +data/labels/47_3.png +data/labels/48_3.png +data/labels/49_3.png +data/labels/50_3.png +data/labels/51_3.png +data/labels/52_3.png +data/labels/53_3.png +data/labels/54_3.png +data/labels/55_3.png +data/labels/56_3.png +data/labels/57_3.png +data/labels/58_3.png +data/labels/59_3.png +data/labels/60_3.png +data/labels/61_3.png +data/labels/62_3.png +data/labels/63_3.png +data/labels/64_3.png +data/labels/65_3.png +data/labels/66_3.png +data/labels/67_3.png +data/labels/68_3.png +data/labels/69_3.png +data/labels/70_3.png +data/labels/71_3.png +data/labels/72_3.png +data/labels/73_3.png +data/labels/74_3.png +data/labels/75_3.png +data/labels/76_3.png +data/labels/77_3.png +data/labels/78_3.png +data/labels/79_3.png +data/labels/80_3.png +data/labels/81_3.png +data/labels/82_3.png +data/labels/83_3.png +data/labels/84_3.png +data/labels/85_3.png +data/labels/86_3.png +data/labels/87_3.png +data/labels/88_3.png +data/labels/89_3.png +data/labels/90_3.png +data/labels/91_3.png +data/labels/92_3.png +data/labels/93_3.png +data/labels/94_3.png +data/labels/95_3.png +data/labels/96_3.png +data/labels/97_3.png +data/labels/98_3.png +data/labels/99_3.png +data/labels/100_3.png +data/labels/101_3.png +data/labels/102_3.png +data/labels/103_3.png +data/labels/104_3.png +data/labels/105_3.png +data/labels/106_3.png +data/labels/107_3.png +data/labels/108_3.png +data/labels/109_3.png +data/labels/110_3.png +data/labels/111_3.png +data/labels/112_3.png +data/labels/113_3.png +data/labels/114_3.png +data/labels/115_3.png +data/labels/116_3.png +data/labels/117_3.png +data/labels/118_3.png +data/labels/119_3.png +data/labels/120_3.png +data/labels/121_3.png +data/labels/122_3.png +data/labels/123_3.png +data/labels/124_3.png +data/labels/125_3.png +data/labels/126_3.png +data/labels/32_4.png +data/labels/33_4.png +data/labels/34_4.png +data/labels/35_4.png +data/labels/36_4.png +data/labels/37_4.png +data/labels/38_4.png +data/labels/39_4.png +data/labels/40_4.png +data/labels/41_4.png +data/labels/42_4.png +data/labels/43_4.png +data/labels/44_4.png +data/labels/45_4.png +data/labels/46_4.png +data/labels/47_4.png +data/labels/48_4.png +data/labels/49_4.png +data/labels/50_4.png +data/labels/51_4.png +data/labels/52_4.png +data/labels/53_4.png +data/labels/54_4.png +data/labels/55_4.png +data/labels/56_4.png +data/labels/57_4.png +data/labels/58_4.png +data/labels/59_4.png +data/labels/60_4.png +data/labels/61_4.png +data/labels/62_4.png +data/labels/63_4.png +data/labels/64_4.png +data/labels/65_4.png +data/labels/66_4.png +data/labels/67_4.png +data/labels/68_4.png +data/labels/69_4.png +data/labels/70_4.png +data/labels/71_4.png +data/labels/72_4.png +data/labels/73_4.png +data/labels/74_4.png +data/labels/75_4.png +data/labels/76_4.png +data/labels/77_4.png +data/labels/78_4.png +data/labels/79_4.png +data/labels/80_4.png +data/labels/81_4.png +data/labels/82_4.png +data/labels/83_4.png +data/labels/84_4.png +data/labels/85_4.png +data/labels/86_4.png +data/labels/87_4.png +data/labels/88_4.png +data/labels/89_4.png +data/labels/90_4.png +data/labels/91_4.png +data/labels/92_4.png +data/labels/93_4.png +data/labels/94_4.png +data/labels/95_4.png +data/labels/96_4.png +data/labels/97_4.png +data/labels/98_4.png +data/labels/99_4.png +data/labels/100_4.png +data/labels/101_4.png +data/labels/102_4.png +data/labels/103_4.png +data/labels/104_4.png +data/labels/105_4.png +data/labels/106_4.png +data/labels/107_4.png +data/labels/108_4.png +data/labels/109_4.png +data/labels/110_4.png +data/labels/111_4.png +data/labels/112_4.png +data/labels/113_4.png +data/labels/114_4.png +data/labels/115_4.png +data/labels/116_4.png +data/labels/117_4.png +data/labels/118_4.png +data/labels/119_4.png +data/labels/120_4.png +data/labels/121_4.png +data/labels/122_4.png +data/labels/123_4.png +data/labels/124_4.png +data/labels/125_4.png +data/labels/126_4.png +data/labels/32_5.png +data/labels/33_5.png +data/labels/34_5.png +data/labels/35_5.png +data/labels/36_5.png +data/labels/37_5.png +data/labels/38_5.png +data/labels/39_5.png +data/labels/40_5.png +data/labels/41_5.png +data/labels/42_5.png +data/labels/43_5.png +data/labels/44_5.png +data/labels/45_5.png +data/labels/46_5.png +data/labels/47_5.png +data/labels/48_5.png +data/labels/49_5.png +data/labels/50_5.png +data/labels/51_5.png +data/labels/52_5.png +data/labels/53_5.png +data/labels/54_5.png +data/labels/55_5.png +data/labels/56_5.png +data/labels/57_5.png +data/labels/58_5.png +data/labels/59_5.png +data/labels/60_5.png +data/labels/61_5.png +data/labels/62_5.png +data/labels/63_5.png +data/labels/64_5.png +data/labels/65_5.png +data/labels/66_5.png +data/labels/67_5.png +data/labels/68_5.png +data/labels/69_5.png +data/labels/70_5.png +data/labels/71_5.png +data/labels/72_5.png +data/labels/73_5.png +data/labels/74_5.png +data/labels/75_5.png +data/labels/76_5.png +data/labels/77_5.png +data/labels/78_5.png +data/labels/79_5.png +data/labels/80_5.png +data/labels/81_5.png +data/labels/82_5.png +data/labels/83_5.png +data/labels/84_5.png +data/labels/85_5.png +data/labels/86_5.png +data/labels/87_5.png +data/labels/88_5.png +data/labels/89_5.png +data/labels/90_5.png +data/labels/91_5.png +data/labels/92_5.png +data/labels/93_5.png +data/labels/94_5.png +data/labels/95_5.png +data/labels/96_5.png +data/labels/97_5.png +data/labels/98_5.png +data/labels/99_5.png +data/labels/100_5.png +data/labels/101_5.png +data/labels/102_5.png +data/labels/103_5.png +data/labels/104_5.png +data/labels/105_5.png +data/labels/106_5.png +data/labels/107_5.png +data/labels/108_5.png +data/labels/109_5.png +data/labels/110_5.png +data/labels/111_5.png +data/labels/112_5.png +data/labels/113_5.png +data/labels/114_5.png +data/labels/115_5.png +data/labels/116_5.png +data/labels/117_5.png +data/labels/118_5.png +data/labels/119_5.png +data/labels/120_5.png +data/labels/121_5.png +data/labels/122_5.png +data/labels/123_5.png +data/labels/124_5.png +data/labels/125_5.png +data/labels/126_5.png +data/labels/32_6.png +data/labels/33_6.png +data/labels/34_6.png +data/labels/35_6.png +data/labels/36_6.png +data/labels/37_6.png +data/labels/38_6.png +data/labels/39_6.png +data/labels/40_6.png +data/labels/41_6.png +data/labels/42_6.png +data/labels/43_6.png +data/labels/44_6.png +data/labels/45_6.png +data/labels/46_6.png +data/labels/47_6.png +data/labels/48_6.png +data/labels/49_6.png +data/labels/50_6.png +data/labels/51_6.png +data/labels/52_6.png +data/labels/53_6.png +data/labels/54_6.png +data/labels/55_6.png +data/labels/56_6.png +data/labels/57_6.png +data/labels/58_6.png +data/labels/59_6.png +data/labels/60_6.png +data/labels/61_6.png +data/labels/62_6.png +data/labels/63_6.png +data/labels/64_6.png +data/labels/65_6.png +data/labels/66_6.png +data/labels/67_6.png +data/labels/68_6.png +data/labels/69_6.png +data/labels/70_6.png +data/labels/71_6.png +data/labels/72_6.png +data/labels/73_6.png +data/labels/74_6.png +data/labels/75_6.png +data/labels/76_6.png +data/labels/77_6.png +data/labels/78_6.png +data/labels/79_6.png +data/labels/80_6.png +data/labels/81_6.png +data/labels/82_6.png +data/labels/83_6.png +data/labels/84_6.png +data/labels/85_6.png +data/labels/86_6.png +data/labels/87_6.png +data/labels/88_6.png +data/labels/89_6.png +data/labels/90_6.png +data/labels/91_6.png +data/labels/92_6.png +data/labels/93_6.png +data/labels/94_6.png +data/labels/95_6.png +data/labels/96_6.png +data/labels/97_6.png +data/labels/98_6.png +data/labels/99_6.png +data/labels/100_6.png +data/labels/101_6.png +data/labels/102_6.png +data/labels/103_6.png +data/labels/104_6.png +data/labels/105_6.png +data/labels/106_6.png +data/labels/107_6.png +data/labels/108_6.png +data/labels/109_6.png +data/labels/110_6.png +data/labels/111_6.png +data/labels/112_6.png +data/labels/113_6.png +data/labels/114_6.png +data/labels/115_6.png +data/labels/116_6.png +data/labels/117_6.png +data/labels/118_6.png +data/labels/119_6.png +data/labels/120_6.png +data/labels/121_6.png +data/labels/122_6.png +data/labels/123_6.png +data/labels/124_6.png +data/labels/125_6.png +data/labels/126_6.png +data/labels/32_7.png +data/labels/33_7.png +data/labels/34_7.png +data/labels/35_7.png +data/labels/36_7.png +data/labels/37_7.png +data/labels/38_7.png +data/labels/39_7.png +data/labels/40_7.png +data/labels/41_7.png +data/labels/42_7.png +data/labels/43_7.png +data/labels/44_7.png +data/labels/45_7.png +data/labels/46_7.png +data/labels/47_7.png +data/labels/48_7.png +data/labels/49_7.png +data/labels/50_7.png +data/labels/51_7.png +data/labels/52_7.png +data/labels/53_7.png +data/labels/54_7.png +data/labels/55_7.png +data/labels/56_7.png +data/labels/57_7.png +data/labels/58_7.png +data/labels/59_7.png +data/labels/60_7.png +data/labels/61_7.png +data/labels/62_7.png +data/labels/63_7.png +data/labels/64_7.png +data/labels/65_7.png +data/labels/66_7.png +data/labels/67_7.png +data/labels/68_7.png +data/labels/69_7.png +data/labels/70_7.png +data/labels/71_7.png +data/labels/72_7.png +data/labels/73_7.png +data/labels/74_7.png +data/labels/75_7.png +data/labels/76_7.png +data/labels/77_7.png +data/labels/78_7.png +data/labels/79_7.png +data/labels/80_7.png +data/labels/81_7.png +data/labels/82_7.png +data/labels/83_7.png +data/labels/84_7.png +data/labels/85_7.png +data/labels/86_7.png +data/labels/87_7.png +data/labels/88_7.png +data/labels/89_7.png +data/labels/90_7.png +data/labels/91_7.png +data/labels/92_7.png +data/labels/93_7.png +data/labels/94_7.png +data/labels/95_7.png +data/labels/96_7.png +data/labels/97_7.png +data/labels/98_7.png +data/labels/99_7.png +data/labels/100_7.png +data/labels/101_7.png +data/labels/102_7.png +data/labels/103_7.png +data/labels/104_7.png +data/labels/105_7.png +data/labels/106_7.png +data/labels/107_7.png +data/labels/108_7.png +data/labels/109_7.png +data/labels/110_7.png +data/labels/111_7.png +data/labels/112_7.png +data/labels/113_7.png +data/labels/114_7.png +data/labels/115_7.png +data/labels/116_7.png +data/labels/117_7.png +data/labels/118_7.png +data/labels/119_7.png +data/labels/120_7.png +data/labels/121_7.png +data/labels/122_7.png +data/labels/123_7.png +data/labels/124_7.png +data/labels/125_7.png +data/labels/126_7.png +data/labels/32_0.png +data/labels/33_0.png +data/labels/34_0.png +data/labels/35_0.png +data/labels/36_0.png +data/labels/37_0.png +data/labels/38_0.png +data/labels/39_0.png +data/labels/40_0.png +data/labels/41_0.png +data/labels/42_0.png +data/labels/43_0.png +data/labels/44_0.png +data/labels/45_0.png +data/labels/46_0.png +data/labels/47_0.png +data/labels/48_0.png +data/labels/49_0.png +data/labels/50_0.png +data/labels/51_0.png +data/labels/52_0.png +data/labels/53_0.png +data/labels/54_0.png +data/labels/55_0.png +data/labels/56_0.png +data/labels/57_0.png +data/labels/58_0.png +data/labels/59_0.png +data/labels/60_0.png +data/labels/61_0.png +data/labels/62_0.png +data/labels/63_0.png +data/labels/64_0.png +data/labels/65_0.png +data/labels/66_0.png +data/labels/67_0.png +data/labels/68_0.png +data/labels/69_0.png +data/labels/70_0.png +data/labels/71_0.png +data/labels/72_0.png +data/labels/73_0.png +data/labels/74_0.png +data/labels/75_0.png +data/labels/76_0.png +data/labels/77_0.png +data/labels/78_0.png +data/labels/79_0.png +data/labels/80_0.png +data/labels/81_0.png +data/labels/82_0.png +data/labels/83_0.png +data/labels/84_0.png +data/labels/85_0.png +data/labels/86_0.png +data/labels/87_0.png +data/labels/88_0.png +data/labels/89_0.png +data/labels/90_0.png +data/labels/91_0.png +data/labels/92_0.png +data/labels/93_0.png +data/labels/94_0.png +data/labels/95_0.png +data/labels/96_0.png +data/labels/97_0.png +data/labels/98_0.png +data/labels/99_0.png +data/labels/100_0.png +data/labels/101_0.png +data/labels/102_0.png +data/labels/103_0.png +data/labels/104_0.png +data/labels/105_0.png +data/labels/106_0.png +data/labels/107_0.png +data/labels/108_0.png +data/labels/109_0.png +data/labels/110_0.png +data/labels/111_0.png +data/labels/112_0.png +data/labels/113_0.png +data/labels/114_0.png +data/labels/115_0.png +data/labels/116_0.png +data/labels/117_0.png +data/labels/118_0.png +data/labels/119_0.png +data/labels/120_0.png +data/labels/121_0.png +data/labels/122_0.png +data/labels/123_0.png +data/labels/124_0.png +data/labels/125_0.png +data/labels/126_0.png +data/labels/32_1.png +data/labels/33_1.png +data/labels/34_1.png +data/labels/35_1.png +data/labels/36_1.png +data/labels/37_1.png +data/labels/38_1.png +data/labels/39_1.png +data/labels/40_1.png +data/labels/41_1.png +data/labels/42_1.png +data/labels/43_1.png +data/labels/44_1.png +data/labels/45_1.png +data/labels/46_1.png +data/labels/47_1.png +data/labels/48_1.png +data/labels/49_1.png +data/labels/50_1.png +data/labels/51_1.png +data/labels/52_1.png +data/labels/53_1.png +data/labels/54_1.png +data/labels/55_1.png +data/labels/56_1.png +data/labels/57_1.png +data/labels/58_1.png +data/labels/59_1.png +data/labels/60_1.png +data/labels/61_1.png +data/labels/62_1.png +data/labels/63_1.png +data/labels/64_1.png +data/labels/65_1.png +data/labels/66_1.png +data/labels/67_1.png +data/labels/68_1.png +data/labels/69_1.png +data/labels/70_1.png +data/labels/71_1.png +data/labels/72_1.png +data/labels/73_1.png +data/labels/74_1.png +data/labels/75_1.png +data/labels/76_1.png +data/labels/77_1.png +data/labels/78_1.png +data/labels/79_1.png +data/labels/80_1.png +data/labels/81_1.png +data/labels/82_1.png +data/labels/83_1.png +data/labels/84_1.png +data/labels/85_1.png +data/labels/86_1.png +data/labels/87_1.png +data/labels/88_1.png +data/labels/89_1.png +data/labels/90_1.png +data/labels/91_1.png +data/labels/92_1.png +data/labels/93_1.png +data/labels/94_1.png +data/labels/95_1.png +data/labels/96_1.png +data/labels/97_1.png +data/labels/98_1.png +data/labels/99_1.png +data/labels/100_1.png +data/labels/101_1.png +data/labels/102_1.png +data/labels/103_1.png +data/labels/104_1.png +data/labels/105_1.png +data/labels/106_1.png +data/labels/107_1.png +data/labels/108_1.png +data/labels/109_1.png +data/labels/110_1.png +data/labels/111_1.png +data/labels/112_1.png +data/labels/113_1.png +data/labels/114_1.png +data/labels/115_1.png +data/labels/116_1.png +data/labels/117_1.png +data/labels/118_1.png +data/labels/119_1.png +data/labels/120_1.png +data/labels/121_1.png +data/labels/122_1.png +data/labels/123_1.png +data/labels/124_1.png +data/labels/125_1.png +data/labels/126_1.png +data/labels/32_2.png +data/labels/33_2.png +data/labels/34_2.png +data/labels/35_2.png +data/labels/36_2.png +data/labels/37_2.png +data/labels/38_2.png +data/labels/39_2.png +data/labels/40_2.png +data/labels/41_2.png +data/labels/42_2.png +data/labels/43_2.png +data/labels/44_2.png +data/labels/45_2.png +data/labels/46_2.png +data/labels/47_2.png +data/labels/48_2.png +data/labels/49_2.png +data/labels/50_2.png +data/labels/51_2.png +data/labels/52_2.png +data/labels/53_2.png +data/labels/54_2.png +data/labels/55_2.png +data/labels/56_2.png +data/labels/57_2.png +data/labels/58_2.png +data/labels/59_2.png +data/labels/60_2.png +data/labels/61_2.png +data/labels/62_2.png +data/labels/63_2.png +data/labels/64_2.png +data/labels/65_2.png +data/labels/66_2.png +data/labels/67_2.png +data/labels/68_2.png +data/labels/69_2.png +data/labels/70_2.png +data/labels/71_2.png +data/labels/72_2.png +data/labels/73_2.png +data/labels/74_2.png +data/labels/75_2.png +data/labels/76_2.png +data/labels/77_2.png +data/labels/78_2.png +data/labels/79_2.png +data/labels/80_2.png +data/labels/81_2.png +data/labels/82_2.png +data/labels/83_2.png +data/labels/84_2.png +data/labels/85_2.png +data/labels/86_2.png +data/labels/87_2.png +data/labels/88_2.png +data/labels/89_2.png +data/labels/90_2.png +data/labels/91_2.png +data/labels/92_2.png +data/labels/93_2.png +data/labels/94_2.png +data/labels/95_2.png +data/labels/96_2.png +data/labels/97_2.png +data/labels/98_2.png +data/labels/99_2.png +data/labels/100_2.png +data/labels/101_2.png +data/labels/102_2.png +data/labels/103_2.png +data/labels/104_2.png +data/labels/105_2.png +data/labels/106_2.png +data/labels/107_2.png +data/labels/108_2.png +data/labels/109_2.png +data/labels/110_2.png +data/labels/111_2.png +data/labels/112_2.png +data/labels/113_2.png +data/labels/114_2.png +data/labels/115_2.png +data/labels/116_2.png +data/labels/117_2.png +data/labels/118_2.png +data/labels/119_2.png +data/labels/120_2.png +data/labels/121_2.png +data/labels/122_2.png +data/labels/123_2.png +data/labels/124_2.png +data/labels/125_2.png +data/labels/126_2.png +data/labels/32_3.png +data/labels/33_3.png +data/labels/34_3.png +data/labels/35_3.png +data/labels/36_3.png +data/labels/37_3.png +data/labels/38_3.png +data/labels/39_3.png +data/labels/40_3.png +data/labels/41_3.png +data/labels/42_3.png +data/labels/43_3.png +data/labels/44_3.png +data/labels/45_3.png +data/labels/46_3.png +data/labels/47_3.png +data/labels/48_3.png +data/labels/49_3.png +data/labels/50_3.png +data/labels/51_3.png +data/labels/52_3.png +data/labels/53_3.png +data/labels/54_3.png +data/labels/55_3.png +data/labels/56_3.png +data/labels/57_3.png +data/labels/58_3.png +data/labels/59_3.png +data/labels/60_3.png +data/labels/61_3.png +data/labels/62_3.png +data/labels/63_3.png +data/labels/64_3.png +data/labels/65_3.png +data/labels/66_3.png +data/labels/67_3.png +data/labels/68_3.png +data/labels/69_3.png +data/labels/70_3.png +data/labels/71_3.png +data/labels/72_3.png +data/labels/73_3.png +data/labels/74_3.png +data/labels/75_3.png +data/labels/76_3.png +data/labels/77_3.png +data/labels/78_3.png +data/labels/79_3.png +data/labels/80_3.png +data/labels/81_3.png +data/labels/82_3.png +data/labels/83_3.png +data/labels/84_3.png +data/labels/85_3.png +data/labels/86_3.png +data/labels/87_3.png +data/labels/88_3.png +data/labels/89_3.png +data/labels/90_3.png +data/labels/91_3.png +data/labels/92_3.png +data/labels/93_3.png +data/labels/94_3.png +data/labels/95_3.png +data/labels/96_3.png +data/labels/97_3.png +data/labels/98_3.png +data/labels/99_3.png +data/labels/100_3.png +data/labels/101_3.png +data/labels/102_3.png +data/labels/103_3.png +data/labels/104_3.png +data/labels/105_3.png +data/labels/106_3.png +data/labels/107_3.png +data/labels/108_3.png +data/labels/109_3.png +data/labels/110_3.png +data/labels/111_3.png +data/labels/112_3.png +data/labels/113_3.png +data/labels/114_3.png +data/labels/115_3.png +data/labels/116_3.png +data/labels/117_3.png +data/labels/118_3.png +data/labels/119_3.png +data/labels/120_3.png +data/labels/121_3.png +data/labels/122_3.png +data/labels/123_3.png +data/labels/124_3.png +data/labels/125_3.png +data/labels/126_3.png +data/labels/32_4.png +data/labels/33_4.png +data/labels/34_4.png +data/labels/35_4.png +data/labels/36_4.png +data/labels/37_4.png +data/labels/38_4.png +data/labels/39_4.png +data/labels/40_4.png +data/labels/41_4.png +data/labels/42_4.png +data/labels/43_4.png +data/labels/44_4.png +data/labels/45_4.png +data/labels/46_4.png +data/labels/47_4.png +data/labels/48_4.png +data/labels/49_4.png +data/labels/50_4.png +data/labels/51_4.png +data/labels/52_4.png +data/labels/53_4.png +data/labels/54_4.png +data/labels/55_4.png +data/labels/56_4.png +data/labels/57_4.png +data/labels/58_4.png +data/labels/59_4.png +data/labels/60_4.png +data/labels/61_4.png +data/labels/62_4.png +data/labels/63_4.png +data/labels/64_4.png +data/labels/65_4.png +data/labels/66_4.png +data/labels/67_4.png +data/labels/68_4.png +data/labels/69_4.png +data/labels/70_4.png +data/labels/71_4.png +data/labels/72_4.png +data/labels/73_4.png +data/labels/74_4.png +data/labels/75_4.png +data/labels/76_4.png +data/labels/77_4.png +data/labels/78_4.png +data/labels/79_4.png +data/labels/80_4.png +data/labels/81_4.png +data/labels/82_4.png +data/labels/83_4.png +data/labels/84_4.png +data/labels/85_4.png +data/labels/86_4.png +data/labels/87_4.png +data/labels/88_4.png +data/labels/89_4.png +data/labels/90_4.png +data/labels/91_4.png +data/labels/92_4.png +data/labels/93_4.png +data/labels/94_4.png +data/labels/95_4.png +data/labels/96_4.png +data/labels/97_4.png +data/labels/98_4.png +data/labels/99_4.png +data/labels/100_4.png +data/labels/101_4.png +data/labels/102_4.png +data/labels/103_4.png +data/labels/104_4.png +data/labels/105_4.png +data/labels/106_4.png +data/labels/107_4.png +data/labels/108_4.png +data/labels/109_4.png +data/labels/110_4.png +data/labels/111_4.png +data/labels/112_4.png +data/labels/113_4.png +data/labels/114_4.png +data/labels/115_4.png +data/labels/116_4.png +data/labels/117_4.png +data/labels/118_4.png +data/labels/119_4.png +data/labels/120_4.png +data/labels/121_4.png +data/labels/122_4.png +data/labels/123_4.png +data/labels/124_4.png +data/labels/125_4.png +data/labels/126_4.png +data/labels/32_5.png +data/labels/33_5.png +data/labels/34_5.png +data/labels/35_5.png +data/labels/36_5.png +data/labels/37_5.png +data/labels/38_5.png +data/labels/39_5.png +data/labels/40_5.png +data/labels/41_5.png +data/labels/42_5.png +data/labels/43_5.png +data/labels/44_5.png +data/labels/45_5.png +data/labels/46_5.png +data/labels/47_5.png +data/labels/48_5.png +data/labels/49_5.png +data/labels/50_5.png +data/labels/51_5.png +data/labels/52_5.png +data/labels/53_5.png +data/labels/54_5.png +data/labels/55_5.png +data/labels/56_5.png +data/labels/57_5.png +data/labels/58_5.png +data/labels/59_5.png +data/labels/60_5.png +data/labels/61_5.png +data/labels/62_5.png +data/labels/63_5.png +data/labels/64_5.png +data/labels/65_5.png +data/labels/66_5.png +data/labels/67_5.png +data/labels/68_5.png +data/labels/69_5.png +data/labels/70_5.png +data/labels/71_5.png +data/labels/72_5.png +data/labels/73_5.png +data/labels/74_5.png +data/labels/75_5.png +data/labels/76_5.png +data/labels/77_5.png +data/labels/78_5.png +data/labels/79_5.png +data/labels/80_5.png +data/labels/81_5.png +data/labels/82_5.png +data/labels/83_5.png +data/labels/84_5.png +data/labels/85_5.png +data/labels/86_5.png +data/labels/87_5.png +data/labels/88_5.png +data/labels/89_5.png +data/labels/90_5.png +data/labels/91_5.png +data/labels/92_5.png +data/labels/93_5.png +data/labels/94_5.png +data/labels/95_5.png +data/labels/96_5.png +data/labels/97_5.png +data/labels/98_5.png +data/labels/99_5.png +data/labels/100_5.png +data/labels/101_5.png +data/labels/102_5.png +data/labels/103_5.png +data/labels/104_5.png +data/labels/105_5.png +data/labels/106_5.png +data/labels/107_5.png +data/labels/108_5.png +data/labels/109_5.png +data/labels/110_5.png +data/labels/111_5.png +data/labels/112_5.png +data/labels/113_5.png +data/labels/114_5.png +data/labels/115_5.png +data/labels/116_5.png +data/labels/117_5.png +data/labels/118_5.png +data/labels/119_5.png +data/labels/120_5.png +data/labels/121_5.png +data/labels/122_5.png +data/labels/123_5.png +data/labels/124_5.png +data/labels/125_5.png +data/labels/126_5.png +data/labels/32_6.png +data/labels/33_6.png +data/labels/34_6.png +data/labels/35_6.png +data/labels/36_6.png +data/labels/37_6.png +data/labels/38_6.png +data/labels/39_6.png +data/labels/40_6.png +data/labels/41_6.png +data/labels/42_6.png +data/labels/43_6.png +data/labels/44_6.png +data/labels/45_6.png +data/labels/46_6.png +data/labels/47_6.png +data/labels/48_6.png +data/labels/49_6.png +data/labels/50_6.png +data/labels/51_6.png +data/labels/52_6.png +data/labels/53_6.png +data/labels/54_6.png +data/labels/55_6.png +data/labels/56_6.png +data/labels/57_6.png +data/labels/58_6.png +data/labels/59_6.png +data/labels/60_6.png +data/labels/61_6.png +data/labels/62_6.png +data/labels/63_6.png +data/labels/64_6.png +data/labels/65_6.png +data/labels/66_6.png +data/labels/67_6.png +data/labels/68_6.png +data/labels/69_6.png +data/labels/70_6.png +data/labels/71_6.png +data/labels/72_6.png +data/labels/73_6.png +data/labels/74_6.png +data/labels/75_6.png +data/labels/76_6.png +data/labels/77_6.png +data/labels/78_6.png +data/labels/79_6.png +data/labels/80_6.png +data/labels/81_6.png +data/labels/82_6.png +data/labels/83_6.png +data/labels/84_6.png +data/labels/85_6.png +data/labels/86_6.png +data/labels/87_6.png +data/labels/88_6.png +data/labels/89_6.png +data/labels/90_6.png +data/labels/91_6.png +data/labels/92_6.png +data/labels/93_6.png +data/labels/94_6.png +data/labels/95_6.png +data/labels/96_6.png +data/labels/97_6.png +data/labels/98_6.png +data/labels/99_6.png +data/labels/100_6.png +data/labels/101_6.png +data/labels/102_6.png +data/labels/103_6.png +data/labels/104_6.png +data/labels/105_6.png +data/labels/106_6.png +data/labels/107_6.png +data/labels/108_6.png +data/labels/109_6.png +data/labels/110_6.png +data/labels/111_6.png +data/labels/112_6.png +data/labels/113_6.png +data/labels/114_6.png +data/labels/115_6.png +data/labels/116_6.png +data/labels/117_6.png +data/labels/118_6.png +data/labels/119_6.png +data/labels/120_6.png +data/labels/121_6.png +data/labels/122_6.png +data/labels/123_6.png +data/labels/124_6.png +data/labels/125_6.png +data/labels/126_6.png +data/labels/32_7.png +data/labels/33_7.png +data/labels/34_7.png +data/labels/35_7.png +data/labels/36_7.png +data/labels/37_7.png +data/labels/38_7.png +data/labels/39_7.png +data/labels/40_7.png +data/labels/41_7.png +data/labels/42_7.png +data/labels/43_7.png +data/labels/44_7.png +data/labels/45_7.png +data/labels/46_7.png +data/labels/47_7.png +data/labels/48_7.png +data/labels/49_7.png +data/labels/50_7.png +data/labels/51_7.png +data/labels/52_7.png +data/labels/53_7.png +data/labels/54_7.png +data/labels/55_7.png +data/labels/56_7.png +data/labels/57_7.png +data/labels/58_7.png +data/labels/59_7.png +data/labels/60_7.png +data/labels/61_7.png +data/labels/62_7.png +data/labels/63_7.png +data/labels/64_7.png +data/labels/65_7.png +data/labels/66_7.png +data/labels/67_7.png +data/labels/68_7.png +data/labels/69_7.png +data/labels/70_7.png +data/labels/71_7.png +data/labels/72_7.png +data/labels/73_7.png +data/labels/74_7.png +data/labels/75_7.png +data/labels/76_7.png +data/labels/77_7.png +data/labels/78_7.png +data/labels/79_7.png +data/labels/80_7.png +data/labels/81_7.png +data/labels/82_7.png +data/labels/83_7.png +data/labels/84_7.png +data/labels/85_7.png +data/labels/86_7.png +data/labels/87_7.png +data/labels/88_7.png +data/labels/89_7.png +data/labels/90_7.png +data/labels/91_7.png +data/labels/92_7.png +data/labels/93_7.png +data/labels/94_7.png +data/labels/95_7.png +data/labels/96_7.png +data/labels/97_7.png +data/labels/98_7.png +data/labels/99_7.png +data/labels/100_7.png +data/labels/101_7.png +data/labels/102_7.png +data/labels/103_7.png +data/labels/104_7.png +data/labels/105_7.png +data/labels/106_7.png +data/labels/107_7.png +data/labels/108_7.png +data/labels/109_7.png +data/labels/110_7.png +data/labels/111_7.png +data/labels/112_7.png +data/labels/113_7.png +data/labels/114_7.png +data/labels/115_7.png +data/labels/116_7.png +data/labels/117_7.png +data/labels/118_7.png +data/labels/119_7.png +data/labels/120_7.png +data/labels/121_7.png +data/labels/122_7.png +data/labels/123_7.png +data/labels/124_7.png +data/labels/125_7.png +data/labels/126_7.png +data/labels/32_0.png +data/labels/33_0.png +data/labels/34_0.png +data/labels/35_0.png +data/labels/36_0.png +data/labels/37_0.png +data/labels/38_0.png +data/labels/39_0.png +data/labels/40_0.png +data/labels/41_0.png +data/labels/42_0.png +data/labels/43_0.png +data/labels/44_0.png +data/labels/45_0.png +data/labels/46_0.png +data/labels/47_0.png +data/labels/48_0.png +data/labels/49_0.png +data/labels/50_0.png +data/labels/51_0.png +data/labels/52_0.png +data/labels/53_0.png +data/labels/54_0.png +data/labels/55_0.png +data/labels/56_0.png +data/labels/57_0.png +data/labels/58_0.png +data/labels/59_0.png +data/labels/60_0.png +data/labels/61_0.png +data/labels/62_0.png +data/labels/63_0.png +data/labels/64_0.png +data/labels/65_0.png +data/labels/66_0.png +data/labels/67_0.png +data/labels/68_0.png +data/labels/69_0.png +data/labels/70_0.png +data/labels/71_0.png +data/labels/72_0.png +data/labels/73_0.png +data/labels/74_0.png +data/labels/75_0.png +data/labels/76_0.png +data/labels/77_0.png +data/labels/78_0.png +data/labels/79_0.png +data/labels/80_0.png +data/labels/81_0.png +data/labels/82_0.png +data/labels/83_0.png +data/labels/84_0.png +data/labels/85_0.png +data/labels/86_0.png +data/labels/87_0.png +data/labels/88_0.png +data/labels/89_0.png +data/labels/90_0.png +data/labels/91_0.png +data/labels/92_0.png +data/labels/93_0.png +data/labels/94_0.png +data/labels/95_0.png +data/labels/96_0.png +data/labels/97_0.png +data/labels/98_0.png +data/labels/99_0.png +data/labels/100_0.png +data/labels/101_0.png +data/labels/102_0.png +data/labels/103_0.png +data/labels/104_0.png +data/labels/105_0.png +data/labels/106_0.png +data/labels/107_0.png +data/labels/108_0.png +data/labels/109_0.png +data/labels/110_0.png +data/labels/111_0.png +data/labels/112_0.png +data/labels/113_0.png +data/labels/114_0.png +data/labels/115_0.png +data/labels/116_0.png +data/labels/117_0.png +data/labels/118_0.png +data/labels/119_0.png +data/labels/120_0.png +data/labels/121_0.png +data/labels/122_0.png +data/labels/123_0.png +data/labels/124_0.png +data/labels/125_0.png +data/labels/126_0.png +data/labels/32_1.png +data/labels/33_1.png +data/labels/34_1.png +data/labels/35_1.png +data/labels/36_1.png +data/labels/37_1.png +data/labels/38_1.png +data/labels/39_1.png +data/labels/40_1.png +data/labels/41_1.png +data/labels/42_1.png +data/labels/43_1.png +data/labels/44_1.png +data/labels/45_1.png +data/labels/46_1.png +data/labels/47_1.png +data/labels/48_1.png +data/labels/49_1.png +data/labels/50_1.png +data/labels/51_1.png +data/labels/52_1.png +data/labels/53_1.png +data/labels/54_1.png +data/labels/55_1.png +data/labels/56_1.png +data/labels/57_1.png +data/labels/58_1.png +data/labels/59_1.png +data/labels/60_1.png +data/labels/61_1.png +data/labels/62_1.png +data/labels/63_1.png +data/labels/64_1.png +data/labels/65_1.png +data/labels/66_1.png +data/labels/67_1.png +data/labels/68_1.png +data/labels/69_1.png +data/labels/70_1.png +data/labels/71_1.png +data/labels/72_1.png +data/labels/73_1.png +data/labels/74_1.png +data/labels/75_1.png +data/labels/76_1.png +data/labels/77_1.png +data/labels/78_1.png +data/labels/79_1.png +data/labels/80_1.png +data/labels/81_1.png +data/labels/82_1.png +data/labels/83_1.png +data/labels/84_1.png +data/labels/85_1.png +data/labels/86_1.png +data/labels/87_1.png +data/labels/88_1.png +data/labels/89_1.png +data/labels/90_1.png +data/labels/91_1.png +data/labels/92_1.png +data/labels/93_1.png +data/labels/94_1.png +data/labels/95_1.png +data/labels/96_1.png +data/labels/97_1.png +data/labels/98_1.png +data/labels/99_1.png +data/labels/100_1.png +data/labels/101_1.png +data/labels/102_1.png +data/labels/103_1.png +data/labels/104_1.png +data/labels/105_1.png +data/labels/106_1.png +data/labels/107_1.png +data/labels/108_1.png +data/labels/109_1.png +data/labels/110_1.png +data/labels/111_1.png +data/labels/112_1.png +data/labels/113_1.png +data/labels/114_1.png +data/labels/115_1.png +data/labels/116_1.png +data/labels/117_1.png +data/labels/118_1.png +data/labels/119_1.png +data/labels/120_1.png +data/labels/121_1.png +data/labels/122_1.png +data/labels/123_1.png +data/labels/124_1.png +data/labels/125_1.png +data/labels/126_1.png +data/labels/32_2.png +data/labels/33_2.png +data/labels/34_2.png +data/labels/35_2.png +data/labels/36_2.png +data/labels/37_2.png +data/labels/38_2.png +data/labels/39_2.png +data/labels/40_2.png +data/labels/41_2.png +data/labels/42_2.png +data/labels/43_2.png +data/labels/44_2.png +data/labels/45_2.png +data/labels/46_2.png +data/labels/47_2.png +data/labels/48_2.png +data/labels/49_2.png +data/labels/50_2.png +data/labels/51_2.png +data/labels/52_2.png +data/labels/53_2.png +data/labels/54_2.png +data/labels/55_2.png +data/labels/56_2.png +data/labels/57_2.png +data/labels/58_2.png +data/labels/59_2.png +data/labels/60_2.png +data/labels/61_2.png +data/labels/62_2.png +data/labels/63_2.png +data/labels/64_2.png +data/labels/65_2.png +data/labels/66_2.png +data/labels/67_2.png +data/labels/68_2.png +data/labels/69_2.png +data/labels/70_2.png +data/labels/71_2.png +data/labels/72_2.png +data/labels/73_2.png +data/labels/74_2.png +data/labels/75_2.png +data/labels/76_2.png +data/labels/77_2.png +data/labels/78_2.png +data/labels/79_2.png +data/labels/80_2.png +data/labels/81_2.png +data/labels/82_2.png +data/labels/83_2.png +data/labels/84_2.png +data/labels/85_2.png +data/labels/86_2.png +data/labels/87_2.png +data/labels/88_2.png +data/labels/89_2.png +data/labels/90_2.png +data/labels/91_2.png +data/labels/92_2.png +data/labels/93_2.png +data/labels/94_2.png +data/labels/95_2.png +data/labels/96_2.png +data/labels/97_2.png +data/labels/98_2.png +data/labels/99_2.png +data/labels/100_2.png +data/labels/101_2.png +data/labels/102_2.png +data/labels/103_2.png +data/labels/104_2.png +data/labels/105_2.png +data/labels/106_2.png +data/labels/107_2.png +data/labels/108_2.png +data/labels/109_2.png +data/labels/110_2.png +data/labels/111_2.png +data/labels/112_2.png +data/labels/113_2.png +data/labels/114_2.png +data/labels/115_2.png +data/labels/116_2.png +data/labels/117_2.png +data/labels/118_2.png +data/labels/119_2.png +data/labels/120_2.png +data/labels/121_2.png +data/labels/122_2.png +data/labels/123_2.png +data/labels/124_2.png +data/labels/125_2.png +data/labels/126_2.png +data/labels/32_3.png +data/labels/33_3.png +data/labels/34_3.png +data/labels/35_3.png +data/labels/36_3.png +data/labels/37_3.png +data/labels/38_3.png +data/labels/39_3.png +data/labels/40_3.png +data/labels/41_3.png +data/labels/42_3.png +data/labels/43_3.png +data/labels/44_3.png +data/labels/45_3.png +data/labels/46_3.png +data/labels/47_3.png +data/labels/48_3.png +data/labels/49_3.png +data/labels/50_3.png +data/labels/51_3.png +data/labels/52_3.png +data/labels/53_3.png +data/labels/54_3.png +data/labels/55_3.png +data/labels/56_3.png +data/labels/57_3.png +data/labels/58_3.png +data/labels/59_3.png +data/labels/60_3.png +data/labels/61_3.png +data/labels/62_3.png +data/labels/63_3.png +data/labels/64_3.png +data/labels/65_3.png +data/labels/66_3.png +data/labels/67_3.png +data/labels/68_3.png +data/labels/69_3.png +data/labels/70_3.png +data/labels/71_3.png +data/labels/72_3.png +data/labels/73_3.png +data/labels/74_3.png +data/labels/75_3.png +data/labels/76_3.png +data/labels/77_3.png +data/labels/78_3.png +data/labels/79_3.png +data/labels/80_3.png +data/labels/81_3.png +data/labels/82_3.png +data/labels/83_3.png +data/labels/84_3.png +data/labels/85_3.png +data/labels/86_3.png +data/labels/87_3.png +data/labels/88_3.png +data/labels/89_3.png +data/labels/90_3.png +data/labels/91_3.png +data/labels/92_3.png +data/labels/93_3.png +data/labels/94_3.png +data/labels/95_3.png +data/labels/96_3.png +data/labels/97_3.png +data/labels/98_3.png +data/labels/99_3.png +data/labels/100_3.png +data/labels/101_3.png +data/labels/102_3.png +data/labels/103_3.png +data/labels/104_3.png +data/labels/105_3.png +data/labels/106_3.png +data/labels/107_3.png +data/labels/108_3.png +data/labels/109_3.png +data/labels/110_3.png +data/labels/111_3.png +data/labels/112_3.png +data/labels/113_3.png +data/labels/114_3.png +data/labels/115_3.png +data/labels/116_3.png +data/labels/117_3.png +data/labels/118_3.png +data/labels/119_3.png +data/labels/120_3.png +data/labels/121_3.png +data/labels/122_3.png +data/labels/123_3.png +data/labels/124_3.png +data/labels/125_3.png +data/labels/126_3.png +data/labels/32_4.png +data/labels/33_4.png +data/labels/34_4.png +data/labels/35_4.png +data/labels/36_4.png +data/labels/37_4.png +data/labels/38_4.png +data/labels/39_4.png +data/labels/40_4.png +data/labels/41_4.png +data/labels/42_4.png +data/labels/43_4.png +data/labels/44_4.png +data/labels/45_4.png +data/labels/46_4.png +data/labels/47_4.png +data/labels/48_4.png +data/labels/49_4.png +data/labels/50_4.png +data/labels/51_4.png +data/labels/52_4.png +data/labels/53_4.png +data/labels/54_4.png +data/labels/55_4.png +data/labels/56_4.png +data/labels/57_4.png +data/labels/58_4.png +data/labels/59_4.png +data/labels/60_4.png +data/labels/61_4.png +data/labels/62_4.png +data/labels/63_4.png +data/labels/64_4.png +data/labels/65_4.png +data/labels/66_4.png +data/labels/67_4.png +data/labels/68_4.png +data/labels/69_4.png +data/labels/70_4.png +data/labels/71_4.png +data/labels/72_4.png +data/labels/73_4.png +data/labels/74_4.png +data/labels/75_4.png +data/labels/76_4.png +data/labels/77_4.png +data/labels/78_4.png +data/labels/79_4.png +data/labels/80_4.png +data/labels/81_4.png +data/labels/82_4.png +data/labels/83_4.png +data/labels/84_4.png +data/labels/85_4.png +data/labels/86_4.png +data/labels/87_4.png +data/labels/88_4.png +data/labels/89_4.png +data/labels/90_4.png +data/labels/91_4.png +data/labels/92_4.png +data/labels/93_4.png +data/labels/94_4.png +data/labels/95_4.png +data/labels/96_4.png +data/labels/97_4.png +data/labels/98_4.png +data/labels/99_4.png +data/labels/100_4.png +data/labels/101_4.png +data/labels/102_4.png +data/labels/103_4.png +data/labels/104_4.png +data/labels/105_4.png +data/labels/106_4.png +data/labels/107_4.png +data/labels/108_4.png +data/labels/109_4.png +data/labels/110_4.png +data/labels/111_4.png +data/labels/112_4.png +data/labels/113_4.png +data/labels/114_4.png +data/labels/115_4.png +data/labels/116_4.png +data/labels/117_4.png +data/labels/118_4.png +data/labels/119_4.png +data/labels/120_4.png +data/labels/121_4.png +data/labels/122_4.png +data/labels/123_4.png +data/labels/124_4.png +data/labels/125_4.png +data/labels/126_4.png +data/labels/32_5.png +data/labels/33_5.png +data/labels/34_5.png +data/labels/35_5.png +data/labels/36_5.png +data/labels/37_5.png +data/labels/38_5.png +data/labels/39_5.png +data/labels/40_5.png +data/labels/41_5.png +data/labels/42_5.png +data/labels/43_5.png +data/labels/44_5.png +data/labels/45_5.png +data/labels/46_5.png +data/labels/47_5.png +data/labels/48_5.png +data/labels/49_5.png +data/labels/50_5.png +data/labels/51_5.png +data/labels/52_5.png +data/labels/53_5.png +data/labels/54_5.png +data/labels/55_5.png +data/labels/56_5.png +data/labels/57_5.png +data/labels/58_5.png +data/labels/59_5.png +data/labels/60_5.png +data/labels/61_5.png +data/labels/62_5.png +data/labels/63_5.png +data/labels/64_5.png +data/labels/65_5.png +data/labels/66_5.png +data/labels/67_5.png +data/labels/68_5.png +data/labels/69_5.png +data/labels/70_5.png +data/labels/71_5.png +data/labels/72_5.png +data/labels/73_5.png +data/labels/74_5.png +data/labels/75_5.png +data/labels/76_5.png +data/labels/77_5.png +data/labels/78_5.png +data/labels/79_5.png +data/labels/80_5.png +data/labels/81_5.png +data/labels/82_5.png +data/labels/83_5.png +data/labels/84_5.png +data/labels/85_5.png +data/labels/86_5.png +data/labels/87_5.png +data/labels/88_5.png +data/labels/89_5.png +data/labels/90_5.png +data/labels/91_5.png +data/labels/92_5.png +data/labels/93_5.png +data/labels/94_5.png +data/labels/95_5.png +data/labels/96_5.png +data/labels/97_5.png +data/labels/98_5.png +data/labels/99_5.png +data/labels/100_5.png +data/labels/101_5.png +data/labels/102_5.png +data/labels/103_5.png +data/labels/104_5.png +data/labels/105_5.png +data/labels/106_5.png +data/labels/107_5.png +data/labels/108_5.png +data/labels/109_5.png +data/labels/110_5.png +data/labels/111_5.png +data/labels/112_5.png +data/labels/113_5.png +data/labels/114_5.png +data/labels/115_5.png +data/labels/116_5.png +data/labels/117_5.png +data/labels/118_5.png +data/labels/119_5.png +data/labels/120_5.png +data/labels/121_5.png +data/labels/122_5.png +data/labels/123_5.png +data/labels/124_5.png +data/labels/125_5.png +data/labels/126_5.png +data/labels/32_6.png +data/labels/33_6.png +data/labels/34_6.png +data/labels/35_6.png +data/labels/36_6.png +data/labels/37_6.png +data/labels/38_6.png +data/labels/39_6.png +data/labels/40_6.png +data/labels/41_6.png +data/labels/42_6.png +data/labels/43_6.png +data/labels/44_6.png +data/labels/45_6.png +data/labels/46_6.png +data/labels/47_6.png +data/labels/48_6.png +data/labels/49_6.png +data/labels/50_6.png +data/labels/51_6.png +data/labels/52_6.png +data/labels/53_6.png +data/labels/54_6.png +data/labels/55_6.png +data/labels/56_6.png +data/labels/57_6.png +data/labels/58_6.png +data/labels/59_6.png +data/labels/60_6.png +data/labels/61_6.png +data/labels/62_6.png +data/labels/63_6.png +data/labels/64_6.png +data/labels/65_6.png +data/labels/66_6.png +data/labels/67_6.png +data/labels/68_6.png +data/labels/69_6.png +data/labels/70_6.png +data/labels/71_6.png +data/labels/72_6.png +data/labels/73_6.png +data/labels/74_6.png +data/labels/75_6.png +data/labels/76_6.png +data/labels/77_6.png +data/labels/78_6.png +data/labels/79_6.png +data/labels/80_6.png +data/labels/81_6.png +data/labels/82_6.png +data/labels/83_6.png +data/labels/84_6.png +data/labels/85_6.png +data/labels/86_6.png +data/labels/87_6.png +data/labels/88_6.png +data/labels/89_6.png +data/labels/90_6.png +data/labels/91_6.png +data/labels/92_6.png +data/labels/93_6.png +data/labels/94_6.png +data/labels/95_6.png +data/labels/96_6.png +data/labels/97_6.png +data/labels/98_6.png +data/labels/99_6.png +data/labels/100_6.png +data/labels/101_6.png +data/labels/102_6.png +data/labels/103_6.png +data/labels/104_6.png +data/labels/105_6.png +data/labels/106_6.png +data/labels/107_6.png +data/labels/108_6.png +data/labels/109_6.png +data/labels/110_6.png +data/labels/111_6.png +data/labels/112_6.png +data/labels/113_6.png +data/labels/114_6.png +data/labels/115_6.png +data/labels/116_6.png +data/labels/117_6.png +data/labels/118_6.png +data/labels/119_6.png +data/labels/120_6.png +data/labels/121_6.png +data/labels/122_6.png +data/labels/123_6.png +data/labels/124_6.png +data/labels/125_6.png +data/labels/126_6.png +data/labels/32_7.png +data/labels/33_7.png +data/labels/34_7.png +data/labels/35_7.png +data/labels/36_7.png +data/labels/37_7.png +data/labels/38_7.png +data/labels/39_7.png +data/labels/40_7.png +data/labels/41_7.png +data/labels/42_7.png +data/labels/43_7.png +data/labels/44_7.png +data/labels/45_7.png +data/labels/46_7.png +data/labels/47_7.png +data/labels/48_7.png +data/labels/49_7.png +data/labels/50_7.png +data/labels/51_7.png +data/labels/52_7.png +data/labels/53_7.png +data/labels/54_7.png +data/labels/55_7.png +data/labels/56_7.png +data/labels/57_7.png +data/labels/58_7.png +data/labels/59_7.png +data/labels/60_7.png +data/labels/61_7.png +data/labels/62_7.png +data/labels/63_7.png +data/labels/64_7.png +data/labels/65_7.png +data/labels/66_7.png +data/labels/67_7.png +data/labels/68_7.png +data/labels/69_7.png +data/labels/70_7.png +data/labels/71_7.png +data/labels/72_7.png +data/labels/73_7.png +data/labels/74_7.png +data/labels/75_7.png +data/labels/76_7.png +data/labels/77_7.png +data/labels/78_7.png +data/labels/79_7.png +data/labels/80_7.png +data/labels/81_7.png +data/labels/82_7.png +data/labels/83_7.png +data/labels/84_7.png +data/labels/85_7.png +data/labels/86_7.png +data/labels/87_7.png +data/labels/88_7.png +data/labels/89_7.png +data/labels/90_7.png +data/labels/91_7.png +data/labels/92_7.png +data/labels/93_7.png +data/labels/94_7.png +data/labels/95_7.png +data/labels/96_7.png +data/labels/97_7.png +data/labels/98_7.png +data/labels/99_7.png +data/labels/100_7.png +data/labels/101_7.png +data/labels/102_7.png +data/labels/103_7.png +data/labels/104_7.png +data/labels/105_7.png +data/labels/106_7.png +data/labels/107_7.png +data/labels/108_7.png +data/labels/109_7.png +data/labels/110_7.png +data/labels/111_7.png +data/labels/112_7.png +data/labels/113_7.png +data/labels/114_7.png +data/labels/115_7.png +data/labels/116_7.png +data/labels/117_7.png +data/labels/118_7.png +data/labels/119_7.png +data/labels/120_7.png +data/labels/121_7.png +data/labels/122_7.png +data/labels/123_7.png +data/labels/124_7.png +data/labels/125_7.png +data/labels/126_7.png diff --git a/Robot_Development/catkin_ws/lane_demo/src/lane_demo.cpp b/Robot_Development/catkin_ws/lane_demo/src/lane_demo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb6da95e61c83a6ed7b50b50ff0bacd0bb2bcffc --- /dev/null +++ b/Robot_Development/catkin_ws/lane_demo/src/lane_demo.cpp @@ -0,0 +1,239 @@ +#include "ros/ros.h" +#include <chrono> +#include <ctime> +#include <vector> +#include "std_msgs/String.h" +#include "geometry_msgs/Twist.h" +#include "std_msgs/Int16.h" +#include "std_msgs/UInt64.h" +#include "std_msgs/Float64.h" +#include "Detection.h" +#include <math.h> +#include <cstddef> +#include <string.h> +#define ANGULAR_SPEED 0.25 +#define OBJECT_DIST_NEAR 40 + +enum STATE { FORWARD, TURN_RIGHT, TURN_LEFT, STOP}; + +class SenseAndAvoid +{ + public: + SenseAndAvoid(); + + private: + void leftEncoderCallback(const std_msgs::UInt64::ConstPtr& msg); + void rightEncoderCallback(const std_msgs::UInt64::ConstPtr& msg); + void sonarCallback(const std_msgs::Int16::ConstPtr& msg); + void sonar_1Callback(const std_msgs::Int16::ConstPtr& msg); + void sonar_3Callback(const std_msgs::Int16::ConstPtr& msg); + void Lanes(const std_msgs::String::ConstPtr& msg); + void Lane_Distance(const std_msgs::Float64::ConstPtr& msg); + void Object_Detection(const std_msgs::String::ConstPtr& msg); + ros::NodeHandle nh; + + ros::Publisher vel_pub; + + ros::Subscriber left_encoder_sub; + ros::Subscriber right_encoder_sub; + ros::Subscriber sonar_sub; + ros::Subscriber sonar_1_sub; + ros::Subscriber sonar_3_sub; + ros::Subscriber lanes_sub; + ros::Subscriber lane_distance_sub; + ros::Subscriber object_sub; + + geometry_msgs::Twist vel_msg; + + int left_count, right_count, left_sonar, right_sonar, object_min, cur_count; + float lane_distance, Kp, Kv, Kd, integral_error, cur_error, derivative_error, prev_error; + + // TODO : Keep a vector of current detections ( last ~1 second, no duplicates ) + // For right now, just use thanos as our single, most recent detection + // vector<Detection> current_detections; + Detection thanos; + time_t last_detection_time; + time_t now = time(NULL); + double elapsed = difftime(now, last_detection_time); + + STATE state; + float linear_speed = 0.5; +}; +SenseAndAvoid::SenseAndAvoid() +{ + left_encoder_sub = nh.subscribe<std_msgs::UInt64>("/arduino/encoder_left_value", 10, &SenseAndAvoid::leftEncoderCallback, this); + right_encoder_sub = nh.subscribe<std_msgs::UInt64>("/arduino/encoder_right_value", 10, &SenseAndAvoid::rightEncoderCallback, this); + sonar_sub = nh.subscribe<std_msgs::Int16>("/arduino/sonar_2", 10, &SenseAndAvoid::sonarCallback, this); + sonar_1_sub = nh.subscribe<std_msgs::Int16>("/arduino/sonar_1", 10, &SenseAndAvoid::sonar_1Callback, this); + sonar_3_sub = nh.subscribe<std_msgs::Int16>("/arduino/sonar_3", 10, &SenseAndAvoid::sonar_3Callback, this); + vel_pub = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 10); + lanes_sub = nh.subscribe<std_msgs::String>("/lanes", 10, &SenseAndAvoid::Lanes, this); + lane_distance_sub = nh.subscribe<std_msgs::Float64>("/lane_distance", 10, &SenseAndAvoid::Lane_Distance, this); + object_sub = nh.subscribe<std_msgs::String>("/object_detection", 10, &SenseAndAvoid::Object_Detection, this); + state = FORWARD; + left_count = 0; + right_count = 0; + cur_error = 0; + Kp = 0.005; + last_detection_time = time(NULL); + Kv = 0; + Kd = 0; +} + +void SenseAndAvoid::Lanes(const std_msgs::String::ConstPtr& msg) +{ + if(msg->data.compare("No Lanes") == 0) + { + state = STOP; + } + else if(msg->data.compare("Left lane does not exist") == 0) + { + state = TURN_LEFT; + } + else if(msg->data.compare("Right lane does not exist") == 0) + { + state = TURN_RIGHT; + } + else + { + state = FORWARD; + } +} + +void SenseAndAvoid::Lane_Distance(const std_msgs::Float64::ConstPtr& msg) +{ + lane_distance = msg->data; +} +void SenseAndAvoid::Object_Detection(const std_msgs::String::ConstPtr& msg) +{ + last_detection_time = time(NULL); + + + std::string object = msg->data; + //printf("c_str objcet %s\n",object.c_str()); + thanos = Detection(object.c_str()); + //ROS_INFO("Detected Object : %s",thanos.to_string().c_str()); + //ROS_INFO("ELAPSED - SECONDS %lf", elapsed); +} +void SenseAndAvoid::leftEncoderCallback(const std_msgs::UInt64::ConstPtr& msg) +{ + left_count += msg->data; +} + +void SenseAndAvoid::rightEncoderCallback(const std_msgs::UInt64::ConstPtr& msg) +{ + right_count += msg->data; +} + +void SenseAndAvoid::sonar_1Callback(const std_msgs::Int16::ConstPtr& msg) +{ + left_sonar = msg->data; +} + +void SenseAndAvoid::sonar_3Callback(const std_msgs::Int16::ConstPtr& msg) +{ + right_sonar = msg->data; +} + +void SenseAndAvoid::sonarCallback(const std_msgs::Int16::ConstPtr& msg) +{ + + // If time elapsed since last detection > 1 second, make last detection null + time_t now = time(NULL); + double elapsed_seconds = difftime(now, last_detection_time); + // How long since last detection + //ROS_INFO("%lf", elapsed); + //ROS_INFO_STREAM(thanos._prob); + if(elapsed_seconds > 2) { + // no detections + // Object is out of frame + ROS_INFO("No object in frame."); + thanos._name = ""; + thanos._prob = -1; + thanos._cx = -1; + thanos._cy = -1; + thanos._w = -1; + thanos._h = -1; + } +/* +Detection Variables + string _name; + float _prob; + int _cx; + int _cy; + int _w; + int _h; +*/ + if((msg->data < OBJECT_DIST_NEAR && msg->data > 0) || (left_sonar < OBJECT_DIST_NEAR && left_sonar > 0) || (right_sonar < OBJECT_DIST_NEAR && right_sonar > 0)) + { + ROS_INFO("OBJECT IN THE WAY, STOP"); + vel_msg.linear.x = 0; + vel_msg.angular.z = 0; + } + else if(thanos._name == "stop" && thanos._prob > 80 && thanos._h > 200) + { + ROS_INFO("STOP SIGN FOUND"); + vel_msg.linear.x = 0; + vel_msg.angular.z = 0; + } + else if(thanos._name == "person" && thanos._prob > 60) + { + ROS_INFO("PERSON FOUND"); + vel_msg.linear.x = 0; + vel_msg.angular.z = 0; + } + else if(thanos._name == "speedLimit25" && thanos._prob > 60) + { + ROS_INFO("SPEED LIMIT 25"); + linear_speed = 0.3; + vel_msg.linear.x = linear_speed; + vel_msg.angular.z = 0; + } + else if(thanos._name == "speedLimit35" && thanos._prob > 60) + { + ROS_INFO("SPEED LIMIT 35"); + linear_speed = 0.4; + vel_msg.linear.x = linear_speed; + vel_msg.angular.z = 0; + } + else if(state == STOP) + { + ROS_INFO("NO LANES, STOP"); + vel_msg.linear.x = 0; + vel_msg.angular.z = 0; + } +/* + else if(state == TURN_LEFT) + { + ROS_INFO("TURNING LEFT"); + vel_msg.linear.x = linear_speed; + vel_msg.angular.z = -ANGULAR_SPEED; + } + else if(state == TURN_RIGHT) + { + ROS_INFO("TURNING_RIGHT"); + vel_msg.linear.x = linear_speed; + vel_msg.angular.z = ANGULAR_SPEED; + } +*/ + else + { + cur_error = lane_distance; + ROS_INFO_STREAM(cur_error); + ROS_INFO("PID Control"); + integral_error += cur_error; + derivative_error = cur_error - prev_error; + vel_msg.linear.x = linear_speed; + vel_msg.angular.z = (Kp * cur_error + Kv * integral_error + Kd * derivative_error); + prev_error = cur_error; + } + vel_pub.publish(vel_msg); +} +int main(int argc, char **argv) +{ + ros::init(argc, argv, "lane_demo"); + + SenseAndAvoid lane_demo; + + ros::spin(); +} diff --git a/Robot_Development/catkin_ws/lane_detection/CMakeLists.txt b/Robot_Development/catkin_ws/lane_detection/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5651bc35cdf3de2b1d7a589f6f1a77e87f81391c --- /dev/null +++ b/Robot_Development/catkin_ws/lane_detection/CMakeLists.txt @@ -0,0 +1,199 @@ +cmake_minimum_required(VERSION 2.8.3) +project(lane_detection) + +## Compile as C++11, supported in ROS Kinetic and newer +# add_compile_options(-std=c++11) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED COMPONENTS + roscpp + rospy + std_msgs +) + +## System dependencies are found with CMake's conventions +# find_package(Boost REQUIRED COMPONENTS system) + + +## Uncomment this if the package has a setup.py. This macro ensures +## modules and global scripts declared therein get installed +## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html +# catkin_python_setup() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +## To declare and build messages, services or actions from within this +## package, follow these steps: +## * Let MSG_DEP_SET be the set of packages whose message types you use in +## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). +## * In the file package.xml: +## * add a build_depend tag for "message_generation" +## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET +## * If MSG_DEP_SET isn't empty the following dependency has been pulled in +## but can be declared for certainty nonetheless: +## * add a exec_depend tag for "message_runtime" +## * In this file (CMakeLists.txt): +## * add "message_generation" and every package in MSG_DEP_SET to +## find_package(catkin REQUIRED COMPONENTS ...) +## * add "message_runtime" and every package in MSG_DEP_SET to +## catkin_package(CATKIN_DEPENDS ...) +## * uncomment the add_*_files sections below as needed +## and list every .msg/.srv/.action file to be processed +## * uncomment the generate_messages entry below +## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) + +## Generate messages in the 'msg' folder +# add_message_files( +# FILES +# Message1.msg +# Message2.msg +# ) + +## Generate services in the 'srv' folder +# add_service_files( +# FILES +# Service1.srv +# Service2.srv +# ) + +## Generate actions in the 'action' folder +# add_action_files( +# FILES +# Action1.action +# Action2.action +# ) + +## Generate added messages and services with any dependencies listed here +# generate_messages( +# DEPENDENCIES +# std_msgs +# ) + +################################################ +## Declare ROS dynamic reconfigure parameters ## +################################################ + +## To declare and build dynamic reconfigure parameters within this +## package, follow these steps: +## * In the file package.xml: +## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" +## * In this file (CMakeLists.txt): +## * add "dynamic_reconfigure" to +## find_package(catkin REQUIRED COMPONENTS ...) +## * uncomment the "generate_dynamic_reconfigure_options" section below +## and list every .cfg file to be processed + +## Generate dynamic reconfigure parameters in the 'cfg' folder +# generate_dynamic_reconfigure_options( +# cfg/DynReconf1.cfg +# cfg/DynReconf2.cfg +# ) + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if your package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES lane_detection +# CATKIN_DEPENDS roscpp rospy std_msgs +# DEPENDS system_lib +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +include_directories( +# include + ${catkin_INCLUDE_DIRS} +) + +## Declare a C++ library +# add_library(${PROJECT_NAME} +# src/${PROJECT_NAME}/lane_detection.cpp +# ) + +## Add cmake target dependencies of the library +## as an example, code may need to be generated before libraries +## either from message generation or dynamic reconfigure +# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Declare a C++ executable +## With catkin_make all packages are built within a single CMake context +## The recommended prefix ensures that target names across packages don't collide +# add_executable(${PROJECT_NAME}_node src/lane_detection_node.cpp) + +## Rename C++ executable without prefix +## The above recommended prefix causes long target names, the following renames the +## target back to the shorter version for ease of user use +## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" +# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") + +## Add cmake target dependencies of the executable +## same as for the library above +# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Specify libraries to link a library or executable target against +# target_link_libraries(${PROJECT_NAME}_node +# ${catkin_LIBRARIES} +# ) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_lane_detection.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) \ No newline at end of file diff --git a/Robot_Development/catkin_ws/lane_detection/launch/lane_detection.launch b/Robot_Development/catkin_ws/lane_detection/launch/lane_detection.launch new file mode 100644 index 0000000000000000000000000000000000000000..dd714004f994c772053a5c38662a25eeac2e8659 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_detection/launch/lane_detection.launch @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<launch> + <node name="lane_detection" pkg="lane_detection" type="detect.py" output="screen"/> +</launch> diff --git a/Robot_Development/catkin_ws/lane_detection/package.xml b/Robot_Development/catkin_ws/lane_detection/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5ba37e69f3e25cc845fd1946b6f49455ca58ff7 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_detection/package.xml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<package format="2"> + <name>lane_detection</name> + <version>1.0.0</version> + <description>The lane_detection package</description> + + <!-- One maintainer tag required, multiple allowed, one person per tag --> + <!-- Example: --> + <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> + <maintainer email="kpp55@drexel.edu">Kevin Phan</maintainer> + + + <!-- One license tag required, multiple allowed, one license per tag --> + <!-- Commonly used license strings: --> + <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> + <license>TODO</license> + + + <!-- Url tags are optional, but multiple are allowed, one per tag --> + <!-- Optional attribute type can be: website, bugtracker, or repository --> + <!-- Example: --> + <!-- <url type="website">http://wiki.ros.org/lane_detection</url> --> + + + <!-- Author tags are optional, multiple are allowed, one per tag --> + <!-- Authors do not have to be maintainers, but could be --> + <!-- Example: --> + <!-- <author email="jane.doe@example.com">Jane Doe</author> --> + + + <!-- The *depend tags are used to specify dependencies --> + <!-- Dependencies can be catkin packages or system dependencies --> + <!-- Examples: --> + <!-- Use depend as a shortcut for packages that are both build and exec dependencies --> + <!-- <depend>roscpp</depend> --> + <!-- Note that this is equivalent to the following: --> + <!-- <build_depend>roscpp</build_depend> --> + <!-- <exec_depend>roscpp</exec_depend> --> + <!-- Use build_depend for packages you need at compile time: --> + <!-- <build_depend>message_generation</build_depend> --> + <!-- Use build_export_depend for packages you need in order to build against this package: --> + <!-- <build_export_depend>message_generation</build_export_depend> --> + <!-- Use buildtool_depend for build tool packages: --> + <!-- <buildtool_depend>catkin</buildtool_depend> --> + <!-- Use exec_depend for packages you need at runtime: --> + <!-- <exec_depend>message_runtime</exec_depend> --> + <!-- Use test_depend for packages you need only for testing: --> + <!-- <test_depend>gtest</test_depend> --> + <!-- Use doc_depend for packages you need only for building documentation: --> + <!-- <doc_depend>doxygen</doc_depend> --> + <buildtool_depend>catkin</buildtool_depend> + <build_depend>roscpp</build_depend> + <build_depend>rospy</build_depend> + <build_depend>std_msgs</build_depend> + <build_export_depend>roscpp</build_export_depend> + <build_export_depend>rospy</build_export_depend> + <build_export_depend>std_msgs</build_export_depend> + <exec_depend>roscpp</exec_depend> + <exec_depend>rospy</exec_depend> + <exec_depend>std_msgs</exec_depend> + + + <!-- The export tag contains other, unspecified, tags --> + <export> + <!-- Other tools can request additional information be placed here --> + + </export> +</package> diff --git a/Robot_Development/catkin_ws/lane_detection/src/detect.py b/Robot_Development/catkin_ws/lane_detection/src/detect.py new file mode 100755 index 0000000000000000000000000000000000000000..209413382a30918e2eb8a953781f0bb037f39e3d --- /dev/null +++ b/Robot_Development/catkin_ws/lane_detection/src/detect.py @@ -0,0 +1,249 @@ +#!/usr/bin/python + +import numpy as np +import rospy +import matplotlib.pyplot as plt +import cv2 +from imutils.video import WebcamVideoStream +from imutils.video import FPS +from std_msgs.msg import String +from std_msgs.msg import Float64 + +pub = rospy.Publisher('lanes', String, queue_size=10) +pub1 = rospy.Publisher('lane_distance', Float64, queue_size=10) +rospy.init_node('lane_detection') +rate = rospy.Rate(1000) # 1000hz +width = 325 + + +# Converts picture to grayscale and applies filter to picture +# params +# pic : a numpy array of pixel values to represent a picture + +def thresh(pic): + grayscaled = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY) #grayscale + retval, th = cv2.threshold(grayscaled, 60, 255, cv2.THRESH_BINARY) #filter out unncessary edges + img_filter = cv2.GaussianBlur(th, (5, 5), 0) #Make the image more cohesive + img_edge = cv2.Canny(img_filter, 50, 150) #find the edges + return img_edge + +# Define the region of in which the lanes will be in the cameras view +# params +# pic: original image to apply the pre-set region of interest too +def ROI_real(pic): + height = pic.shape[0] + width = pic.shape[1] + triangle = np.array([[(0, height), (0, 250), (width, 250), (width, height)]], dtype=np.int32) #shape of a trapazoid + mask = np.zeros_like(pic) + cv2.fillPoly(mask, triangle, 255) + roi = cv2.bitwise_and(pic, mask) + return roi + +# Get all possible HoughLines and return them +# params +# edge_pic: the image with the edge detection performed +def getLines(edge_pic): + return cv2.HoughLinesP(edge_pic, 1, np.pi / 180, 50, maxLineGap=80, minLineLength=10) + + +# Apply the passed in lines the the original picture +# params +# original_pic: +# lines: Array of lines in the form (x1, x2, y1, y2) +def applyLines(original_pic, lines): + # If there is no lines return the original photo + if lines is None: + return original_pic + + # Loop through all possible lines + for line in lines: + # parse the array to individual variables + x1, y1, x2, y2 = line.reshape(4) + # print(line) + + # Draw the lines on the original picture + cv2.line(original_pic, (x1, y1), (x2, y2), (255, 0, 0), 3) + + # return the original picture with the lines drawn on + return original_pic + + +def find_middle(leftPoints, rightPoints): + middle_lines = [[], []] + + if leftPoints[1] == []: + print( + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Caught the empty list~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + return 0 + + elif rightPoints[1] == []: + print( + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Caught the empty list~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + return 0 + + else: + for x in range(150): + midPoint = (rightPoints[0][149 - x] + leftPoints[0][x]) / 2 + + middle_lines[1].append(leftPoints[1][x]) + middle_lines[0].append(midPoint) + + return middle_lines + + +# Find the two average lines given the set of lines +# params +# pic: the original image +# lines: An array of lines in the form (x1, x2, y1, y2) +def find_poly_lane(pic, lines): + # Collections for the negative and positive sloped lines + left_lines_points = [[], []] # Negative slope + right_lines_points = [[], []] # Positive slope + # print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Start~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + for line in lines: + x1, y1, x2, y2 = line[0] + parameters = np.polyfit((x1, x2), (y1, y2), 1) + # print("Slope, intercept") + # print(parameters) + slope = parameters[0] + intercept = parameters[1] + + if (slope < .75 and slope > -.75): + # print("Line ignored"); + x = 1 + + elif (slope < 0): + # print("left insert") + left_lines_points[0].append(x1) + left_lines_points[0].append(x2) + left_lines_points[1].append(y1) + left_lines_points[1].append(y2) + + else: + # print("right insert") + right_lines_points[0].append(x1) + right_lines_points[0].append(x2) + right_lines_points[1].append(y1) + right_lines_points[1].append(y2) + + # print("POINTS") + # print(right_lines_points[0]) + # print(left_lines_points[0]) + + if right_lines_points[0]: + z = np.polyfit(right_lines_points[0], right_lines_points[1], 1) + f = np.poly1d(z) + # print(f) + + right_x_new = np.linspace(np.amin(right_lines_points[0]), np.amax(right_lines_points[0]), 150) + right_y_new = f(right_x_new) + + else: + right_x_new = [] + right_y_new = [] + + if left_lines_points[0]: + z = np.polyfit(left_lines_points[0], left_lines_points[1], 1) + f = np.poly1d(z) + # print(f) + + left_x_new = np.linspace(np.amin(left_lines_points[0]), np.amax(left_lines_points[0]), 150) + left_y_new = f(left_x_new) + + else: + left_x_new = [] + left_y_new = [] + + # print("New left") + # print(left_x_new) + # print(left_y_new) + + return [right_x_new, right_y_new], [left_x_new, left_y_new] + + +def make_coordinates(image, line_parameters): + # print(line_parameters) + slope, intercept = line_parameters + y1 = image.shape[0] + y2 = int(y1 * (1 / 2)) + x1 = int((y1 - intercept) / slope) + x2 = int((y2 - intercept) / slope) + return np.array([x1, y1, x2, y2]) + + +def detectDeparture(left, car, right): + a = 9999999 + b = 999999 + left_lane = 0 + right_lane = 0 + missing_lane = "" + try: + parametersLeft = np.polyfit((left[0][0], left[0][-1]), (left[1][0], left[1][-1]), 1) + leftEq = np.poly1d(parametersLeft) + leftPosition = (310 - parametersLeft[1]) / parametersLeft[0] + a = car - leftPosition + left_lane = 1 + except IndexError: + missing_lane = "Left lane does not exist" + try: + parametersRight = np.polyfit((right[0][0], right[0][-1]), (right[1][0], right[1][-1]), 1) + rightEq = np.poly1d(parametersRight) + rightPosition = (310 - parametersRight[1]) / parametersRight[0] + b = rightPosition - car + right_lane = 1 + except IndexError: + missing_lane = "Right lane does not exist" + if (left_lane == 0 and right_lane == 0): + missing_lane = "No Lanes" + return missing_lane + + +def detectDepartureNew(midPoints): + midx = 325 + midy = 350 + for x in range(150): + if (myround(midPoints[1][x]) == midy): + # print(midPoints[0][x] - midx) + return midPoints[0][x] - midx + + +def myround(x): + return int(5 * round(float(x) / 5)) + + +def lane_status(lane_distance): + rospy.loginfo(lane_distance) + pub1.publish(lane_distance) + rate.sleep() + + +def lanes_detected(lanes): + rospy.loginfo(lanes) + pub.publish(lanes) + rate.sleep() + +video = WebcamVideoStream(src=1).start() + +while not rospy.is_shutdown(): + frame = video.read() + filterImg = thresh(frame) + cropped = ROI_real(filterImg) + lines = getLines(cropped) + if lines is None: + x=0 + else: + Rpoints, Lpoints = find_poly_lane(filterImg, lines) + Mpoints = find_middle(Lpoints,Rpoints) + lanes = detectDeparture(Lpoints, 350, Rpoints) + lanes_detected(lanes) + if (Mpoints != 0): + lane_distance = detectDepartureNew(Mpoints) + lane_status(lane_distance) + else: + print("No midpoint calculated") + if(lanes == "Left lane does not exist"): + lane_distance = -100 + lane_status(lane_distance) + elif(lanes == "Right lane does not exist"): + lane_distance = 100 + lane_status(lane_distance) \ No newline at end of file diff --git a/Robot_Development/catkin_ws/lane_detection/src/detect_old.py b/Robot_Development/catkin_ws/lane_detection/src/detect_old.py new file mode 100755 index 0000000000000000000000000000000000000000..032a84c800d13ce16c4e82cab8681da75261f8c4 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_detection/src/detect_old.py @@ -0,0 +1,282 @@ + #!/usr/bin/python2 + +import numpy as np +#import rospy +import matplotlib.pyplot as plt +import cv2 + +from imutils.video import WebcamVideoStream +from imutils.video import FPS +#from std_msgs.msg import String +#from std_msgs.msg import Float64 + +#pub = rospy.Publisher('lane_status', String, queue_size=10) +#rospy.init_node('lane_status') +#rate = rospy.Rate(100) # 100hz +width = 325 + +# Converts picture to grayscale and applies filter to picture +# param`s +# pic : a numpy array of pixel values to represent a picture +def formatImg(pic): + # Convert picture to gray scale + gray = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY) + + # Apply filter to image + img_filter = cv2.GaussianBlur(gray, (5, 5), 0) + + return img_filter + + +# pre-processes and performs edge detection on an image +# params +# pic: a numpy array of pixel values for an image in gray scale +def detect_edge(pic): + # Perform canny edge detection + img_edge = cv2.Canny(pic, 50, 150) + + # return new edge image + return img_edge + + +# Define the region of in which the lanes will be in the cameras view +# params +# pic: original image to apply the pre-set region of interest too +def ROI(pic): + height = pic.shape[0] + triangle = np.array([[(0, height), (650, height), (325, 100)]]) + mask = np.zeros_like(pic) + cv2.fillPoly(mask, triangle, 255) + roi = cv2.bitwise_and(pic, mask) + return roi + + +# Define the region of in which the lanes will be in the cameras view +# params +# pic: original image to apply the pre-set region of interest too +def ROI_real(pic): + height = pic.shape[0] + triangle = np.array([[(0, height), (145, 300), (475, 300), (600, height)]]) + mask = np.zeros_like(pic) + cv2.fillPoly(mask, triangle, 255) + roi = cv2.bitwise_and(pic, mask) + return roi + + +# Get all possible HoughLines and return them +# params +# edge_pic: the image with the edge detection performed +def getLines(edge_pic): + return cv2.HoughLinesP(edge_pic, 1, np.pi / 180, 100, maxLineGap=80, minLineLength=20) + + +# Apply the passed in lines the the original picture +# params +# original_pic: +# lines: Array of lines in the form (x1, x2, y1, y2) +def applyLines(original_pic, lines): + # If there is no lines return the original photo + if lines is None: + return original_pic + +# print("Frame lines") +# print(lines) + +# lines = lines[0] + # Loop through all possible lines + for line in lines: + + # parse the array to individual variables + x1, y1, x2, y2 = line.reshape(4) + + # Draw the lines on the original picture + cv2.line(original_pic, (x1, y1), (x2, y2), (255, 0, 0), 3) + + # return the original picture with the lines drawn on + return original_pic + + +# Find the two average lines given the set of lines +# params +# pic: the original image +# lines: An array of lines in the form (x1, x2, y1, y2) +def find_poly_lane(pic, lines): + # Collections for the negative and positive sloped lines + left_lines_points = [[], []] # Negative slope + right_lines_points = [[], []] # Positive slope + +# print("poly") +# print(lines) + + # lines = lines[0] + for line in lines: + print("Averaged line") + print(line) + x1, y1, x2, y2 = line.reshape(4) + parameters = np.polyfit((x1, x2), (y1, y2), 1) + # print("Slope, intercept") + # print(parameters) + slope = parameters[0] + intercept = parameters[1] + + if (slope < 1 and slope > -1): + print("Line ignored"); + x = 1 + + elif (slope < 0): + print("left insert") + left_lines_points[0].append(x1) + left_lines_points[0].append(x2) + left_lines_points[1].append(y1) + left_lines_points[1].append(y2) + + else: + print("right insert") + right_lines_points[0].append(x1) + right_lines_points[0].append(x2) + right_lines_points[1].append(y1) + right_lines_points[1].append(y2) + + if right_lines_points[0]: + z = np.polyfit(right_lines_points[0], right_lines_points[1], 1) + f = np.poly1d(z) + + right_x_new = np.linspace(np.amin(right_lines_points[0]), np.amax(right_lines_points[0]), 150) + right_y_new = f(right_x_new) + + else: + right_x_new = [] + right_y_new = [] + + if left_lines_points[0]: + z = np.polyfit(left_lines_points[0], left_lines_points[1], 1) + f = np.poly1d(z) + + left_x_new = np.linspace(np.amin(left_lines_points[0]), np.amax(left_lines_points[0]), 150) + left_y_new = f(left_x_new) + + else: + left_x_new = [] + left_y_new = [] + + return [right_x_new, right_y_new], [left_x_new, left_y_new] + +def make_coordinates(image, line_parameters): + slope, intercept = line_parameters + y1 = image.shape[0] + y2 = int(y1 * (1 / 2)) + x1 = int((y1 - intercept) / slope) + x2 = int((y2 - intercept) / slope) + return np.array([x1, y1, x2, y2]) + + +def detectDeparture(left, car, right): + a = 9999999 + b = 999999 + + try: + parametersLeft = np.polyfit((left[0][0], left[0][-1]), (left[1][0], left[1][-1]), 1) + leftEq = np.poly1d(parametersLeft) + leftPosition = (310 - parametersLeft[1]) / parametersLeft[0] + a = car - leftPosition + left_lane = 1 + + except IndexError: + print("Left lane does not exist") + left_lane = 0 + try: + parametersRight = np.polyfit((right[0][0], right[0][-1]), (right[1][0], right[1][-1]), 1) + rightEq = np.poly1d(parametersRight) + rightPosition = (310 - parametersRight[1]) / parametersRight[0] + b = rightPosition - car + right_lane = 1 + + except IndexError: + print("Right lane does not exist") + right_lane = 0 + area = width / 4 + + #print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + if left_lane == 0 and right_lane == 0: + direction = "No lane detected" + print("No lanes detected") + elif (area > a): + direction = "Drift Left" + print("Drift left") + elif (area > b): + direction = "Drift Right" + print("Drift right") + else: + direction = "On Course" + print("On course") + #print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + return direction + +def lane_status(direction): + rospy.loginfo(direction) + pub.publish(direction) + rate.sleep() + + +# For debugging purposes +# Displays lanes on video feed +plt.ion() + +# Threaded frame capture object +video = WebcamVideoStream(src=1).start() + +# Run until robot is shut down +#while not rospy.is_shutdown(): + +while True: + + # Get video frame + frame = video.read() + + # Get the edge detection + frame_edge = detect_edge(frame) + + new_img = formatImg(frame) + + wEdges = detect_edge(new_img) + + cropped = ROI_real(wEdges) + + lines = getLines(cropped) + + if lines is None: + x = 0 + + else: + Rpoints, Lpoints = find_poly_lane(new_img, lines) + + # plt.cla() +# plt.clf() + + # plt.scatter(Rpoints[0], Rpoints[1]) + # plt.scatter(Lpoints[0], Lpoints[1]) + + # plt.scatter(310, 400) + + # plt.imshow(frame, zorder=0) + + direction = detectDeparture(Lpoints, 400, Rpoints) +# lane_status(direction) +# plt.pause(.001) + + lane = applyLines(frame, lines) + + # Display edge detection + #cv2.imshow("edges", wEdges) + + # Display cropped edge detection + #cv2.imshow("cropped", cropped) + + # Show original image with all lines detected + cv2.imshow("frame", lane) + + key = cv2.waitKey(20) + if key == 27: + break +video.release() +v2.destroyAllWindows() diff --git a/Robot_Development/catkin_ws/lane_detection/src/detect_plot.py b/Robot_Development/catkin_ws/lane_detection/src/detect_plot.py new file mode 100755 index 0000000000000000000000000000000000000000..2ff87745bf14a96b9329a980cf0050816887e13c --- /dev/null +++ b/Robot_Development/catkin_ws/lane_detection/src/detect_plot.py @@ -0,0 +1,254 @@ +#!/usr/bin/python + +import numpy as np +import rospy +import matplotlib.pyplot as plt +import cv2 +from imutils.video import WebcamVideoStream +from imutils.video import FPS +from std_msgs.msg import String +from std_msgs.msg import Float64 + +pub = rospy.Publisher('lanes', String, queue_size=10) +pub1 = rospy.Publisher('lane_distance', Float64, queue_size=10) +rospy.init_node('lane_detection') +rate = rospy.Rate(1000) # 1000hz +width = 325 + + + +def thresh(pic): + grayscaled = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY) #grayscale + retval, th = cv2.threshold(grayscaled, 60, 255, cv2.THRESH_BINARY) #filter out unncessary edges + cv2.imshow("th",th) + img_filter = cv2.GaussianBlur(th, (5, 5), 0) #Make the image more cohesive + img_edge = cv2.Canny(img_filter, 50, 150) #find the edges + return img_edge + +# Define the region of in which the lanes will be in the cameras view +# params +# pic: original image to apply the pre-set region of interest too +def ROI_real(pic): + height = pic.shape[0] + width = pic.shape[1] + triangle = np.array([[(0, height), (0, 250), (width, 250), (width, height)]], dtype=np.int32) #shape of a trapazoid + mask = np.zeros_like(pic) + cv2.fillPoly(mask, triangle, 255) + roi = cv2.bitwise_and(pic, mask) + return roi + + +# Get all possible HoughLines and return them +# params +# edge_pic: the image with the edge detection performed +def getLines(edge_pic): + return cv2.HoughLinesP(edge_pic, 1, np.pi / 180, 50, maxLineGap=80, minLineLength=10) + + +# Apply the passed in lines the the original picture +# params +# original_pic: +# lines: Array of lines in the form (x1, x2, y1, y2) +def applyLines(original_pic, lines): + # If there is no lines return the original photo + if lines is None: + return original_pic + + # Loop through all possible lines + for line in lines: + # parse the array to individual variables + x1, y1, x2, y2 = line.reshape(4) + # print(line) + + # Draw the lines on the original picture + cv2.line(original_pic, (x1, y1), (x2, y2), (255, 0, 0), 3) + + # return the original picture with the lines drawn on + return original_pic + + +def find_middle(leftPoints, rightPoints): + middle_lines = [[], []] + + if leftPoints[1] == []: + print( + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Caught the empty list~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + return 0 + + elif rightPoints[1] == []: + print( + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Caught the empty list~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + return 0 + + else: + for x in range(150): + midPoint = (rightPoints[0][149 - x] + leftPoints[0][x]) / 2 + + middle_lines[1].append(leftPoints[1][x]) + middle_lines[0].append(midPoint) + + return middle_lines + + +# Find the two average lines given the set of lines +# params +# pic: the original image +# lines: An array of lines in the form (x1, x2, y1, y2) +def find_poly_lane(pic, lines): + # Collections for the negative and positive sloped lines + left_lines_points = [[], []] # Negative slope + right_lines_points = [[], []] # Positive slope + # print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Start~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + for line in lines: + x1, y1, x2, y2 = line[0] + parameters = np.polyfit((x1, x2), (y1, y2), 1) + # print("Slope, intercept") + # print(parameters) + slope = parameters[0] + intercept = parameters[1] + + if (slope < .75 and slope > -.75): + # print("Line ignored"); + x = 1 + + elif (slope < 0): + # print("left insert") + left_lines_points[0].append(x1) + left_lines_points[0].append(x2) + left_lines_points[1].append(y1) + left_lines_points[1].append(y2) + + else: + # print("right insert") + right_lines_points[0].append(x1) + right_lines_points[0].append(x2) + right_lines_points[1].append(y1) + right_lines_points[1].append(y2) + + # print("POINTS") + # print(right_lines_points[0]) + # print(left_lines_points[0]) + + if right_lines_points[0]: + z = np.polyfit(right_lines_points[0], right_lines_points[1], 1) + f = np.poly1d(z) + # print(f) + + right_x_new = np.linspace(np.amin(right_lines_points[0]), np.amax(right_lines_points[0]), 150) + right_y_new = f(right_x_new) + + else: + right_x_new = [] + right_y_new = [] + + if left_lines_points[0]: + z = np.polyfit(left_lines_points[0], left_lines_points[1], 1) + f = np.poly1d(z) + # print(f) + + left_x_new = np.linspace(np.amin(left_lines_points[0]), np.amax(left_lines_points[0]), 150) + left_y_new = f(left_x_new) + + else: + left_x_new = [] + left_y_new = [] + + # print("New left") + # print(left_x_new) + # print(left_y_new) + + return [right_x_new, right_y_new], [left_x_new, left_y_new] + + +def make_coordinates(image, line_parameters): + # print(line_parameters) + slope, intercept = line_parameters + y1 = image.shape[0] + y2 = int(y1 * (1 / 2)) + x1 = int((y1 - intercept) / slope) + x2 = int((y2 - intercept) / slope) + return np.array([x1, y1, x2, y2]) + + +def detectDeparture(left, car, right): + a = 9999999 + b = 999999 + left_lane = 0 + right_lane = 0 + missing_lane = "" + try: + parametersLeft = np.polyfit((left[0][0], left[0][-1]), (left[1][0], left[1][-1]), 1) + leftEq = np.poly1d(parametersLeft) + leftPosition = (310 - parametersLeft[1]) / parametersLeft[0] + a = car - leftPosition + left_lane = 1 + except IndexError: + missing_lane = "Left lane does not exist" + try: + parametersRight = np.polyfit((right[0][0], right[0][-1]), (right[1][0], right[1][-1]), 1) + rightEq = np.poly1d(parametersRight) + rightPosition = (310 - parametersRight[1]) / parametersRight[0] + b = rightPosition - car + right_lane = 1 + except IndexError: + missing_lane = "Right lane does not exist" + if (left_lane == 0 and right_lane == 0): + missing_lane = "No Lanes" + return missing_lane + + +def detectDepartureNew(midPoints): + midx = 325 + midy = 350 + for x in range(150): + if (myround(midPoints[1][x]) == midy): + # print(midPoints[0][x] - midx) + return midPoints[0][x] - midx + + +def myround(x): + return int(5 * round(float(x) / 5)) + +def lane_status(lane_distance): + rospy.loginfo(lane_distance) + pub1.publish(lane_distance) + rate.sleep() + +def lanes_detected(lanes): + rospy.loginfo(lanes) + pub.publish(lanes) + rate.sleep() + +video = WebcamVideoStream(src=1).start() +plt.ion() + +while not rospy.is_shutdown(): + frame = video.read() + filterImg = thresh(frame) + cropped = ROI_real(filterImg) + lines = getLines(cropped) + if lines is None: + x = 0 + else: + plt.cla() + plt.clf() + Rpoints, Lpoints = find_poly_lane(filterImg, lines) + Mpoints = find_middle(Lpoints,Rpoints) + plt.scatter(Rpoints[0], Rpoints[1]) + plt.scatter(Lpoints[0], Lpoints[1]) + lanes = detectDeparture(Lpoints, 400, Rpoints) + lanes_detected(lanes) + if (Mpoints != 0): + plt.scatter(Mpoints[0],Mpoints[1]) + lane_distance = detectDepartureNew(Mpoints) + lane_status(lane_distance) + else: + print("No midpoint calculated") + plt.scatter(325, 350) + plt.imshow(frame, zorder=0) + plt.pause(.001) + cv2.imshow("thresh",filterImg) + cv2.imshow("cropped",cropped) + key = cv2.waitKey(1) + if key == 27: + break \ No newline at end of file diff --git a/Robot_Development/catkin_ws/lane_detection/src/roi.py b/Robot_Development/catkin_ws/lane_detection/src/roi.py new file mode 100644 index 0000000000000000000000000000000000000000..ea7102918a75e58c4b587b10446877d6a6d07073 --- /dev/null +++ b/Robot_Development/catkin_ws/lane_detection/src/roi.py @@ -0,0 +1,19 @@ +import matplotlib.pyplot as plt +import cv2 + +video = cv2.VideoCapture(1) + +plt.ion + +while True: + ret, frame = video.read() + + key = cv2.waitKey(25) + if key == 27: + break + + plt.imshow(frame, zorder=0) + plt.pause(.001) + +video.release() +cv2.destroyAllWindows() diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/.tar b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/.tar new file mode 100644 index 0000000000000000000000000000000000000000..4753507a95c805d332ee0570d12947edb5c7bdc8 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/.tar @@ -0,0 +1,2 @@ +{!!python/unicode 'url': 'https://github.com/ros-gbp/image_common-release/archive/release/kinetic/camera_info_manager/1.11.10-0.tar.gz', + !!python/unicode 'version': image_common-release-release-kinetic-camera_info_manager-1.11.10-0} diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/CHANGELOG.rst b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/CHANGELOG.rst new file mode 100644 index 0000000000000000000000000000000000000000..bc030e7f821fabee5a78d2418181975b476fec54 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/CHANGELOG.rst @@ -0,0 +1,198 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package camera_info_manager +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1.11.10 (2016-01-19) +-------------------- + +1.11.9 (2016-01-17) +------------------- + +1.11.8 (2015-11-29) +------------------- +* fix compilation on Fedora, fixes `#42 <https://github.com/ros-perception/image_common/issues/42>`_ +* Contributors: Vincent Rabaud + +1.11.7 (2015-07-28) +------------------- + +1.11.6 (2015-07-16) +------------------- +* simplify target_link_libraries + That should fix `#35 <https://github.com/ros-perception/image_common/issues/35>`_ +* Contributors: Vincent Rabaud + +1.11.5 (2015-05-14) +------------------- + +1.11.4 (2014-09-21) +------------------- + +1.11.3 (2014-05-19) +------------------- +* Add public member function to manually set camera info (`#19 + <https://github.com/ros-perception/image_common/issues/19>`_) +* make rostest in CMakeLists optional (`ros/rosdistro#3010 + <https://github.com/ros/rosdistro/issues/3010>`_) +* Contributors: Jack O'Quin, Jonathan Bohren, Lukas Bulwahn + +1.11.2 (2014-02-13) +------------------- + +1.11.1 (2014-01-26 02:33) +------------------------- +* check for CATKIN_ENABLE_TESTING +* Contributors: Lukas Bulwahn + +1.11.0 (2013-07-20 12:23) +------------------------- + +1.10.5 (2014-01-26 02:34) +------------------------- + +1.10.4 (2013-07-20 11:42) +------------------------- +* add Jack as maintainer +* Contributors: Vincent Rabaud + +1.10.3 (2013-02-21 05:33) +------------------------- +* add gtest libraries linkage +* Contributors: Vincent Rabaud + +1.10.2 (2013-02-21 04:48) +------------------------- +* fix the rostest dependency +* Contributors: Vincent Rabaud + +1.10.1 (2013-02-21 04:16) +------------------------- +* fix catkin gtest and rostest problem +* fix unit test dependencies +* Removed duplicated test dependancy + Test dependencies should never duplicate build or run dependencies. +* Contributors: Aaron Blasdel, Jack O'Quin + +1.10.0 (2013-01-13) +------------------- +* fix the urls +* Contributors: Vincent Rabaud + +1.9.22 (2012-12-16) +------------------- + +1.9.21 (2012-12-14) +------------------- +* Updated package.xml file(s) to handle new catkin buildtool_depend + requirement +* Contributors: mirzashah + +1.9.20 (2012-12-04) +------------------- + +1.9.19 (2012-11-08) +------------------- + +1.9.18 (2012-11-06) +------------------- +* remove the brief attribute +* Contributors: Vincent Rabaud + +1.9.17 (2012-10-30 19:32) +------------------------- + +1.9.16 (2012-10-30 09:10) +------------------------- + +1.9.15 (2012-10-13 08:43) +------------------------- +* fix bad folder/libraries +* Contributors: Vincent Rabaud + +1.9.14 (2012-10-13 01:07) +------------------------- + +1.9.13 (2012-10-06) +------------------- + +1.9.12 (2012-10-04) +------------------- + +1.9.11 (2012-10-02 02:56) +------------------------- +* add missing rostest dependency +* Contributors: Vincent Rabaud + +1.9.10 (2012-10-02 02:42) +------------------------- +* fix bad dependency +* Contributors: Vincent Rabaud + +1.9.9 (2012-10-01) +------------------ +* fix dependencies +* Contributors: Vincent Rabaud + +1.9.8 (2012-09-30) +------------------ +* add catkin as a dependency +* comply to the catkin API +* Contributors: Vincent Rabaud + +1.9.7 (2012-09-18 11:39) +------------------------ +* add missing linkage +* Contributors: Vincent Rabaud + +1.9.6 (2012-09-18 11:07) +------------------------ + +1.9.5 (2012-09-13) +------------------ +* install the include directories +* Contributors: Vincent Rabaud + +1.9.4 (2012-09-12 23:37) +------------------------ + +1.9.3 (2012-09-12 20:44) +------------------------ + +1.9.2 (2012-09-10) +------------------ +* fix build issues +* Contributors: Vincent Rabaud + +1.9.1 (2012-09-07 15:33) +------------------------ +* make the libraries public +* Contributors: Vincent Rabaud + +1.9.0 (2012-09-07 13:03) +------------------------ +* API documentation review update +* suppress misleading camera_info_manager error messages [`#5273 + <https://github.com/ros-perception/image_common/issues/5273>`_] +* remove deprecated global CameraInfoManager symbol for Fuerte (`#4971 + <https://github.com/ros-perception/image_common/issues/4971>`_) +* Revert to using boost::mutex, not boost::recursive_mutex. +* Hack saveCalibrationFile() to stat() the containing directory and + attempt to create it if necessary. Test for this case. +* Reload camera info when camera name changes. +* Implement most new Electric API changes, with test cases. +* Add ${ROS_HOME} expansion, with unit test cases. + Do not use "$$" for a single '$', look for "${" instead. +* Use case-insensitive comparisons for parsing URL tags (`#4761 + <https://github.com/ros-perception/image_common/issues/4761>`_). + Add unit test cases to cover this. Add unit test case for camera + name containing video mode. +* add test for resolving an empty URL +* Deprecate use of global CameraInfoManager symbol in E-turtle (`#4786 + <https://github.com/ros-perception/image_common/issues/4786>`_). + Modify unit tests accordingly. +* provide camera_info_manager namespace, fixes `#4760 + <https://github.com/ros-perception/image_common/issues/4760>`_ +* Add support for "package://" URLs. +* Fixed tests to work with new CameraInfo. +* Moved image_common from camera_drivers. +* Contributors: Vincent Rabaud, blaise, Jack O'Quin, mihelich diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/CMakeLists.txt b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bcb250e6f7a7b663314ff8edc7c765a25ea3ca56 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 2.8) +project(camera_info_manager) + +find_package(catkin REQUIRED) + +find_package(Boost) +find_package(catkin REQUIRED roscpp sensor_msgs) +catkin_package(INCLUDE_DIRS include + LIBRARIES ${PROJECT_NAME} + DEPENDS Boost roscpp sensor_msgs +) + +find_package(catkin COMPONENTS camera_calibration_parsers image_transport roscpp roslib) + +include_directories(${catkin_INCLUDE_DIRS}) +include_directories(include) + +# add a library +add_library(${PROJECT_NAME} src/camera_info_manager.cpp) +target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES}) + +install(TARGETS ${PROJECT_NAME} + DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + COMPONENT main +) +install(DIRECTORY include/${PROJECT_NAME}/ + DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +) + +if(CATKIN_ENABLE_TESTING) + find_package(rostest) + # Unit test uses gtest, but needs rostest to create a ROS environment. + # Hence, it must be created as a normal executable, not using + # catkin_add_gtest() which runs an additional test without rostest. + add_executable(unit_test tests/unit_test.cpp) + target_link_libraries(unit_test ${PROJECT_NAME} ${GTEST_LIBRARIES} ${catkin_LIBRARIES}) + + add_rostest(tests/unit_test.test) +endif() diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/include/camera_info_manager/camera_info_manager.h b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/include/camera_info_manager/camera_info_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..56bb5d9cac9bafed2f53f2388a6057530664a3a9 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/include/camera_info_manager/camera_info_manager.h @@ -0,0 +1,243 @@ +/* -*- mode: C++ -*- */ +/* $Id$ */ + +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2010-2012 Jack O'Quin +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the author nor other contributors may be +* used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef _CAMERA_INFO_MANAGER_H_ +#define _CAMERA_INFO_MANAGER_H_ + +#include <ros/ros.h> +#include <boost/thread/mutex.hpp> +#include <sensor_msgs/CameraInfo.h> +#include <sensor_msgs/SetCameraInfo.h> + +/** @file + + @brief CameraInfo Manager interface + + @author Jack O'Quin + */ + +namespace camera_info_manager +{ + +/** @brief CameraInfo Manager class + + Provides CameraInfo, handles the sensor_msgs/SetCameraInfo service + requests, saves and restores sensor_msgs/CameraInfo data. + + @par ROS Service + + - @b set_camera_info (sensor_msgs/SetCameraInfo) stores + calibration information + + Typically, these service requests are made by a calibration + package, such as: + + - http://www.ros.org/wiki/camera_calibration + + The calling node @em must invoke ros::spin() or ros::spinOnce() in + some thread, so CameraInfoManager can handle arriving service + requests. + + @par Camera Name + + The device driver sets a camera name via the + CameraInfoManager::CameraInfoManager constructor or the + setCameraName() method. This name is written when CameraInfo is + saved, and checked when data are loaded, with a warning logged if + the name read does not match. + + Syntax: a camera name contains any combination of alphabetic, + numeric and '_' characters. Case is significant. + + Camera drivers may use any syntactically valid name they please. + Where possible, it is best for the name to be unique to the + device, such as a GUID, or the make, model and serial number. Any + parameters that affect calibration, such as resolution, focus, + zoom, etc., may also be included in the name, uniquely identifying + each CameraInfo file. + + Beginning with Electric Emys, the camera name can be resolved as + part of the URL, allowing direct access to device-specific + calibration information. + + @par Uniform Resource Locator + + The location for getting and saving calibration data is expressed + by Uniform Resource Locator. The driver defines a URL via the + CameraInfoManager::CameraInfoManager constructor or the + loadCameraInfo() method. Many drivers provide a @c + ~camera_info_url parameter so users may customize this URL, but + that is handled outside this class. + + Typically, cameras store calibration information in a file, which + can be in any format supported by @c camera_calibration_parsers. + Currently, that includes YAML and Videre INI files, identified by + their .yaml or .ini extensions as shown in the examples. These + file formats are described here: + + - http://www.ros.org/wiki/camera_calibration_parsers#File_formats + + Example URL syntax: + + - file:///full/path/to/local/file.yaml + - file:///full/path/to/videre/file.ini + - package://camera_info_manager/tests/test_calibration.yaml + - package://ros_package_name/calibrations/camera3.yaml + + The @c file: URL specifies a full path name in the local system. + The @c package: URL is handled the same as @c file:, except the + path name is resolved relative to the location of the named ROS + package, which @em must be reachable via @c $ROS_PACKAGE_PATH. + + Beginning with Electric Emys, the URL may contain substitution + variables delimited by <tt>${...}</tt>, including: + + - @c ${NAME} resolved to the current camera name defined by the + device driver. + - @c ${ROS_HOME} resolved to the @c $ROS_HOME environment variable + if defined, <tt>~/.ros</tt> if not. + + Resolution is done in a single pass through the URL string. + Variable values containing substitutable strings are not resolved + recursively. Unrecognized variable names are treated literally + with no substitution, but an error is logged. + + Examples with variable substitution: + + - package://my_cameras/calibrations/${NAME}.yaml + - file://${ROS_HOME}/camera_info/left_front_camera.yaml + + In C-turtle and Diamondback, if the URL was empty, no calibration + data were loaded, and any data provided via `set_camera_info` + would be stored in: + + - file:///tmp/calibration_${NAME}.yaml + + Beginning in Electric, the default URL changed to: + + - file://${ROS_HOME}/camera_info/${NAME}.yaml. + + If that file exists, its contents are used. Any new calibration + will be stored there, missing parent directories being created if + necessary and possible. + + @par Loading Calibration Data + + Prior to Fuerte, calibration information was loaded in the + constructor, and again each time the URL or camera name was + updated. This frequently caused logging of confusing and + misleading error messages. + + Beginning in Fuerte, camera_info_manager loads nothing until the + @c loadCameraInfo(), @c isCalibrated() or @c getCameraInfo() + method is called. That suppresses bogus error messages, but allows + (valid) load errors to occur during the first @c getCameraInfo(), + or @c isCalibrated(). To avoid that, do an explicit @c + loadCameraInfo() first. + +*/ + +class CameraInfoManager +{ + public: + + CameraInfoManager(ros::NodeHandle nh, + const std::string &cname="camera", + const std::string &url=""); + + sensor_msgs::CameraInfo getCameraInfo(void); + bool isCalibrated(void); + bool loadCameraInfo(const std::string &url); + std::string resolveURL(const std::string &url, + const std::string &cname); + bool setCameraName(const std::string &cname); + bool setCameraInfo(const sensor_msgs::CameraInfo &camera_info); + bool validateURL(const std::string &url); + + private: + + // recognized URL types + typedef enum + { + // supported URLs + URL_empty = 0, // empty string + URL_file, // file: + URL_package, // package: + // URLs not supported + URL_invalid, // anything >= is invalid + URL_flash, // flash: + } url_type_t; + + // private methods + std::string getPackageFileName(const std::string &url); + bool loadCalibration(const std::string &url, + const std::string &cname); + bool loadCalibrationFile(const std::string &filename, + const std::string &cname); + url_type_t parseURL(const std::string &url); + bool saveCalibration(const sensor_msgs::CameraInfo &new_info, + const std::string &url, + const std::string &cname); + bool saveCalibrationFile(const sensor_msgs::CameraInfo &new_info, + const std::string &filename, + const std::string &cname); + bool setCameraInfoService(sensor_msgs::SetCameraInfo::Request &req, + sensor_msgs::SetCameraInfo::Response &rsp); + + /** @brief mutual exclusion lock for private data + * + * This non-recursive mutex is only held for a short time while + * accessing or changing private class variables. To avoid + * deadlocks and contention, it is never held during I/O or while + * invoking a callback. Most private methods operate on copies of + * class variables, keeping the mutex hold time short. + */ + boost::mutex mutex_; + + // private data + ros::NodeHandle nh_; ///< node handle for service + ros::ServiceServer info_service_; ///< set_camera_info service + std::string camera_name_; ///< camera name + std::string url_; ///< URL for calibration data + sensor_msgs::CameraInfo cam_info_; ///< current CameraInfo + bool loaded_cam_info_; ///< cam_info_ load attempted + +}; // class CameraInfoManager + +}; // namespace camera_info_manager + +#endif // _CAMERA_INFO_MANAGER_H_ diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/mainpage.dox b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/mainpage.dox new file mode 100644 index 0000000000000000000000000000000000000000..418954812b36ba3dced5c3f70c6ad6755aef308b --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/mainpage.dox @@ -0,0 +1,9 @@ +/** +\mainpage +\htmlinclude manifest.html + +\section codeapi C++ API + +See: <camera_info_manager/camera_info_manager.h>. + +*/ diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/package.xml b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b8b82e211d6bf6ed1c41aa07665d4aef23c08d0 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/package.xml @@ -0,0 +1,40 @@ +<package> + <name>camera_info_manager</name> + <version>1.11.10</version> + <description> + + This package provides a C++ interface for camera calibration + information. It provides CameraInfo, and handles SetCameraInfo + service requests, saving and restoring the camera calibration + data. + + </description> + <author>Jack O'Quin</author> + <maintainer email="jack.oquin@gmail.com">Jack O'Quin</maintainer> + <maintainer email="vincent.rabaud@gmail.com">Vincent Rabaud</maintainer> + <license>BSD</license> + + <url type="website">http://ros.org/wiki/camera_info_manager</url> + <url type="bugtracker">https://github.com/ros-perception/image_common/issues</url> + <url type="repository">https://github.com/ros-perception/image_common</url> + + <buildtool_depend version_gte="0.5.68">catkin</buildtool_depend> + + <build_depend>boost</build_depend> + <build_depend>camera_calibration_parsers</build_depend> + <build_depend>image_transport</build_depend> + <build_depend>roscpp</build_depend> + <build_depend>roslib</build_depend> + <build_depend>rostest</build_depend> + <build_depend>sensor_msgs</build_depend> + + <run_depend>boost</run_depend> + <run_depend>camera_calibration_parsers</run_depend> + <run_depend>image_transport</run_depend> + <run_depend>roscpp</run_depend> + <run_depend>roslib</run_depend> + <run_depend>sensor_msgs</run_depend> + + <test_depend>gtest</test_depend> + +</package> diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/src/camera_info_manager.cpp b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/src/camera_info_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..976d7f10876151f5ae385015c155ea73cb4fee4c --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/src/camera_info_manager.cpp @@ -0,0 +1,657 @@ +/* $Id$ */ + +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2010-2012 Jack O'Quin +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the author nor other contributors may be +* used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include <string> +#include <locale> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <ros/ros.h> +#include <ros/package.h> +#include <boost/algorithm/string.hpp> +#include <camera_calibration_parsers/parse.h> + +#include "camera_info_manager/camera_info_manager.h" + +/** @file + + @brief CameraInfo Manager implementation + + Provides CameraInfo, handles the SetCameraInfo service requests, + saves and restores sensor_msgs/CameraInfo data. + + @author Jack O'Quin + */ + +namespace camera_info_manager +{ + +using namespace camera_calibration_parsers; + +/** URL to use when no other is defined. */ +const std::string + default_camera_info_url = "file://${ROS_HOME}/camera_info/${NAME}.yaml"; + +/** Constructor + * + * @param nh node handle, normally for the driver's streaming name + * space ("camera"). The service name is relative to this + * handle. Nodes supporting multiple cameras may use + * subordinate names, like "left/camera" and "right/camera". + * @param cname default camera name + * @param url default Uniform Resource Locator for loading and saving data. + */ +CameraInfoManager::CameraInfoManager(ros::NodeHandle nh, + const std::string &cname, + const std::string &url): + nh_(nh), + camera_name_(cname), + url_(url), + loaded_cam_info_(false) +{ + // register callback for camera calibration service request + info_service_ = nh_.advertiseService("set_camera_info", + &CameraInfoManager::setCameraInfoService, this); +} + +/** Get the current CameraInfo data. + * + * If CameraInfo has not yet been loaded, an attempt must be made + * here. To avoid that, ensure that loadCameraInfo() ran previously. + * If the load is attempted but fails, an empty CameraInfo will be + * supplied. + * + * The matrices are all zeros if no calibration is available. The + * image pipeline handles that as uncalibrated data. + * + * @warning The caller @em must fill in the message Header of the + * CameraInfo returned. The time stamp and frame_id should + * normally be the same as the corresponding Image message + * Header fields. + */ +sensor_msgs::CameraInfo CameraInfoManager::getCameraInfo(void) +{ + while (ros::ok()) + { + std::string cname; + std::string url; + { + boost::mutex::scoped_lock lock_(mutex_); + if (loaded_cam_info_) + { + return cam_info_; // all done + } + + // load being attempted now + loaded_cam_info_ = true; + + // copy the name and URL strings + url = url_; + cname = camera_name_; + + } // release the lock + + // attempt load without the lock, it is not recursive + loadCalibration(url, cname); + } +} + +/** Get file name corresponding to a @c package: URL. + * + * @param url a copy of the Uniform Resource Locator + * @return file name if package found, "" otherwise + */ +std::string CameraInfoManager::getPackageFileName(const std::string &url) +{ + ROS_DEBUG_STREAM("camera calibration URL: " << url); + + // Scan URL from after "package://" until next '/' and extract + // package name. The parseURL() already checked that it's present. + size_t prefix_len = std::string("package://").length(); + size_t rest = url.find('/', prefix_len); + std::string package(url.substr(prefix_len, rest - prefix_len)); + + // Look up the ROS package path name. + std::string pkgPath(ros::package::getPath(package)); + if (pkgPath.empty()) // package not found? + { + ROS_WARN_STREAM("unknown package: " << package << " (ignored)"); + return pkgPath; + } + else + { + // Construct file name from package location and remainder of URL. + return pkgPath + url.substr(rest); + } +} + +/** Is the current CameraInfo calibrated? + * + * If CameraInfo has not yet been loaded, an attempt must be made + * here. To avoid that, ensure that loadCameraInfo() ran previously. + * If the load failed, CameraInfo will be empty and this predicate + * will return false. + * + * @return true if the current CameraInfo is calibrated. + */ +bool CameraInfoManager::isCalibrated(void) +{ + while (true) + { + std::string cname; + std::string url; + { + boost::mutex::scoped_lock lock_(mutex_); + if (loaded_cam_info_) + { + return (cam_info_.K[0] != 0.0); + } + + // load being attempted now + loaded_cam_info_ = true; + + // copy the name and URL strings + url = url_; + cname = camera_name_; + + } // release the lock + + // attempt load without the lock, it is not recursive + loadCalibration(url, cname); + } +} + +/** Load CameraInfo calibration data (if any). + * + * @pre mutex_ unlocked + * + * @param url a copy of the Uniform Resource Locator + * @param cname is a copy of the camera_name_ + * @return true if URL contains calibration data. + * + * sets cam_info_, if successful + */ +bool CameraInfoManager::loadCalibration(const std::string &url, + const std::string &cname) +{ + bool success = false; // return value + + const std::string resURL(resolveURL(url, cname)); + url_type_t url_type = parseURL(resURL); + + if (url_type != URL_empty) + { + ROS_INFO_STREAM("camera calibration URL: " << resURL); + } + + switch (url_type) + { + case URL_empty: + { + ROS_INFO("using default calibration URL"); + success = loadCalibration(default_camera_info_url, cname); + break; + } + case URL_file: + { + success = loadCalibrationFile(resURL.substr(7), cname); + break; + } + case URL_flash: + { + ROS_WARN("[CameraInfoManager] reading from flash not implemented yet"); + break; + } + case URL_package: + { + std::string filename(getPackageFileName(resURL)); + if (!filename.empty()) + success = loadCalibrationFile(filename, cname); + break; + } + default: + { + ROS_ERROR_STREAM("Invalid camera calibration URL: " << resURL); + break; + } + } + + return success; +} + +/** Load CameraInfo calibration data from a file. + * + * @pre mutex_ unlocked + * + * @param filename containing CameraInfo to read + * @param cname is a copy of the camera_name_ + * @return true if URL contains calibration data. + * + * Sets cam_info_, if successful + */ +bool CameraInfoManager::loadCalibrationFile(const std::string &filename, + const std::string &cname) +{ + bool success = false; + + ROS_DEBUG_STREAM("reading camera calibration from " << filename); + std::string cam_name; + sensor_msgs::CameraInfo cam_info; + + if (readCalibration(filename, cam_name, cam_info)) + { + if (cname != cam_name) + { + ROS_WARN_STREAM("[" << cname << "] does not match name " + << cam_name << " in file " << filename); + } + success = true; + { + // lock only while updating cam_info_ + boost::mutex::scoped_lock lock(mutex_); + cam_info_ = cam_info; + } + } + else + { + ROS_WARN_STREAM("Camera calibration file " << filename << " not found."); + } + + return success; +} + +/** Set a new URL and load its calibration data (if any). + * + * If multiple threads call this method simultaneously with different + * URLs, there is no guarantee which will prevail. + * + * @param url new Uniform Resource Locator for CameraInfo. + * @return true if new URL contains calibration data. + * + * @post @c loaded_cam_info_ true (meaning a load was attempted, even + * if it failed); @c cam_info_ updated, if successful. + */ +bool CameraInfoManager::loadCameraInfo(const std::string &url) +{ + std::string cname; + { + boost::mutex::scoped_lock lock(mutex_); + url_ = url; + cname = camera_name_; + loaded_cam_info_ = true; + } + + // load using copies of the parameters, no need to hold the lock + return loadCalibration(url, cname); +} + + +/** Resolve Uniform Resource Locator string. + * + * @param url a copy of the Uniform Resource Locator, which may + * include <tt>${...}</tt> substitution variables. + * @param cname is a copy of the camera_name_ + * + * @return a copy of the URL with any variable information resolved. + */ +std::string CameraInfoManager::resolveURL(const std::string &url, + const std::string &cname) +{ + std::string resolved; + size_t rest = 0; + + while (true) + { + // find the next '$' in the URL string + size_t dollar = url.find('$', rest); + + if (dollar >= url.length()) + { + // no more variables left in the URL + resolved += url.substr(rest); + break; + } + + // copy characters up to the next '$' + resolved += url.substr(rest, dollar-rest); + + if (url.substr(dollar+1, 1) != "{") + { + // no '{' follows, so keep the '$' + resolved += "$"; + } + else if (url.substr(dollar+1, 6) == "{NAME}") + { + // substitute camera name + resolved += cname; + dollar += 6; + } + else if (url.substr(dollar+1, 10) == "{ROS_HOME}") + { + // substitute $ROS_HOME + std::string ros_home; + char *ros_home_env; + if ((ros_home_env = getenv("ROS_HOME"))) + { + // use environment variable + ros_home = ros_home_env; + } + else if ((ros_home_env = getenv("HOME"))) + { + // use "$HOME/.ros" + ros_home = ros_home_env; + ros_home += "/.ros"; + } + resolved += ros_home; + dollar += 10; + } + else + { + // not a valid substitution variable + ROS_ERROR_STREAM("[CameraInfoManager]" + " invalid URL substitution (not resolved): " + << url); + resolved += "$"; // keep the bogus '$' + } + + // look for next '$' + rest = dollar + 1; + } + + return resolved; +} + +/** Parse calibration Uniform Resource Locator. + * + * @param url string to parse + * @return URL type + * + * @note Recognized but unsupported URL types have enum values >= URL_invalid. + */ +CameraInfoManager::url_type_t CameraInfoManager::parseURL(const std::string &url) +{ + if (url == "") + { + return URL_empty; + } + if (boost::iequals(url.substr(0, 8), "file:///")) + { + return URL_file; + } + if (boost::iequals(url.substr(0, 9), "flash:///")) + { + return URL_flash; + } + if (boost::iequals(url.substr(0, 10), "package://")) + { + // look for a '/' following the package name, make sure it is + // there, the name is not empty, and something follows it + size_t rest = url.find('/', 10); + if (rest < url.length()-1 && rest > 10) + return URL_package; + } + return URL_invalid; +} + +/** Save CameraInfo calibration data. + * + * @pre mutex_ unlocked + * + * @param new_info contains CameraInfo to save + * @param url is a copy of the URL storage location (if empty, use + * @c file://${ROS_HOME}/camera_info/${NAME}.yaml) + * @param cname is a copy of the camera_name_ + * @return true, if successful + */ +bool +CameraInfoManager::saveCalibration(const sensor_msgs::CameraInfo &new_info, + const std::string &url, + const std::string &cname) +{ + bool success = false; + + const std::string resURL(resolveURL(url, cname)); + + switch (parseURL(resURL)) + { + case URL_empty: + { + // store using default file name + success = saveCalibration(new_info, default_camera_info_url, cname); + break; + } + case URL_file: + { + success = saveCalibrationFile(new_info, resURL.substr(7), cname); + break; + } + case URL_package: + { + std::string filename(getPackageFileName(resURL)); + if (!filename.empty()) + success = saveCalibrationFile(new_info, filename, cname); + break; + } + default: + { + // invalid URL, save to default location + ROS_ERROR_STREAM("invalid url: " << resURL << " (ignored)"); + success = saveCalibration(new_info, default_camera_info_url, cname); + break; + } + } + + return success; +} + +/** Save CameraInfo calibration data to a file. + * + * @pre mutex_ unlocked + * + * @param new_info contains CameraInfo to save + * @param filename is local file to store data + * @param cname is a copy of the camera_name_ + * @return true, if successful + */ +bool +CameraInfoManager::saveCalibrationFile(const sensor_msgs::CameraInfo &new_info, + const std::string &filename, + const std::string &cname) +{ + ROS_INFO_STREAM("writing calibration data to " << filename); + + // isolate the name of the containing directory + size_t last_slash = filename.rfind('/'); + if (last_slash >= filename.length()) + { + // No slash in the name. This should never happen, the URL + // parser ensures there is at least one '/' at the beginning. + ROS_ERROR_STREAM("filename [" << filename << "] has no '/'"); + return false; // not a valid URL + } + + // make sure the directory exists and is writable + std::string dirname(filename.substr(0, last_slash+1)); + struct stat stat_data; + int rc = stat(dirname.c_str(), &stat_data); + if (rc != 0) + { + if (errno == ENOENT) + { + // directory does not exist, try to create it and its parents + std::string command("mkdir -p " + dirname); + rc = system(command.c_str()); + if (rc != 0) + { + // mkdir failed + ROS_ERROR_STREAM("unable to create path to directory [" + << dirname << "]"); + return false; + } + } + else + { + // not accessible, or something screwy + ROS_ERROR_STREAM("directory [" << dirname << "] not accessible"); + return false; + } + } + else if (!S_ISDIR(stat_data.st_mode)) + { + // dirname exists but is not a directory + ROS_ERROR_STREAM("[" << dirname << "] is not a directory"); + return false; + } + + // Directory exists and is accessible. Permissions might still be bad. + + // Currently, writeCalibration() always returns true no matter what + // (ros-pkg ticket #5010). + return writeCalibration(filename, cname, new_info); +} + +/** Callback for SetCameraInfo request. + * + * Always updates cam_info_ class variable, even if save fails. + * + * @param req SetCameraInfo request message + * @param rsp SetCameraInfo response message + * @return true if message handled + */ +bool +CameraInfoManager::setCameraInfoService(sensor_msgs::SetCameraInfo::Request &req, + sensor_msgs::SetCameraInfo::Response &rsp) +{ + // copies of class variables needed for saving calibration + std::string url_copy; + std::string cname; + { + boost::mutex::scoped_lock lock(mutex_); + cam_info_ = req.camera_info; + url_copy = url_; + cname = camera_name_; + loaded_cam_info_ = true; + } + + if (!nh_.ok()) + { + ROS_ERROR("set_camera_info service called, but driver not running."); + rsp.status_message = "Camera driver not running."; + rsp.success = false; + return false; + } + + rsp.success = saveCalibration(req.camera_info, url_copy, cname); + if (!rsp.success) + rsp.status_message = "Error storing camera calibration."; + + return true; +} + +/** Set a new camera name. + * + * @param cname new camera name to use for saving calibration data + * + * @return true if new name has valid syntax; valid names contain only + * alphabetic, numeric, or '_' characters. + * + * @post @c cam_name_ updated, if valid; since it may affect the URL, + * @c cam_info_ will be reloaded before being used again. + */ +bool CameraInfoManager::setCameraName(const std::string &cname) +{ + // the camera name may not be empty + if (cname.empty()) + return false; + + // validate the camera name characters + for (unsigned i = 0; i < cname.size(); ++i) + { + if (!isalnum(cname[i]) && cname[i] != '_') + return false; + } + + // The name is valid, so update our private copy. Since the new + // name might cause the existing URL to resolve somewhere else, + // force @c cam_info_ to be reloaded before being used again. + { + boost::mutex::scoped_lock lock(mutex_); + camera_name_ = cname; + loaded_cam_info_ = false; + } + + return true; +} + +/** Set the camera info manually + * + * @param camera_info new camera calibration data + * + * @return true if new camera info is set + * + * @post @c cam_info_ updated, if valid; + */ +bool CameraInfoManager::setCameraInfo(const sensor_msgs::CameraInfo &camera_info) +{ + boost::mutex::scoped_lock lock(mutex_); + + cam_info_ = camera_info; + loaded_cam_info_ = true; + + return true; +} + +/** Validate URL syntax. + * + * @param url Uniform Resource Locator to check + * + * @return true if URL syntax is supported by CameraInfoManager + * (although the resource need not actually exist) + */ +bool CameraInfoManager::validateURL(const std::string &url) +{ + std::string cname; // copy of camera name + { + boost::mutex::scoped_lock lock(mutex_); + cname = camera_name_; + } // release the lock + + url_type_t url_type = parseURL(resolveURL(url, cname)); + return (url_type < URL_invalid); +} + +} // namespace camera_info_manager diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/test_calibration.yaml b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/test_calibration.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8df9d707ca774e00425a146ef0bab9eeaf76017c --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/test_calibration.yaml @@ -0,0 +1,20 @@ +image_width: 640 +image_height: 480 +camera_name: 08144361026320a0 +camera_matrix: + rows: 3 + cols: 3 + data: [1168.68, 0, 295.015, 0, 1169.01, 252.247, 0, 0, 1] +distortion_model: plumb_bob +distortion_coefficients: + rows: 1 + cols: 5 + data: [-1.04482, 1.59252, -0.0196308, 0.0287906, 0] +rectification_matrix: + rows: 3 + cols: 3 + data: [1, 0, 0, 0, 1, 0, 0, 0, 1] +projection_matrix: + rows: 3 + cols: 4 + data: [1168.68, 0, 295.015, 0, 0, 1169.01, 252.247, 0, 0, 0, 1, 0] \ No newline at end of file diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/unit_test.cpp b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/unit_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d7222573ef3ecce82c2976e14e613a804a1a7e7 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/unit_test.cpp @@ -0,0 +1,719 @@ +/* $Id$ */ + +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2010 Jack O'Quin +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the author nor other contributors may be +* used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include <unistd.h> +#include <stdlib.h> +#include <ros/ros.h> +#include <ros/package.h> +#include "camera_info_manager/camera_info_manager.h" +#include <sensor_msgs/distortion_models.h> +#include <string> +#include <gtest/gtest.h> + +/////////////////////////////////////////////////////////////// +// global test data +/////////////////////////////////////////////////////////////// + +namespace +{ + const std::string g_package_name("camera_info_manager"); + const std::string g_test_name("test_calibration"); + const std::string g_package_filename("/tests/" + g_test_name +".yaml"); + const std::string g_package_url("package://" + g_package_name + + g_package_filename); + const std::string g_package_name_url("package://" + g_package_name + + "/tests/${NAME}.yaml"); + const std::string g_default_url("file://${ROS_HOME}/camera_info/${NAME}.yaml"); + const std::string g_camera_name("08144361026320a0"); +} + +/////////////////////////////////////////////////////////////// +// utility functions +/////////////////////////////////////////////////////////////// + +// compare CameraInfo fields that are saved and loaded for calibration +void compare_calibration(const sensor_msgs::CameraInfo &exp, + const sensor_msgs::CameraInfo &ci) +{ + // check image size + EXPECT_EQ(exp.width, ci.width); + EXPECT_EQ(exp.height, ci.height); + + // check distortion coefficients + EXPECT_EQ(exp.distortion_model, ci.distortion_model); + EXPECT_EQ(exp.D.size(), ci.D.size()); + for (unsigned i = 0; i < ci.D.size(); ++i) + { + EXPECT_EQ(exp.D[i], ci.D[i]); + } + + // check camera matrix + for (unsigned i = 0; i < ci.K.size(); ++i) + { + EXPECT_EQ(exp.K[i], ci.K[i]); + } + + // check rectification matrix + for (unsigned i = 0; i < ci.R.size(); ++i) + { + EXPECT_EQ(exp.R[i], ci.R[i]); + } + + // check projection matrix + for (unsigned i = 0; i < ci.P.size(); ++i) + { + EXPECT_EQ(exp.P[i], ci.P[i]); + } +} + +// make sure this file does not exist +void delete_file(std::string filename) +{ + int rc = unlink(filename.c_str()); + if (rc != 0) + { + if (errno != ENOENT) + ROS_INFO_STREAM("unexpected unlink() error: " << errno); + } +} + +void delete_default_file(void) +{ + std::string ros_home("/tmp"); + setenv("ROS_HOME", ros_home.c_str(), true); + std::string tmpFile(ros_home + "/camera_info/camera.yaml"); + delete_file(tmpFile); +} + +void do_system(const std::string &command) +{ + int rc = system(command.c_str()); + if (rc) + std::cout << command << " returns " << rc; +} + +void delete_tmp_camera_info_directory(void) +{ + do_system(std::string("rm -rf /tmp/camera_info")); +} + +void make_tmp_camera_info_directory(void) +{ + do_system(std::string("mkdir -p /tmp/camera_info")); +} + +// These data must match the contents of test_calibration.yaml. +sensor_msgs::CameraInfo expected_calibration(void) +{ + sensor_msgs::CameraInfo ci; + + ci.width = 640u; + ci.height = 480u; + + // set distortion coefficients + ci.distortion_model = sensor_msgs::distortion_models::PLUMB_BOB; + ci.D.resize(5); + ci.D[0] = -1.04482; + ci.D[1] = 1.59252; + ci.D[2] = -0.0196308; + ci.D[3] = 0.0287906; + ci.D[4] = 0.0; + + // set camera matrix + ci.K[0] = 1168.68; + ci.K[1] = 0.0; + ci.K[2] = 295.015; + ci.K[3] = 0.0; + ci.K[4] = 1169.01; + ci.K[5] = 252.247; + ci.K[6] = 0.0; + ci.K[7] = 0.0; + ci.K[8] = 1.0; + + // set rectification matrix + ci.R[0] = 1.0; + ci.R[1] = 0.0; + ci.R[2] = 0.0; + ci.R[3] = 0.0; + ci.R[4] = 1.0; + ci.R[5] = 0.0; + ci.R[6] = 0.0; + ci.R[7] = 0.0; + ci.R[8] = 1.0; + + // set projection matrix + ci.P[0] = ci.K[0]; + ci.P[1] = ci.K[1]; + ci.P[2] = ci.K[2]; + ci.P[3] = 0.0; + ci.P[4] = ci.K[3]; + ci.P[5] = ci.K[4]; + ci.P[6] = ci.K[5]; + ci.P[7] = 0.0; + ci.P[8] = ci.K[6]; + ci.P[9] = ci.K[7]; + ci.P[10] = ci.K[8]; + ci.P[11] = 0.0; + + return ci; +} + +// issue SetCameraInfo service request +bool set_calibration(ros::NodeHandle node, + const sensor_msgs::CameraInfo &calib) +{ + ros::ServiceClient client = + node.serviceClient<sensor_msgs::SetCameraInfo>("set_camera_info"); + sensor_msgs::SetCameraInfo set_camera_info; + set_camera_info.request.camera_info = calib; + bool success; + EXPECT_TRUE((success = client.call(set_camera_info))); + return success; +} + +// resolve URL string, result should be as expected +void check_url_substitution(ros::NodeHandle node, + const std::string &url, + const std::string &exp_url, + const std::string &camera_name) +{ + camera_info_manager::CameraInfoManager cinfo(node, camera_name, url); + std::string sub_url = cinfo.resolveURL(url, camera_name); + EXPECT_EQ(sub_url, exp_url); +} + +/////////////////////////////////////////////////////////////// +// Test cases +/////////////////////////////////////////////////////////////// + +// Test that valid camera names are accepted +TEST(CameraName, validNames) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + EXPECT_TRUE(cinfo.setCameraName(std::string("a"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("1"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("_"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("abcdefghijklmnopqrstuvwxyz"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("0123456789"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("0123456789abcdef"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("A1"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("9z"))); + EXPECT_TRUE(cinfo.setCameraName(std::string("08144361026320a0_640x480_mono8"))); + +} + +// Test that invalid camera names are rejected +TEST(CameraName, invalidNames) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + EXPECT_FALSE(cinfo.setCameraName(std::string(""))); + EXPECT_FALSE(cinfo.setCameraName(std::string("-21"))); + EXPECT_FALSE(cinfo.setCameraName(std::string("C++"))); + EXPECT_FALSE(cinfo.setCameraName(std::string("file:///tmp/url.yaml"))); + EXPECT_FALSE(cinfo.setCameraName(std::string("file://${INVALID}/xxx.yaml"))); +} + +// Test that valid URLs are accepted +TEST(UrlValidation, validURLs) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + EXPECT_TRUE(cinfo.validateURL(std::string(""))); + EXPECT_TRUE(cinfo.validateURL(std::string("file:///"))); + EXPECT_TRUE(cinfo.validateURL(std::string("file:///tmp/url.yaml"))); + EXPECT_TRUE(cinfo.validateURL(std::string("File:///tmp/url.ini"))); + EXPECT_TRUE(cinfo.validateURL(std::string("FILE:///tmp/url.yaml"))); + EXPECT_TRUE(cinfo.validateURL(g_default_url)); + EXPECT_TRUE(cinfo.validateURL(g_package_url)); + EXPECT_TRUE(cinfo.validateURL(std::string("package://no_such_package/calibration.yaml"))); + EXPECT_TRUE(cinfo.validateURL(std::string("packAge://camera_info_manager/x"))); +} + +// Test that invalid URLs are rejected +TEST(UrlValidation, invalidURLs) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + EXPECT_FALSE(cinfo.validateURL(std::string("file://"))); + EXPECT_FALSE(cinfo.validateURL(std::string("flash:///"))); + EXPECT_FALSE(cinfo.validateURL(std::string("html://ros.org/wiki/camera_info_manager"))); + EXPECT_FALSE(cinfo.validateURL(std::string("package://"))); + EXPECT_FALSE(cinfo.validateURL(std::string("package:///"))); + EXPECT_FALSE(cinfo.validateURL(std::string("package://calibration.yaml"))); + EXPECT_FALSE(cinfo.validateURL(std::string("package://camera_info_manager/"))); +} + +// Test ability to provide uncalibrated CameraInfo +TEST(GetInfo, uncalibrated) +{ + ros::NodeHandle node; + + delete_default_file(); + + camera_info_manager::CameraInfoManager cinfo(node); + EXPECT_FALSE(cinfo.isCalibrated()); + + sensor_msgs::CameraInfo ci(cinfo.getCameraInfo()); + sensor_msgs::CameraInfo exp; + compare_calibration(exp, ci); +} + +// Test ability to load calibrated CameraInfo +TEST(GetInfo, calibrated) +{ + ros::NodeHandle node; + + delete_default_file(); + + camera_info_manager::CameraInfoManager cinfo(node); + EXPECT_FALSE(cinfo.isCalibrated()); + + std::string pkgPath(ros::package::getPath(g_package_name)); + std::string url("file://" + pkgPath + "/tests/test_calibration.yaml"); + EXPECT_TRUE(cinfo.loadCameraInfo(url)); + EXPECT_TRUE(cinfo.isCalibrated()); + + sensor_msgs::CameraInfo ci(cinfo.getCameraInfo()); + sensor_msgs::CameraInfo exp(expected_calibration()); + compare_calibration(exp, ci); +} + +// Test ability to load calibrated CameraInfo from package +TEST(GetInfo, fromPackage) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + EXPECT_TRUE(cinfo.loadCameraInfo(g_package_url)); + EXPECT_TRUE(cinfo.isCalibrated()); + + sensor_msgs::CameraInfo ci(cinfo.getCameraInfo()); + sensor_msgs::CameraInfo exp(expected_calibration()); + compare_calibration(exp, ci); +} + +// Test ability to access named calibrated CameraInfo from package +TEST(GetInfo, fromPackageWithName) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node, g_test_name, + g_package_name_url); + EXPECT_TRUE(cinfo.isCalibrated()); + + sensor_msgs::CameraInfo ci(cinfo.getCameraInfo()); + sensor_msgs::CameraInfo exp(expected_calibration()); + compare_calibration(exp, ci); +} + +// Test load of unresolved "package:" URL files +TEST(GetInfo, unresolvedLoads) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + EXPECT_FALSE(cinfo.loadCameraInfo(std::string("package://"))); + EXPECT_FALSE(cinfo.isCalibrated()); + + EXPECT_FALSE(cinfo.loadCameraInfo(std::string("package:///calibration.yaml"))); + EXPECT_FALSE(cinfo.isCalibrated()); + + EXPECT_FALSE(cinfo.loadCameraInfo(std::string("package://no_such_package/calibration.yaml"))); + EXPECT_FALSE(cinfo.isCalibrated()); + + EXPECT_FALSE(cinfo.loadCameraInfo(std::string("package://camera_info_manager/no_such_file.yaml"))); + EXPECT_FALSE(cinfo.isCalibrated()); +} + +// Test load of "package:" URL after changing name +TEST(GetInfo, nameChange) +{ + ros::NodeHandle node; + const std::string missing_file("no_such_file"); + + // first declare using non-existent camera name + camera_info_manager::CameraInfoManager cinfo(node, missing_file, + g_package_name_url); + EXPECT_FALSE(cinfo.isCalibrated()); + + // set name so it resolves to a test file that does exist + EXPECT_TRUE(cinfo.setCameraName(g_test_name)); + EXPECT_TRUE(cinfo.isCalibrated()); + sensor_msgs::CameraInfo ci(cinfo.getCameraInfo()); + sensor_msgs::CameraInfo exp(expected_calibration()); + compare_calibration(exp, ci); +} + +// Test load of invalid CameraInfo URLs +TEST(GetInfo, invalidLoads) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + EXPECT_FALSE(cinfo.loadCameraInfo(std::string("flash:///"))); + EXPECT_FALSE(cinfo.isCalibrated()); + + EXPECT_FALSE(cinfo.loadCameraInfo(std::string("html://ros.org/wiki/camera_info_manager"))); + EXPECT_FALSE(cinfo.isCalibrated()); + + sensor_msgs::CameraInfo ci(cinfo.getCameraInfo()); + sensor_msgs::CameraInfo exp; + compare_calibration(exp, ci); +} + +// Test ability to set CameraInfo directly +TEST(SetInfo, setCameraInfo) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + // issue calibration service request + sensor_msgs::CameraInfo exp(expected_calibration()); + bool success = cinfo.setCameraInfo(exp); + EXPECT_TRUE(success); + + // only check results if the service succeeded, avoiding confusing + // and redundant failure messages + if (success) + { + // check that it worked + EXPECT_TRUE(cinfo.isCalibrated()); + sensor_msgs::CameraInfo ci = cinfo.getCameraInfo(); + compare_calibration(exp, ci); + } +} + +// Test ability to set calibrated CameraInfo +TEST(SetInfo, setCalibration) +{ + ros::NodeHandle node; + camera_info_manager::CameraInfoManager cinfo(node); + + // issue calibration service request + sensor_msgs::CameraInfo exp(expected_calibration()); + bool success = set_calibration(node, exp); + + // only check results if the service succeeded, avoiding confusing + // and redundant failure messages + if (success) + { + // check that it worked + EXPECT_TRUE(cinfo.isCalibrated()); + sensor_msgs::CameraInfo ci = cinfo.getCameraInfo(); + compare_calibration(exp, ci); + } +} + +// Test ability to save calibrated CameraInfo in default URL +TEST(SetInfo, saveCalibrationDefault) +{ + ros::NodeHandle node; + sensor_msgs::CameraInfo exp(expected_calibration()); + bool success; + + // Set ${ROS_HOME} to /tmp, then delete the /tmp/camera_info + // directory and everything in it. + setenv("ROS_HOME", "/tmp", true); + delete_tmp_camera_info_directory(); + + { + // create instance to save calibrated data + camera_info_manager::CameraInfoManager cinfo(node); + EXPECT_FALSE(cinfo.isCalibrated()); + + // issue calibration service request + success = set_calibration(node, exp); + EXPECT_TRUE(cinfo.isCalibrated()); + } + + // only check results if the service succeeded, avoiding confusing + // and redundant failure messages + if (success) + { + // create a new instance to load saved calibration + camera_info_manager::CameraInfoManager cinfo2(node); + EXPECT_TRUE(cinfo2.isCalibrated()); + if (cinfo2.isCalibrated()) + { + sensor_msgs::CameraInfo ci(cinfo2.getCameraInfo()); + compare_calibration(exp, ci); + } + } +} + +// Test ability to save calibrated CameraInfo to default location with +// explicit camera name +TEST(SetInfo, saveCalibrationCameraName) +{ + ros::NodeHandle node; + sensor_msgs::CameraInfo exp(expected_calibration()); + bool success; + + // set ${ROS_HOME} to /tmp, delete the calibration file + std::string ros_home("/tmp"); + setenv("ROS_HOME", ros_home.c_str(), true); + std::string tmpFile(ros_home + "/camera_info/" + g_camera_name + ".yaml"); + delete_file(tmpFile); + + { + // create instance to save calibrated data + camera_info_manager::CameraInfoManager cinfo(node, g_camera_name); + success = set_calibration(node, exp); + EXPECT_TRUE(cinfo.isCalibrated()); + } + + // only check results if the service succeeded, avoiding confusing + // and redundant failure messages + if (success) + { + // create a new instance to load saved calibration + camera_info_manager::CameraInfoManager cinfo2(node); + std::string url = "file://" + tmpFile; + cinfo2.loadCameraInfo(std::string(url)); + EXPECT_TRUE(cinfo2.isCalibrated()); + if (cinfo2.isCalibrated()) + { + sensor_msgs::CameraInfo ci(cinfo2.getCameraInfo()); + compare_calibration(exp, ci); + } + } +} + +// Test ability to save calibrated CameraInfo in a file +TEST(SetInfo, saveCalibrationFile) +{ + return; + + ros::NodeHandle node; + sensor_msgs::CameraInfo exp(expected_calibration()); + std::string cname("camera"); + std::string tmpFile("/tmp/camera_info_manager_calibration_test.yaml"); + std::string url = "file://" + tmpFile; + bool success; + + // first, delete the file + delete_file(tmpFile); + + { + // create instance to save calibrated data + camera_info_manager::CameraInfoManager cinfo(node, cname, url); + success = set_calibration(node, exp); + EXPECT_TRUE(cinfo.isCalibrated()); + } + + // only check results if the service succeeded, avoiding confusing + // and redundant failure messages + if (success) + { + // create a new instance to load saved calibration + camera_info_manager::CameraInfoManager cinfo2(node, cname, url); + EXPECT_TRUE(cinfo2.isCalibrated()); + if (cinfo2.isCalibrated()) + { + sensor_msgs::CameraInfo ci(cinfo2.getCameraInfo()); + compare_calibration(exp, ci); + } + } +} + +// Test ability to save calibrated CameraInfo in a package +// (needs write access). +TEST(SetInfo, saveCalibrationPackage) +{ + ros::NodeHandle node; + sensor_msgs::CameraInfo exp(expected_calibration()); + std::string pkgPath(ros::package::getPath(g_package_name)); + std::string filename(pkgPath + g_package_filename); + bool success; + + // first, delete the file + delete_file(filename); + + { + // create instance to save calibrated data + camera_info_manager::CameraInfoManager cinfo(node, g_camera_name, + g_package_url); + success = set_calibration(node, exp); + EXPECT_TRUE(cinfo.isCalibrated()); + } + + // only check results if the service succeeded, avoiding confusing + // and redundant failure messages + if (success) + { + // create a new instance to load saved calibration + camera_info_manager::CameraInfoManager cinfo2(node, g_camera_name, + g_package_url); + EXPECT_TRUE(cinfo2.isCalibrated()); + if (cinfo2.isCalibrated()) + { + sensor_msgs::CameraInfo ci(cinfo2.getCameraInfo()); + compare_calibration(exp, ci); + } + } +} + +TEST(UrlSubstitution, cameraName) +{ + ros::NodeHandle node; + std::string name_url; + std::string exp_url; + + // resolve a GUID camera name + name_url = "package://" + g_package_name + "/tests/${NAME}.yaml"; + exp_url = "package://" + g_package_name + "/tests/" + g_camera_name + ".yaml"; + check_url_substitution(node, name_url, exp_url, g_camera_name); + + // substitute camera name "test" + name_url = "package://" + g_package_name + "/tests/${NAME}_calibration.yaml"; + std::string test_name("test"); + exp_url = "package://" + g_package_name + "/tests/" + test_name + + "_calibration.yaml"; + check_url_substitution(node, name_url, exp_url, test_name); + + // with an '_' in the name + test_name = "camera_1024x768"; + exp_url = "package://" + g_package_name + "/tests/" + test_name + + "_calibration.yaml"; + check_url_substitution(node, name_url, exp_url, test_name); + + // substitute empty camera name + name_url = "package://" + g_package_name + "/tests/${NAME}_calibration.yaml"; + std::string empty_name(""); + exp_url = "package://" + g_package_name + "/tests/" + empty_name + + "_calibration.yaml"; + check_url_substitution(node, name_url, exp_url, empty_name); + + // substitute test camera calibration from this package + check_url_substitution(node, g_package_name_url, g_package_url, g_test_name); +} + +TEST(UrlSubstitution, rosHome) +{ + ros::NodeHandle node; + std::string name_url; + std::string exp_url; + char *home_env = getenv("HOME"); + std::string home(home_env); + + // resolve ${ROS_HOME} with environment variable undefined + unsetenv("ROS_HOME"); + name_url = "file://${ROS_HOME}/camera_info/test_camera.yaml"; + exp_url = "file://" + home + "/.ros/camera_info/test_camera.yaml"; + check_url_substitution(node, name_url, exp_url, g_camera_name); + + // resolve ${ROS_HOME} with environment variable defined + setenv("ROS_HOME", "/my/ros/home", true); + name_url = "file://${ROS_HOME}/camera_info/test_camera.yaml"; + exp_url = "file:///my/ros/home/camera_info/test_camera.yaml"; + check_url_substitution(node, name_url, exp_url, g_camera_name); +} + +TEST(UrlSubstitution, unmatchedDollarSigns) +{ + ros::NodeHandle node; + + // test for "$$" in the URL (NAME should be resolved) + std::string name_url("file:///tmp/$${NAME}.yaml"); + std::string exp_url("file:///tmp/$" + g_camera_name + ".yaml"); + check_url_substitution(node, name_url, exp_url, g_camera_name); + + // test for "$" in middle of string + name_url = "file:///$whatever.yaml"; + check_url_substitution(node, name_url, name_url, g_camera_name); + + // test for "$$" in middle of string + name_url = "file:///something$$whatever.yaml"; + check_url_substitution(node, name_url, name_url, g_camera_name); + + // test for "$$" at end of string + name_url = "file:///$$"; + check_url_substitution(node, name_url, name_url, g_camera_name); +} + +TEST(UrlSubstitution, emptyURL) +{ + // test that empty URL is handled correctly + ros::NodeHandle node; + std::string empty_url(""); + check_url_substitution(node, empty_url, empty_url, g_camera_name); +} + +TEST(UrlSubstitution, invalidVariables) +{ + ros::NodeHandle node; + std::string name_url; + + // missing "{...}" + name_url = "file:///tmp/$NAME.yaml"; + check_url_substitution(node, name_url, name_url, g_camera_name); + + // invalid substitution variable name + name_url = "file:///tmp/${INVALID}/calibration.yaml"; + check_url_substitution(node, name_url, name_url, g_camera_name); + + // truncated substitution variable + name_url = "file:///tmp/${NAME"; + check_url_substitution(node, name_url, name_url, g_camera_name); + + // missing substitution variable + name_url = "file:///tmp/${}"; + check_url_substitution(node, name_url, name_url, g_camera_name); + + // no exception thrown for single "$" at end of string + name_url = "file:///$"; + check_url_substitution(node, name_url, name_url, g_camera_name); +} + +// Run all the tests that were declared with TEST() +int main(int argc, char **argv) +{ + ros::init(argc, argv, "camera_info_manager_unit_test"); + testing::InitGoogleTest(&argc, argv); + + // create asynchronous thread for handling service requests + ros::AsyncSpinner spinner(1); + spinner.start(); + + // run the tests in this thread + return RUN_ALL_TESTS(); +} diff --git a/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/unit_test.test b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/unit_test.test new file mode 100644 index 0000000000000000000000000000000000000000..e70b5736d32faf0470e3bdc12ebe50f477c50897 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/camera_info_manager/tests/unit_test.test @@ -0,0 +1,17 @@ +<!-- -*- mode: XML -*- --> +<!-- rostest launch file for camera_info_manager + + This unit test uses rostest, because the camera_info_manager + constructor requires a node handle. Apart from needing a ROS + environment, it is completely self-contained. + + $Id$ + --> + +<launch> + + <!-- start unit-test node --> + <test pkg="camera_info_manager" type="unit_test" name="unit_test" + test-name="unit_test" time-limit="2.0" /> + +</launch> diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/.tar b/Robot_Development/catkin_ws/libraries/image_common/image_transport/.tar new file mode 100644 index 0000000000000000000000000000000000000000..adccd66f34fcb50acc674a489808b6f27352e721 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/.tar @@ -0,0 +1,2 @@ +{!!python/unicode 'url': 'https://github.com/ros-gbp/image_common-release/archive/release/kinetic/image_transport/1.11.10-0.tar.gz', + !!python/unicode 'version': image_common-release-release-kinetic-image_transport-1.11.10-0} diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/CHANGELOG.rst b/Robot_Development/catkin_ws/libraries/image_common/image_transport/CHANGELOG.rst new file mode 100644 index 0000000000000000000000000000000000000000..87bfe1642808f76daffcb96f69d385a58b38c51e --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/CHANGELOG.rst @@ -0,0 +1,177 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package image_transport +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1.11.10 (2016-01-19) +-------------------- + +1.11.9 (2016-01-17) +------------------- +* fix linkage in tutorials +* Use $catkin_EXPORTED_TARGETS +* Contributors: Jochen Sprickerhof, Vincent Rabaud + +1.11.8 (2015-11-29) +------------------- + +1.11.7 (2015-07-28) +------------------- + +1.11.6 (2015-07-16) +------------------- + +1.11.5 (2015-05-14) +------------------- +* image_transport: fix CameraSubscriber shutdown (circular shared_ptr ref) + CameraSubscriber uses a private boost::shared_ptr to share an impl object + between copied instances. In CameraSubscriber::CameraSubscriber(), it + handed this shared_ptr to boost::bind() and saved the created wall timer + in the impl object, thus creating a circular reference. The impl object + was therefore never freed. + Fix that by passing a plain pointer to boost::bind(). +* avoid a memory copy for the raw publisher +* add a way to publish an image with only the data pointer +* Make function inline to avoid duplicated names when linking statically +* add plugin examples for the tutorial +* update instructions for catkin +* remove uselessly linked library + fixes `#28 <https://github.com/ros-perception/image_common/issues/28>`_ +* add a tutorial for image_transport +* Contributors: Gary Servin, Max Schwarz, Vincent Rabaud + +1.11.4 (2014-09-21) +------------------- + +1.11.3 (2014-05-19) +------------------- + +1.11.2 (2014-02-13) +------------------- + +1.11.1 (2014-01-26 02:33) +------------------------- + +1.11.0 (2013-07-20 12:23) +------------------------- + +1.10.5 (2014-01-26 02:34) +------------------------- + +1.10.4 (2013-07-20 11:42) +------------------------- +* add Jack as maintainer +* update my email address +* Contributors: Vincent Rabaud + +1.10.3 (2013-02-21 05:33) +------------------------- + +1.10.2 (2013-02-21 04:48) +------------------------- + +1.10.1 (2013-02-21 04:16) +------------------------- + +1.10.0 (2013-01-13) +------------------- +* fix the urls +* use the pluginlib script to remove some warnings +* added license headers to various cpp and h files +* Contributors: Aaron Blasdel, Vincent Rabaud + +1.9.22 (2012-12-16) +------------------- +* get rid of the deprecated class_loader interface +* Contributors: Vincent Rabaud + +1.9.21 (2012-12-14) +------------------- +* CMakeLists.txt clean up +* Updated package.xml file(s) to handle new catkin buildtool_depend + requirement +* Contributors: William Woodall, mirzashah + +1.9.20 (2012-12-04) +------------------- + +1.9.19 (2012-11-08) +------------------- +* add the right link libraries +* Contributors: Vincent Rabaud + +1.9.18 (2012-11-06) +------------------- +* Isolated plugins into their own library to follow new + class_loader/pluginlib guidelines. +* remove the brief attribute +* Contributors: Mirza Shah, Vincent Rabaud + +1.9.17 (2012-10-30 19:32) +------------------------- + +1.9.16 (2012-10-30 09:10) +------------------------- +* add xml file +* Contributors: Vincent Rabaud + +1.9.15 (2012-10-13 08:43) +------------------------- +* fix bad folder/libraries +* Contributors: Vincent Rabaud + +1.9.14 (2012-10-13 01:07) +------------------------- + +1.9.13 (2012-10-06) +------------------- + +1.9.12 (2012-10-04) +------------------- + +1.9.11 (2012-10-02 02:56) +------------------------- + +1.9.10 (2012-10-02 02:42) +------------------------- + +1.9.9 (2012-10-01) +------------------ +* fix dependencies +* Contributors: Vincent Rabaud + +1.9.8 (2012-09-30) +------------------ +* add catkin as a dependency +* comply to the catkin API +* Contributors: Vincent Rabaud + +1.9.7 (2012-09-18 11:39) +------------------------ + +1.9.6 (2012-09-18 11:07) +------------------------ + +1.9.5 (2012-09-13) +------------------ +* install the include directories +* Contributors: Vincent Rabaud + +1.9.4 (2012-09-12 23:37) +------------------------ + +1.9.3 (2012-09-12 20:44) +------------------------ + +1.9.2 (2012-09-10) +------------------ + +1.9.1 (2012-09-07 15:33) +------------------------ +* make the libraries public +* Contributors: Vincent Rabaud + +1.9.0 (2012-09-07 13:03) +------------------------ +* catkinize for Groovy +* Initial image_common stack check-in, containing image_transport. +* Contributors: Vincent Rabaud, gerkey, kwc, mihelich, pmihelich, straszheim, vrabaud diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/CMakeLists.txt b/Robot_Development/catkin_ws/libraries/image_common/image_transport/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6e43f2fd642e41349b6721cbc4f942a0eee0c4d0 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 2.8.3) +project(image_transport) + +find_package(catkin REQUIRED + COMPONENTS + message_filters + pluginlib + rosconsole + roscpp + roslib + sensor_msgs +) + +find_package(Boost REQUIRED) + +catkin_package( + INCLUDE_DIRS include + LIBRARIES ${PROJECT_NAME} + DEPENDS message_filters pluginlib rosconsole roscpp roslib sensor_msgs +) + +include_directories(include ${catkin_INCLUDE_DIRS}) + +# Build libimage_transport +add_library(${PROJECT_NAME} + src/camera_common.cpp + src/camera_publisher.cpp + src/camera_subscriber.cpp + src/image_transport.cpp + src/publisher.cpp + src/single_subscriber_publisher.cpp + src/subscriber.cpp +) +add_dependencies(${PROJECT_NAME} ${catkin_EXPORTED_TARGETS}) +target_link_libraries(${PROJECT_NAME} + ${Boost_LIBRARIES} + ${catkin_LIBRARIES} +) + +# Build libimage_transport_plugins +add_library(${PROJECT_NAME}_plugins src/manifest.cpp src/raw_publisher.cpp) +target_link_libraries(${PROJECT_NAME}_plugins ${PROJECT_NAME}) + +install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_plugins + DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + COMPONENT main +) +install(DIRECTORY include/${PROJECT_NAME}/ + DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +) + +# add two execs +add_executable(republish src/republish.cpp) +target_link_libraries(republish ${PROJECT_NAME}) + +add_executable(list_transports src/list_transports.cpp) +target_link_libraries(list_transports + ${PROJECT_NAME} + ${catkin_LIBRARIES} +) + +install(TARGETS list_transports republish + DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +# add xml file +install(FILES default_plugins.xml + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +) diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/default_plugins.xml b/Robot_Development/catkin_ws/libraries/image_common/image_transport/default_plugins.xml new file mode 100644 index 0000000000000000000000000000000000000000..f3500ecbbed9777682c927a840a55fdb191cc0f9 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/default_plugins.xml @@ -0,0 +1,13 @@ +<library path="lib/libimage_transport_plugins"> + <class name="image_transport/raw_pub" type="image_transport::RawPublisher" base_class_type="image_transport::PublisherPlugin"> + <description> + This is the default publisher. It publishes the Image as-is on the base topic. + </description> + </class> + + <class name="image_transport/raw_sub" type="image_transport::RawSubscriber" base_class_type="image_transport::SubscriberPlugin"> + <description> + This is the default pass-through subscriber for topics of type sensor_msgs/Image. + </description> + </class> +</library> diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_common.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_common.h new file mode 100644 index 0000000000000000000000000000000000000000..f4c7745a2e6c1a9c66fac1c42117471a2707ba12 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_common.h @@ -0,0 +1,47 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_CAMERA_COMMON_H +#define IMAGE_TRANSPORT_CAMERA_COMMON_H + +#include <string> + +namespace image_transport { + +/// \brief Form the camera info topic name, sibling to the base topic +std::string getCameraInfoTopic(const std::string& base_topic); + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_publisher.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_publisher.h new file mode 100644 index 0000000000000000000000000000000000000000..222e68aef6a4b8c6446521d98281a2252256a505 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_publisher.h @@ -0,0 +1,135 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_CAMERA_PUBLISHER_H +#define IMAGE_TRANSPORT_CAMERA_PUBLISHER_H + +#include <ros/ros.h> +#include <sensor_msgs/Image.h> +#include <sensor_msgs/CameraInfo.h> +#include "image_transport/single_subscriber_publisher.h" + +namespace image_transport { + +class ImageTransport; + +/** + * \brief Manages advertisements for publishing camera images. + * + * CameraPublisher is a convenience class for publishing synchronized image and + * camera info topics using the standard topic naming convention, where the info + * topic name is "camera_info" in the same namespace as the base image topic. + * + * On the client side, CameraSubscriber simplifies subscribing to camera images. + * + * A CameraPublisher should always be created through a call to + * ImageTransport::advertiseCamera(), or copied from one that was. + * Once all copies of a specific CameraPublisher go out of scope, any subscriber callbacks + * associated with that handle will stop being called. Once all CameraPublisher for a + * given base topic go out of scope the topic (and all subtopics) will be unadvertised. + */ +class CameraPublisher +{ +public: + CameraPublisher() {} + + /*! + * \brief Returns the number of subscribers that are currently connected to + * this CameraPublisher. + * + * Returns max(image topic subscribers, info topic subscribers). + */ + uint32_t getNumSubscribers() const; + + /*! + * \brief Returns the base (image) topic of this CameraPublisher. + */ + std::string getTopic() const; + + /** + * \brief Returns the camera info topic of this CameraPublisher. + */ + std::string getInfoTopic() const; + + /*! + * \brief Publish an (image, info) pair on the topics associated with this CameraPublisher. + */ + void publish(const sensor_msgs::Image& image, const sensor_msgs::CameraInfo& info) const; + + /*! + * \brief Publish an (image, info) pair on the topics associated with this CameraPublisher. + */ + void publish(const sensor_msgs::ImageConstPtr& image, + const sensor_msgs::CameraInfoConstPtr& info) const; + + /*! + * \brief Publish an (image, info) pair with given timestamp on the topics associated with + * this CameraPublisher. + * + * Convenience version, which sets the timestamps of both image and info to stamp before + * publishing. + */ + void publish(sensor_msgs::Image& image, sensor_msgs::CameraInfo& info, ros::Time stamp) const; + + /*! + * \brief Shutdown the advertisements associated with this Publisher. + */ + void shutdown(); + + operator void*() const; + bool operator< (const CameraPublisher& rhs) const { return impl_ < rhs.impl_; } + bool operator!=(const CameraPublisher& rhs) const { return impl_ != rhs.impl_; } + bool operator==(const CameraPublisher& rhs) const { return impl_ == rhs.impl_; } + +private: + CameraPublisher(ImageTransport& image_it, ros::NodeHandle& info_nh, + const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& image_connect_cb, + const SubscriberStatusCallback& image_disconnect_cb, + const ros::SubscriberStatusCallback& info_connect_cb, + const ros::SubscriberStatusCallback& info_disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch); + + struct Impl; + typedef boost::shared_ptr<Impl> ImplPtr; + typedef boost::weak_ptr<Impl> ImplWPtr; + + ImplPtr impl_; + + friend class ImageTransport; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_subscriber.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_subscriber.h new file mode 100644 index 0000000000000000000000000000000000000000..aef447d94e6aedec5509b94ba7eb660efbe6b411 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/camera_subscriber.h @@ -0,0 +1,118 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_CAMERA_SUBSCRIBER_H +#define IMAGE_TRANSPORT_CAMERA_SUBSCRIBER_H + +#include <ros/ros.h> +#include <sensor_msgs/CameraInfo.h> +#include <sensor_msgs/Image.h> +#include "image_transport/transport_hints.h" + +namespace image_transport { + +class ImageTransport; + +/** + * \brief Manages a subscription callback on synchronized Image and CameraInfo topics. + * + * CameraSubscriber is the client-side counterpart to CameraPublisher, and assumes the + * same topic naming convention. The callback is of type: +\verbatim +void callback(const sensor_msgs::ImageConstPtr&, const sensor_msgs::CameraInfoConstPtr&); +\endverbatim + * + * A CameraSubscriber should always be created through a call to + * ImageTransport::subscribeCamera(), or copied from one that was. + * Once all copies of a specific CameraSubscriber go out of scope, the subscription callback + * associated with that handle will stop being called. Once all CameraSubscriber for a given + * topic go out of scope the topic will be unsubscribed. + */ +class CameraSubscriber +{ +public: + typedef boost::function<void(const sensor_msgs::ImageConstPtr&, + const sensor_msgs::CameraInfoConstPtr&)> Callback; + + CameraSubscriber() {} + + /** + * \brief Get the base topic (on which the raw image is published). + */ + std::string getTopic() const; + + /** + * \brief Get the camera info topic. + */ + std::string getInfoTopic() const; + + /** + * \brief Returns the number of publishers this subscriber is connected to. + */ + uint32_t getNumPublishers() const; + + /** + * \brief Returns the name of the transport being used. + */ + std::string getTransport() const; + + /** + * \brief Unsubscribe the callback associated with this CameraSubscriber. + */ + void shutdown(); + + operator void*() const; + bool operator< (const CameraSubscriber& rhs) const { return impl_ < rhs.impl_; } + bool operator!=(const CameraSubscriber& rhs) const { return impl_ != rhs.impl_; } + bool operator==(const CameraSubscriber& rhs) const { return impl_ == rhs.impl_; } + +private: + CameraSubscriber(ImageTransport& image_it, ros::NodeHandle& info_nh, + const std::string& base_topic, uint32_t queue_size, + const Callback& callback, + const ros::VoidPtr& tracked_object = ros::VoidPtr(), + const TransportHints& transport_hints = TransportHints()); + + struct Impl; + typedef boost::shared_ptr<Impl> ImplPtr; + typedef boost::weak_ptr<Impl> ImplWPtr; + + ImplPtr impl_; + + friend class ImageTransport; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/exception.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/exception.h new file mode 100644 index 0000000000000000000000000000000000000000..1b3e2f928c88c97ec93e69b71b41634ae25345ae --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/exception.h @@ -0,0 +1,71 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_EXCEPTION_H +#define IMAGE_TRANSPORT_EXCEPTION_H + +#include <stdexcept> + +namespace image_transport { + +/** + * \brief A base class for all image_transport exceptions inheriting from std::runtime_error. + */ +class Exception : public std::runtime_error +{ +public: + Exception(const std::string& message) : std::runtime_error(message) {} +}; + +/** + * \brief An exception class thrown when image_transport is unable to load a requested transport. + */ +class TransportLoadException : public Exception +{ +public: + TransportLoadException(const std::string& transport, const std::string& message) + : Exception("Unable to load plugin for transport '" + transport + "', error string:\n" + message), + transport_(transport.c_str()) + { + } + + std::string getTransport() const { return transport_; } + +protected: + const char* transport_; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/image_transport.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/image_transport.h new file mode 100644 index 0000000000000000000000000000000000000000..195799982eef75fb2e535e174398c8c2bd56a083 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/image_transport.h @@ -0,0 +1,204 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_IMAGE_TRANSPORT_H +#define IMAGE_TRANSPORT_IMAGE_TRANSPORT_H + +#include "image_transport/publisher.h" +#include "image_transport/subscriber.h" +#include "image_transport/camera_publisher.h" +#include "image_transport/camera_subscriber.h" + +namespace image_transport { + +/** + * \brief Advertise and subscribe to image topics. + * + * ImageTransport is analogous to ros::NodeHandle in that it contains advertise() and + * subscribe() functions for creating advertisements and subscriptions of image topics. + */ +class ImageTransport +{ +public: + explicit ImageTransport(const ros::NodeHandle& nh); + + ~ImageTransport(); + + /*! + * \brief Advertise an image topic, simple version. + */ + Publisher advertise(const std::string& base_topic, uint32_t queue_size, bool latch = false); + + /*! + * \brief Advertise an image topic with subcriber status callbacks. + */ + Publisher advertise(const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& connect_cb, + const SubscriberStatusCallback& disconnect_cb = SubscriberStatusCallback(), + const ros::VoidPtr& tracked_object = ros::VoidPtr(), bool latch = false); + + /** + * \brief Subscribe to an image topic, version for arbitrary boost::function object. + */ + Subscriber subscribe(const std::string& base_topic, uint32_t queue_size, + const boost::function<void(const sensor_msgs::ImageConstPtr&)>& callback, + const ros::VoidPtr& tracked_object = ros::VoidPtr(), + const TransportHints& transport_hints = TransportHints()); + + /** + * \brief Subscribe to an image topic, version for bare function. + */ + Subscriber subscribe(const std::string& base_topic, uint32_t queue_size, + void(*fp)(const sensor_msgs::ImageConstPtr&), + const TransportHints& transport_hints = TransportHints()) + { + return subscribe(base_topic, queue_size, + boost::function<void(const sensor_msgs::ImageConstPtr&)>(fp), + ros::VoidPtr(), transport_hints); + } + + /** + * \brief Subscribe to an image topic, version for class member function with bare pointer. + */ + template<class T> + Subscriber subscribe(const std::string& base_topic, uint32_t queue_size, + void(T::*fp)(const sensor_msgs::ImageConstPtr&), T* obj, + const TransportHints& transport_hints = TransportHints()) + { + return subscribe(base_topic, queue_size, boost::bind(fp, obj, _1), ros::VoidPtr(), transport_hints); + } + + /** + * \brief Subscribe to an image topic, version for class member function with shared_ptr. + */ + template<class T> + Subscriber subscribe(const std::string& base_topic, uint32_t queue_size, + void(T::*fp)(const sensor_msgs::ImageConstPtr&), + const boost::shared_ptr<T>& obj, + const TransportHints& transport_hints = TransportHints()) + { + return subscribe(base_topic, queue_size, boost::bind(fp, obj.get(), _1), obj, transport_hints); + } + + /*! + * \brief Advertise a synchronized camera raw image + info topic pair, simple version. + */ + CameraPublisher advertiseCamera(const std::string& base_topic, uint32_t queue_size, bool latch = false); + + /*! + * \brief Advertise a synchronized camera raw image + info topic pair with subscriber status + * callbacks. + */ + CameraPublisher advertiseCamera(const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& image_connect_cb, + const SubscriberStatusCallback& image_disconnect_cb = SubscriberStatusCallback(), + const ros::SubscriberStatusCallback& info_connect_cb = ros::SubscriberStatusCallback(), + const ros::SubscriberStatusCallback& info_disconnect_cb = ros::SubscriberStatusCallback(), + const ros::VoidPtr& tracked_object = ros::VoidPtr(), bool latch = false); + + /** + * \brief Subscribe to a synchronized image & camera info topic pair, version for arbitrary + * boost::function object. + * + * This version assumes the standard topic naming scheme, where the info topic is + * named "camera_info" in the same namespace as the base image topic. + */ + CameraSubscriber subscribeCamera(const std::string& base_topic, uint32_t queue_size, + const CameraSubscriber::Callback& callback, + const ros::VoidPtr& tracked_object = ros::VoidPtr(), + const TransportHints& transport_hints = TransportHints()); + + /** + * \brief Subscribe to a synchronized image & camera info topic pair, version for bare function. + */ + CameraSubscriber subscribeCamera(const std::string& base_topic, uint32_t queue_size, + void(*fp)(const sensor_msgs::ImageConstPtr&, + const sensor_msgs::CameraInfoConstPtr&), + const TransportHints& transport_hints = TransportHints()) + { + return subscribeCamera(base_topic, queue_size, CameraSubscriber::Callback(fp), ros::VoidPtr(), + transport_hints); + } + + /** + * \brief Subscribe to a synchronized image & camera info topic pair, version for class member + * function with bare pointer. + */ + template<class T> + CameraSubscriber subscribeCamera(const std::string& base_topic, uint32_t queue_size, + void(T::*fp)(const sensor_msgs::ImageConstPtr&, + const sensor_msgs::CameraInfoConstPtr&), T* obj, + const TransportHints& transport_hints = TransportHints()) + { + return subscribeCamera(base_topic, queue_size, boost::bind(fp, obj, _1, _2), ros::VoidPtr(), + transport_hints); + } + + /** + * \brief Subscribe to a synchronized image & camera info topic pair, version for class member + * function with shared_ptr. + */ + template<class T> + CameraSubscriber subscribeCamera(const std::string& base_topic, uint32_t queue_size, + void(T::*fp)(const sensor_msgs::ImageConstPtr&, + const sensor_msgs::CameraInfoConstPtr&), + const boost::shared_ptr<T>& obj, + const TransportHints& transport_hints = TransportHints()) + { + return subscribeCamera(base_topic, queue_size, boost::bind(fp, obj.get(), _1, _2), obj, + transport_hints); + } + + /** + * \brief Returns the names of all transports declared in the system. Declared + * transports are not necessarily built or loadable. + */ + std::vector<std::string> getDeclaredTransports() const; + + /** + * \brief Returns the names of all transports that are loadable in the system. + */ + std::vector<std::string> getLoadableTransports() const; + +private: + struct Impl; + typedef boost::shared_ptr<Impl> ImplPtr; + typedef boost::weak_ptr<Impl> ImplWPtr; + + ImplPtr impl_; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/loader_fwds.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/loader_fwds.h new file mode 100644 index 0000000000000000000000000000000000000000..2d2dd311f4ad8be9c459315c2ee70dd020c7ace4 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/loader_fwds.h @@ -0,0 +1,56 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_LOADER_FWDS_H +#define IMAGE_TRANSPORT_LOADER_FWDS_H + +// Forward-declare some classes most users shouldn't care about so that +// image_transport.h doesn't bring them in. + +namespace pluginlib { + template<class T> class ClassLoader; +} + +namespace image_transport { + class PublisherPlugin; + class SubscriberPlugin; + + typedef pluginlib::ClassLoader<PublisherPlugin> PubLoader; + typedef boost::shared_ptr<PubLoader> PubLoaderPtr; + + typedef pluginlib::ClassLoader<SubscriberPlugin> SubLoader; + typedef boost::shared_ptr<SubLoader> SubLoaderPtr; +} + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/publisher.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/publisher.h new file mode 100644 index 0000000000000000000000000000000000000000..593e56a5ea58e135a9541843cefe32acb3467691 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/publisher.h @@ -0,0 +1,125 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_PUBLISHER_H +#define IMAGE_TRANSPORT_PUBLISHER_H + +#include <ros/ros.h> +#include <sensor_msgs/Image.h> +#include "image_transport/single_subscriber_publisher.h" +#include "image_transport/exception.h" +#include "image_transport/loader_fwds.h" + +namespace image_transport { + +/** + * \brief Manages advertisements of multiple transport options on an Image topic. + * + * Publisher is a drop-in replacement for ros::Publisher when publishing + * Image topics. In a minimally built environment, they behave the same; however, + * Publisher is extensible via plugins to publish alternative representations of + * the image on related subtopics. This is especially useful for limiting bandwidth and + * latency over a network connection, when you might (for example) use the theora plugin + * to transport the images as streamed video. All topics are published only on demand + * (i.e. if there are subscribers). + * + * A Publisher should always be created through a call to ImageTransport::advertise(), + * or copied from one that was. + * Once all copies of a specific Publisher go out of scope, any subscriber callbacks + * associated with that handle will stop being called. Once all Publisher for a + * given base topic go out of scope the topic (and all subtopics) will be unadvertised. + */ +class Publisher +{ +public: + Publisher() {} + + /*! + * \brief Returns the number of subscribers that are currently connected to + * this Publisher. + * + * Returns the total number of subscribers to all advertised topics. + */ + uint32_t getNumSubscribers() const; + + /*! + * \brief Returns the base topic of this Publisher. + */ + std::string getTopic() const; + + /*! + * \brief Publish an image on the topics associated with this Publisher. + */ + void publish(const sensor_msgs::Image& message) const; + + /*! + * \brief Publish an image on the topics associated with this Publisher. + */ + void publish(const sensor_msgs::ImageConstPtr& message) const; + + /*! + * \brief Shutdown the advertisements associated with this Publisher. + */ + void shutdown(); + + operator void*() const; + bool operator< (const Publisher& rhs) const { return impl_ < rhs.impl_; } + bool operator!=(const Publisher& rhs) const { return impl_ != rhs.impl_; } + bool operator==(const Publisher& rhs) const { return impl_ == rhs.impl_; } + +private: + Publisher(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& connect_cb, + const SubscriberStatusCallback& disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch, + const PubLoaderPtr& loader); + + struct Impl; + typedef boost::shared_ptr<Impl> ImplPtr; + typedef boost::weak_ptr<Impl> ImplWPtr; + + ImplPtr impl_; + + static void weakSubscriberCb(const ImplWPtr& impl_wptr, + const SingleSubscriberPublisher& plugin_pub, + const SubscriberStatusCallback& user_cb); + + SubscriberStatusCallback rebindCB(const SubscriberStatusCallback& user_cb); + + friend class ImageTransport; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/publisher_plugin.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/publisher_plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..cc9c08692eb9f04a388bbb070fa29036c2820f97 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/publisher_plugin.h @@ -0,0 +1,150 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_PUBLISHER_PLUGIN_H +#define IMAGE_TRANSPORT_PUBLISHER_PLUGIN_H + +#include <ros/ros.h> +#include <sensor_msgs/Image.h> +#include "image_transport/single_subscriber_publisher.h" + +namespace image_transport { + +/** + * \brief Base class for plugins to Publisher. + */ +class PublisherPlugin : boost::noncopyable +{ +public: + virtual ~PublisherPlugin() {} + + /** + * \brief Get a string identifier for the transport provided by + * this plugin. + */ + virtual std::string getTransportName() const = 0; + + /** + * \brief Advertise a topic, simple version. + */ + void advertise(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + bool latch = true) + { + advertiseImpl(nh, base_topic, queue_size, SubscriberStatusCallback(), + SubscriberStatusCallback(), ros::VoidPtr(), latch); + } + + /** + * \brief Advertise a topic with subscriber status callbacks. + */ + void advertise(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& connect_cb, + const SubscriberStatusCallback& disconnect_cb = SubscriberStatusCallback(), + const ros::VoidPtr& tracked_object = ros::VoidPtr(), bool latch = true) + { + advertiseImpl(nh, base_topic, queue_size, connect_cb, disconnect_cb, tracked_object, latch); + } + + /** + * \brief Returns the number of subscribers that are currently connected to + * this PublisherPlugin. + */ + virtual uint32_t getNumSubscribers() const = 0; + + /** + * \brief Returns the communication topic that this PublisherPlugin will publish on. + */ + virtual std::string getTopic() const = 0; + + /** + * \brief Publish an image using the transport associated with this PublisherPlugin. + */ + virtual void publish(const sensor_msgs::Image& message) const = 0; + + /** + * \brief Publish an image using the transport associated with this PublisherPlugin. + */ + virtual void publish(const sensor_msgs::ImageConstPtr& message) const + { + publish(*message); + } + + /** + * \brief Publish an image using the transport associated with this PublisherPlugin. + * This version of the function can be used to optimize cases where you don't want to + * fill a ROS message first to avoid useless copies. + * @param message an image message to use information from (but not data) + * @param data a pointer to the image data to use to fill the Image message + */ + virtual void publish(const sensor_msgs::Image& message, const uint8_t* data) const + { + sensor_msgs::Image msg; + msg.header = message.header; + msg.height = message.height; + msg.width = message.width; + msg.encoding = message.encoding; + msg.is_bigendian = message.is_bigendian; + msg.step = message.step; + msg.data = std::vector<uint8_t>(data, data + msg.step*msg.height); + + publish(msg); + } + + /** + * \brief Shutdown any advertisements associated with this PublisherPlugin. + */ + virtual void shutdown() = 0; + + /** + * \brief Return the lookup name of the PublisherPlugin associated with a specific + * transport identifier. + */ + static std::string getLookupName(const std::string& transport_name) + { + return "image_transport/" + transport_name + "_pub"; + } + +protected: + /** + * \brief Advertise a topic. Must be implemented by the subclass. + */ + virtual void advertiseImpl(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& connect_cb, + const SubscriberStatusCallback& disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch) = 0; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/raw_publisher.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/raw_publisher.h new file mode 100644 index 0000000000000000000000000000000000000000..4ba36e3fa4fd49efbf37800f179f76b9ab9e7222 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/raw_publisher.h @@ -0,0 +1,82 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_RAW_PUBLISHER_H +#define IMAGE_TRANSPORT_RAW_PUBLISHER_H + +#include "image_transport/simple_publisher_plugin.h" + +namespace image_transport { + +/** + * \brief The default PublisherPlugin. + * + * RawPublisher is a simple wrapper for ros::Publisher, publishing unaltered Image + * messages on the base topic. + */ +class RawPublisher : public SimplePublisherPlugin<sensor_msgs::Image> +{ +public: + virtual ~RawPublisher() {} + + virtual std::string getTransportName() const + { + return "raw"; + } + + // Override the default implementation because publishing the message pointer allows + // the no-copy intraprocess optimization. + virtual void publish(const sensor_msgs::ImageConstPtr& message) const + { + getPublisher().publish(message); + } + + // Override the default implementation to not copy data to a sensor_msgs::Image first + virtual void publish(const sensor_msgs::Image& message, const uint8_t* data) const; + +protected: + virtual void publish(const sensor_msgs::Image& message, const PublishFn& publish_fn) const + { + publish_fn(message); + } + + virtual std::string getTopicToAdvertise(const std::string& base_topic) const + { + return base_topic; + } +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/raw_subscriber.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/raw_subscriber.h new file mode 100644 index 0000000000000000000000000000000000000000..824119166fb902d1dd3b87f5dbfe9d202d70c982 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/raw_subscriber.h @@ -0,0 +1,72 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_RAW_SUBSCRIBER_H +#define IMAGE_TRANSPORT_RAW_SUBSCRIBER_H + +#include "image_transport/simple_subscriber_plugin.h" + +namespace image_transport { + +/** + * \brief The default SubscriberPlugin. + * + * RawSubscriber is a simple wrapper for ros::Subscriber which listens for Image messages + * and passes them through to the callback. + */ +class RawSubscriber : public SimpleSubscriberPlugin<sensor_msgs::Image> +{ +public: + virtual ~RawSubscriber() {} + + virtual std::string getTransportName() const + { + return "raw"; + } + +protected: + virtual void internalCallback(const sensor_msgs::ImageConstPtr& message, const Callback& user_cb) + { + user_cb(message); + } + + virtual std::string getTopicToSubscribe(const std::string& base_topic) const + { + return base_topic; + } +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/simple_publisher_plugin.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/simple_publisher_plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..691d2ed537ed086db075a20c09b2fe5549ec5179 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/simple_publisher_plugin.h @@ -0,0 +1,240 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_SIMPLE_PUBLISHER_PLUGIN_H +#define IMAGE_TRANSPORT_SIMPLE_PUBLISHER_PLUGIN_H + +#include "image_transport/publisher_plugin.h" +#include <boost/scoped_ptr.hpp> + +namespace image_transport { + +/** + * \brief Base class to simplify implementing most plugins to Publisher. + * + * This base class vastly simplifies implementing a PublisherPlugin in the common + * case that all communication with the matching SubscriberPlugin happens over a + * single ROS topic using a transport-specific message type. SimplePublisherPlugin + * is templated on the transport-specific message type. + * + * A subclass need implement only two methods: + * - getTransportName() from PublisherPlugin + * - publish() with an extra PublishFn argument + * + * For access to the parameter server and name remappings, use nh(). + * + * getTopicToAdvertise() controls the name of the internal communication topic. + * It defaults to \<base topic\>/\<transport name\>. + */ +template <class M> +class SimplePublisherPlugin : public PublisherPlugin +{ +public: + virtual ~SimplePublisherPlugin() {} + + virtual uint32_t getNumSubscribers() const + { + if (simple_impl_) return simple_impl_->pub_.getNumSubscribers(); + return 0; + } + + virtual std::string getTopic() const + { + if (simple_impl_) return simple_impl_->pub_.getTopic(); + return std::string(); + } + + virtual void publish(const sensor_msgs::Image& message) const + { + if (!simple_impl_ || !simple_impl_->pub_) { + ROS_ASSERT_MSG(false, "Call to publish() on an invalid image_transport::SimplePublisherPlugin"); + return; + } + + publish(message, bindInternalPublisher(simple_impl_->pub_)); + } + + virtual void shutdown() + { + if (simple_impl_) simple_impl_->pub_.shutdown(); + } + +protected: + virtual void advertiseImpl(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& user_connect_cb, + const SubscriberStatusCallback& user_disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch) + { + std::string transport_topic = getTopicToAdvertise(base_topic); + ros::NodeHandle param_nh(transport_topic); + simple_impl_.reset(new SimplePublisherPluginImpl(param_nh)); + simple_impl_->pub_ = nh.advertise<M>(transport_topic, queue_size, + bindCB(user_connect_cb, &SimplePublisherPlugin::connectCallback), + bindCB(user_disconnect_cb, &SimplePublisherPlugin::disconnectCallback), + tracked_object, latch); + } + + //! Generic function for publishing the internal message type. + typedef boost::function<void(const M&)> PublishFn; + + /** + * \brief Publish an image using the specified publish function. Must be implemented by + * the subclass. + * + * The PublishFn publishes the transport-specific message type. This indirection allows + * SimpleSubscriberPlugin to use this function for both normal broadcast publishing and + * single subscriber publishing (in subscription callbacks). + */ + virtual void publish(const sensor_msgs::Image& message, const PublishFn& publish_fn) const = 0; + + /** + * \brief Return the communication topic name for a given base topic. + * + * Defaults to \<base topic\>/\<transport name\>. + */ + virtual std::string getTopicToAdvertise(const std::string& base_topic) const + { + return base_topic + "/" + getTransportName(); + } + + /** + * \brief Function called when a subscriber connects to the internal publisher. + * + * Defaults to noop. + */ + virtual void connectCallback(const ros::SingleSubscriberPublisher& pub) {} + + /** + * \brief Function called when a subscriber disconnects from the internal publisher. + * + * Defaults to noop. + */ + virtual void disconnectCallback(const ros::SingleSubscriberPublisher& pub) {} + + /** + * \brief Returns the ros::NodeHandle to be used for parameter lookup. + */ + const ros::NodeHandle& nh() const + { + return simple_impl_->param_nh_; + } + + /** + * \brief Returns the internal ros::Publisher. + * + * This really only exists so RawPublisher can implement no-copy intraprocess message + * passing easily. + */ + const ros::Publisher& getPublisher() const + { + ROS_ASSERT(simple_impl_); + return simple_impl_->pub_; + } + +private: + struct SimplePublisherPluginImpl + { + SimplePublisherPluginImpl(const ros::NodeHandle& nh) + : param_nh_(nh) + { + } + + const ros::NodeHandle param_nh_; + ros::Publisher pub_; + }; + + boost::scoped_ptr<SimplePublisherPluginImpl> simple_impl_; + + typedef void (SimplePublisherPlugin::*SubscriberStatusMemFn)(const ros::SingleSubscriberPublisher& pub); + + /** + * Binds the user callback to subscriberCB(), which acts as an intermediary to expose + * a publish(Image) interface to the user while publishing to an internal topic. + */ + ros::SubscriberStatusCallback bindCB(const SubscriberStatusCallback& user_cb, + SubscriberStatusMemFn internal_cb_fn) + { + ros::SubscriberStatusCallback internal_cb = boost::bind(internal_cb_fn, this, _1); + if (user_cb) + return boost::bind(&SimplePublisherPlugin::subscriberCB, this, _1, user_cb, internal_cb); + else + return internal_cb; + } + + /** + * Forms the ros::SingleSubscriberPublisher for the internal communication topic into + * an image_transport::SingleSubscriberPublisher for Image messages and passes it + * to the user subscriber status callback. + */ + void subscriberCB(const ros::SingleSubscriberPublisher& ros_ssp, + const SubscriberStatusCallback& user_cb, + const ros::SubscriberStatusCallback& internal_cb) + { + // First call the internal callback (for sending setup headers, etc.) + internal_cb(ros_ssp); + + // Construct a function object for publishing sensor_msgs::Image through the + // subclass-implemented publish() using the ros::SingleSubscriberPublisher to send + // messages of the transport-specific type. + typedef void (SimplePublisherPlugin::*PublishMemFn)(const sensor_msgs::Image&, const PublishFn&) const; + PublishMemFn pub_mem_fn = &SimplePublisherPlugin::publish; + ImagePublishFn image_publish_fn = boost::bind(pub_mem_fn, this, _1, bindInternalPublisher(ros_ssp)); + + SingleSubscriberPublisher ssp(ros_ssp.getSubscriberName(), getTopic(), + boost::bind(&SimplePublisherPlugin::getNumSubscribers, this), + image_publish_fn); + user_cb(ssp); + } + + typedef boost::function<void(const sensor_msgs::Image&)> ImagePublishFn; + + /** + * Returns a function object for publishing the transport-specific message type + * through some ROS publisher type. + * + * @param pub An object with method void publish(const M&) + */ + template <class PubT> + PublishFn bindInternalPublisher(const PubT& pub) const + { + // Bind PubT::publish(const Message&) as PublishFn + typedef void (PubT::*InternalPublishMemFn)(const M&) const; + InternalPublishMemFn internal_pub_mem_fn = &PubT::publish; + return boost::bind(internal_pub_mem_fn, &pub, _1); + } +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/simple_subscriber_plugin.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/simple_subscriber_plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..dd6ea3c7104d40140e151f8863ff5e4e5a87e967 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/simple_subscriber_plugin.h @@ -0,0 +1,141 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_SIMPLE_SUBSCRIBER_PLUGIN_H +#define IMAGE_TRANSPORT_SIMPLE_SUBSCRIBER_PLUGIN_H + +#include "image_transport/subscriber_plugin.h" +#include <boost/scoped_ptr.hpp> + +namespace image_transport { + +/** + * \brief Base class to simplify implementing most plugins to Subscriber. + * + * The base class simplifies implementing a SubscriberPlugin in the common case that + * all communication with the matching PublisherPlugin happens over a single ROS + * topic using a transport-specific message type. SimpleSubscriberPlugin is templated + * on the transport-specific message type. + * + * A subclass need implement only two methods: + * - getTransportName() from SubscriberPlugin + * - internalCallback() - processes a message and invoked the user Image callback if + * appropriate. + * + * For access to the parameter server and name remappings, use nh(). + * + * getTopicToSubscribe() controls the name of the internal communication topic. It + * defaults to \<base topic\>/\<transport name\>. + */ +template <class M> +class SimpleSubscriberPlugin : public SubscriberPlugin +{ +public: + virtual ~SimpleSubscriberPlugin() {} + + virtual std::string getTopic() const + { + if (simple_impl_) return simple_impl_->sub_.getTopic(); + return std::string(); + } + + virtual uint32_t getNumPublishers() const + { + if (simple_impl_) return simple_impl_->sub_.getNumPublishers(); + return 0; + } + + virtual void shutdown() + { + if (simple_impl_) simple_impl_->sub_.shutdown(); + } + +protected: + /** + * \brief Process a message. Must be implemented by the subclass. + * + * @param message A message from the PublisherPlugin. + * @param user_cb The user Image callback to invoke, if appropriate. + */ + virtual void internalCallback(const typename M::ConstPtr& message, const Callback& user_cb) = 0; + + /** + * \brief Return the communication topic name for a given base topic. + * + * Defaults to \<base topic\>/\<transport name\>. + */ + virtual std::string getTopicToSubscribe(const std::string& base_topic) const + { + return base_topic + "/" + getTransportName(); + } + + virtual void subscribeImpl(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const Callback& callback, const ros::VoidPtr& tracked_object, + const TransportHints& transport_hints) + { + // Push each group of transport-specific parameters into a separate sub-namespace + ros::NodeHandle param_nh(transport_hints.getParameterNH(), getTransportName()); + simple_impl_.reset(new SimpleSubscriberPluginImpl(param_nh)); + + simple_impl_->sub_ = nh.subscribe<M>(getTopicToSubscribe(base_topic), queue_size, + boost::bind(&SimpleSubscriberPlugin::internalCallback, this, _1, callback), + tracked_object, transport_hints.getRosHints()); + } + + /** + * \brief Returns the ros::NodeHandle to be used for parameter lookup. + */ + const ros::NodeHandle& nh() const + { + return simple_impl_->param_nh_; + } + +private: + struct SimpleSubscriberPluginImpl + { + SimpleSubscriberPluginImpl(const ros::NodeHandle& nh) + : param_nh_(nh) + { + } + + const ros::NodeHandle param_nh_; + ros::Subscriber sub_; + }; + + boost::scoped_ptr<SimpleSubscriberPluginImpl> simple_impl_; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/single_subscriber_publisher.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/single_subscriber_publisher.h new file mode 100644 index 0000000000000000000000000000000000000000..025a99e36dce2065ff88ce926133318822c15991 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/single_subscriber_publisher.h @@ -0,0 +1,80 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_SINGLE_SUBSCRIBER_PUBLISHER +#define IMAGE_TRANSPORT_SINGLE_SUBSCRIBER_PUBLISHER + +#include <boost/noncopyable.hpp> +#include <boost/function.hpp> +#include <sensor_msgs/Image.h> + +namespace image_transport { + +/** + * \brief Allows publication of an image to a single subscriber. Only available inside + * subscriber connection callbacks. + */ +class SingleSubscriberPublisher : boost::noncopyable +{ +public: + typedef boost::function<uint32_t()> GetNumSubscribersFn; + typedef boost::function<void(const sensor_msgs::Image&)> PublishFn; + + SingleSubscriberPublisher(const std::string& caller_id, const std::string& topic, + const GetNumSubscribersFn& num_subscribers_fn, + const PublishFn& publish_fn); + + std::string getSubscriberName() const; + + std::string getTopic() const; + + uint32_t getNumSubscribers() const; + + void publish(const sensor_msgs::Image& message) const; + void publish(const sensor_msgs::ImageConstPtr& message) const; + +private: + std::string caller_id_; + std::string topic_; + GetNumSubscribersFn num_subscribers_fn_; + PublishFn publish_fn_; + + friend class Publisher; // to get publish_fn_ directly +}; + +typedef boost::function<void(const SingleSubscriberPublisher&)> SubscriberStatusCallback; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber.h new file mode 100644 index 0000000000000000000000000000000000000000..f887d59de33d3ceab943a9d386a69bc18924a54c --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber.h @@ -0,0 +1,111 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_SUBSCRIBER_H +#define IMAGE_TRANSPORT_SUBSCRIBER_H + +#include <ros/ros.h> +#include <sensor_msgs/Image.h> +#include "image_transport/transport_hints.h" +#include "image_transport/exception.h" +#include "image_transport/loader_fwds.h" + +namespace image_transport { + +/** + * \brief Manages a subscription callback on a specific topic that can be interpreted + * as an Image topic. + * + * Subscriber is the client-side counterpart to Publisher. By loading the + * appropriate plugin, it can subscribe to a base image topic using any available + * transport. The complexity of what transport is actually used is hidden from the user, + * who sees only a normal Image callback. + * + * A Subscriber should always be created through a call to ImageTransport::subscribe(), + * or copied from one that was. + * Once all copies of a specific Subscriber go out of scope, the subscription callback + * associated with that handle will stop being called. Once all Subscriber for a given + * topic go out of scope the topic will be unsubscribed. + */ +class Subscriber +{ +public: + Subscriber() {} + + /** + * \brief Returns the base image topic. + * + * The Subscriber may actually be subscribed to some transport-specific topic that + * differs from the base topic. + */ + std::string getTopic() const; + + /** + * \brief Returns the number of publishers this subscriber is connected to. + */ + uint32_t getNumPublishers() const; + + /** + * \brief Returns the name of the transport being used. + */ + std::string getTransport() const; + + /** + * \brief Unsubscribe the callback associated with this Subscriber. + */ + void shutdown(); + + operator void*() const; + bool operator< (const Subscriber& rhs) const { return impl_ < rhs.impl_; } + bool operator!=(const Subscriber& rhs) const { return impl_ != rhs.impl_; } + bool operator==(const Subscriber& rhs) const { return impl_ == rhs.impl_; } + +private: + Subscriber(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const boost::function<void(const sensor_msgs::ImageConstPtr&)>& callback, + const ros::VoidPtr& tracked_object, const TransportHints& transport_hints, + const SubLoaderPtr& loader); + + struct Impl; + typedef boost::shared_ptr<Impl> ImplPtr; + typedef boost::weak_ptr<Impl> ImplWPtr; + + ImplPtr impl_; + + friend class ImageTransport; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber_filter.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..3d5be7bd89f7ecf1997ec77f9448735083375dd1 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber_filter.h @@ -0,0 +1,163 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_SUBSCRIBER_FILTER_H +#define IMAGE_TRANSPORT_SUBSCRIBER_FILTER_H + +#include <ros/ros.h> +#include <message_filters/simple_filter.h> + +#include "image_transport/image_transport.h" + +namespace image_transport { + +/** + * \brief Image subscription filter. + * + * This class wraps Subscriber as a "filter" compatible with the message_filters + * package. It acts as a highest-level filter, simply passing messages from an image + * transport subscription through to the filters which have connected to it. + * + * When this object is destroyed it will unsubscribe from the ROS subscription. + * + * \section connections CONNECTIONS + * + * SubscriberFilter has no input connection. + * + * The output connection for the SubscriberFilter object is the same signature as for roscpp + * subscription callbacks, ie. +\verbatim +void callback(const boost::shared_ptr<const sensor_msgs::Image>&); +\endverbatim + */ +class SubscriberFilter : public message_filters::SimpleFilter<sensor_msgs::Image> +{ +public: + /** + * \brief Constructor + * + * See the ros::NodeHandle::subscribe() variants for more information on the parameters + * + * \param nh The ros::NodeHandle to use to subscribe. + * \param base_topic The topic to subscribe to. + * \param queue_size The subscription queue size + * \param transport_hints The transport hints to pass along + */ + SubscriberFilter(ImageTransport& it, const std::string& base_topic, uint32_t queue_size, + const TransportHints& transport_hints = TransportHints()) + { + subscribe(it, base_topic, queue_size, transport_hints); + } + + /** + * \brief Empty constructor, use subscribe() to subscribe to a topic + */ + SubscriberFilter() + { + } + + ~SubscriberFilter() + { + unsubscribe(); + } + + /** + * \brief Subscribe to a topic. + * + * If this Subscriber is already subscribed to a topic, this function will first unsubscribe. + * + * \param nh The ros::NodeHandle to use to subscribe. + * \param base_topic The topic to subscribe to. + * \param queue_size The subscription queue size + * \param transport_hints The transport hints to pass along + */ + void subscribe(ImageTransport& it, const std::string& base_topic, uint32_t queue_size, + const TransportHints& transport_hints = TransportHints()) + { + unsubscribe(); + + sub_ = it.subscribe(base_topic, queue_size, boost::bind(&SubscriberFilter::cb, this, _1), + ros::VoidPtr(), transport_hints); + } + + /** + * \brief Force immediate unsubscription of this subscriber from its topic + */ + void unsubscribe() + { + sub_.shutdown(); + } + + std::string getTopic() const + { + return sub_.getTopic(); + } + + /** + * \brief Returns the number of publishers this subscriber is connected to. + */ + uint32_t getNumPublishers() const + { + return sub_.getNumPublishers(); + } + + /** + * \brief Returns the name of the transport being used. + */ + std::string getTransport() const + { + return sub_.getTransport(); + } + + /** + * \brief Returns the internal image_transport::Subscriber object. + */ + const Subscriber& getSubscriber() const + { + return sub_; + } + +private: + + void cb(const sensor_msgs::ImageConstPtr& m) + { + signalMessage(m); + } + + Subscriber sub_; +}; + +} + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber_plugin.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber_plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..4601dc9b219569606ef1dcd609f9ccf8821de018 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/subscriber_plugin.h @@ -0,0 +1,141 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_SUBSCRIBER_PLUGIN_H +#define IMAGE_TRANSPORT_SUBSCRIBER_PLUGIN_H + +#include <ros/ros.h> +#include <sensor_msgs/Image.h> +#include <boost/noncopyable.hpp> +#include "image_transport/transport_hints.h" + +namespace image_transport { + +/** + * \brief Base class for plugins to Subscriber. + */ +class SubscriberPlugin : boost::noncopyable +{ +public: + typedef boost::function<void(const sensor_msgs::ImageConstPtr&)> Callback; + + virtual ~SubscriberPlugin() {} + + /** + * \brief Get a string identifier for the transport provided by + * this plugin. + */ + virtual std::string getTransportName() const = 0; + + /** + * \brief Subscribe to an image topic, version for arbitrary boost::function object. + */ + void subscribe(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const Callback& callback, const ros::VoidPtr& tracked_object = ros::VoidPtr(), + const TransportHints& transport_hints = TransportHints()) + { + return subscribeImpl(nh, base_topic, queue_size, callback, tracked_object, transport_hints); + } + + /** + * \brief Subscribe to an image topic, version for bare function. + */ + void subscribe(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + void(*fp)(const sensor_msgs::ImageConstPtr&), + const TransportHints& transport_hints = TransportHints()) + { + return subscribe(nh, base_topic, queue_size, + boost::function<void(const sensor_msgs::ImageConstPtr&)>(fp), + ros::VoidPtr(), transport_hints); + } + + /** + * \brief Subscribe to an image topic, version for class member function with bare pointer. + */ + template<class T> + void subscribe(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + void(T::*fp)(const sensor_msgs::ImageConstPtr&), T* obj, + const TransportHints& transport_hints = TransportHints()) + { + return subscribe(nh, base_topic, queue_size, boost::bind(fp, obj, _1), ros::VoidPtr(), transport_hints); + } + + /** + * \brief Subscribe to an image topic, version for class member function with shared_ptr. + */ + template<class T> + void subscribe(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + void(T::*fp)(const sensor_msgs::ImageConstPtr&), + const boost::shared_ptr<T>& obj, + const TransportHints& transport_hints = TransportHints()) + { + return subscribe(nh, base_topic, queue_size, boost::bind(fp, obj.get(), _1), obj, transport_hints); + } + + /** + * \brief Get the transport-specific communication topic. + */ + virtual std::string getTopic() const = 0; + + /** + * \brief Returns the number of publishers this subscriber is connected to. + */ + virtual uint32_t getNumPublishers() const = 0; + + /** + * \brief Unsubscribe the callback associated with this SubscriberPlugin. + */ + virtual void shutdown() = 0; + + /** + * \brief Return the lookup name of the SubscriberPlugin associated with a specific + * transport identifier. + */ + static std::string getLookupName(const std::string& transport_type) + { + return "image_transport/" + transport_type + "_sub"; + } + +protected: + /** + * \brief Subscribe to an image transport topic. Must be implemented by the subclass. + */ + virtual void subscribeImpl(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const Callback& callback, const ros::VoidPtr& tracked_object, + const TransportHints& transport_hints) = 0; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/transport_hints.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/transport_hints.h new file mode 100644 index 0000000000000000000000000000000000000000..1524d1804db32401f959f1c6d3c7188bd6f2776b --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/include/image_transport/transport_hints.h @@ -0,0 +1,94 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#ifndef IMAGE_TRANSPORT_TRANSPORT_HINTS_H +#define IMAGE_TRANSPORT_TRANSPORT_HINTS_H + +#include <ros/ros.h> + +namespace image_transport { + +/** + * \brief Stores transport settings for an image topic subscription. + */ +class TransportHints +{ +public: + /** + * \brief Constructor. + * + * The default transport can be overridden by setting a certain parameter to the + * name of the desired transport. By default this parameter is named "image_transport" + * in the node's local namespace. For consistency across ROS applications, the + * name of this parameter should not be changed without good reason. + * + * @param default_transport Preferred transport to use + * @param ros_hints Hints to pass through to ROS subscriptions + * @param parameter_nh Node handle to use when looking up the transport parameter. + * Defaults to the local namespace. + * @param parameter_name The name of the transport parameter + */ + TransportHints(const std::string& default_transport = "raw", + const ros::TransportHints& ros_hints = ros::TransportHints(), + const ros::NodeHandle& parameter_nh = ros::NodeHandle("~"), + const std::string& parameter_name = "image_transport") + : ros_hints_(ros_hints), parameter_nh_(parameter_nh) + { + parameter_nh_.param(parameter_name, transport_, default_transport); + } + + const std::string& getTransport() const + { + return transport_; + } + + const ros::TransportHints& getRosHints() const + { + return ros_hints_; + } + + const ros::NodeHandle& getParameterNH() const + { + return parameter_nh_; + } + +private: + std::string transport_; + ros::TransportHints ros_hints_; + ros::NodeHandle parameter_nh_; +}; + +} //namespace image_transport + +#endif diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/mainpage.dox b/Robot_Development/catkin_ws/libraries/image_common/image_transport/mainpage.dox new file mode 100644 index 0000000000000000000000000000000000000000..2df6f5b5f32fdd4d82eb056e2290580b2351cd1f --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/mainpage.dox @@ -0,0 +1,45 @@ +/** +\mainpage +\htmlinclude manifest.html + +\section codeapi Code API +When transporting images, you should use image_transport's classes as drop-in +replacements for ros::Publisher and ros::Subscriber. +- image_transport::ImageTransport - use this to create a Publisher or Subscriber +- image_transport::Publisher - manage advertisements for an image topic, using all available transport options +- image_transport::Subscriber - manage an Image subscription callback using a particular transport + +Camera drivers publish a "camera_info" sibling topic containing important metadata on how to +interpret an image for vision applications. image_transport included helper classes to +publish (image, info) message pairs and re-synchronize them on the client side: +- image_transport::CameraPublisher - manage advertisements for camera images +- image_transport::CameraSubscriber - manage a single subscription callback to synchronized image (using any transport) and CameraInfo topics + +For other synchronization or filtering needs, see the low-level filter class: +- image_transport::SubscriberFilter - a wrapper for image_transport::Subscriber compatible with message_filters + +\subsection writing_plugin Writing a plugin +If you are an advanced user implementing your own image transport option, you will need to +implement these base-level interfaces: +- image_transport::PublisherPlugin +- image_transport::SubscriberPlugin + +In the common case that all communication between PublisherPlugin and SubscriberPlugin happens +over a single ROS topic using a transport-specific message type, writing the plugins is vastly +simplified by using these base classes instead: +- image_transport::SimplePublisherPlugin - see image_transport::RawPublisher for a trivial example +- image_transport::SimpleSubscriberPlugin - see image_transport::RawSubscriber for a trivial example + +\section rosapi ROS API + +\subsection pub_sub_rosapi Publishers and Subscribers + +Because they encapsulate complicated communication behavior, image_transport publisher +and subscriber classes have a public ROS API as well as a code API. See the wiki +documentation for details. + +Although image_transport::Publisher may publish many topics, in all code interfaces you should +use only the name of the "base topic." The image transport classes will figure out the name of +the dedicated ROS topic to use for the desired transport. + +*/ diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/package.xml b/Robot_Development/catkin_ws/libraries/image_common/image_transport/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..42fbf98d895b02670e39a509ea7427b8802d573e --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/package.xml @@ -0,0 +1,39 @@ +<package> + <name>image_transport</name> + <version>1.11.10</version> + <description> + + image_transport should always be used to subscribe to and publish images. It provides transparent + support for transporting images in low-bandwidth compressed formats. Examples (provided by separate + plugin packages) include JPEG/PNG compression and Theora streaming video. + + </description> + <author>Patrick Mihelich</author> + <maintainer email="jack.oquin@gmail.com">Jack O'Quin</maintainer> + <maintainer email="vincent.rabaud@gmail.com">Vincent Rabaud</maintainer> + <license>BSD</license> + + <url type="website">http://ros.org/wiki/image_transport</url> + <url type="bugtracker">https://github.com/ros-perception/image_common/issues</url> + <url type="repository">https://github.com/ros-perception/image_common</url> + + <export> + <image_transport plugin="${prefix}/default_plugins.xml" /> + </export> + + <buildtool_depend>catkin</buildtool_depend> + + <build_depend>message_filters</build_depend> + <build_depend>pluginlib</build_depend> + <build_depend>rosconsole</build_depend> + <build_depend>roscpp</build_depend> + <build_depend>roslib</build_depend> + <build_depend>sensor_msgs</build_depend> + + <run_depend>message_filters</run_depend> + <run_depend>pluginlib</run_depend> + <run_depend>rosconsole</run_depend> + <run_depend>roscpp</run_depend> + <run_depend>roslib</run_depend> + <run_depend>sensor_msgs</run_depend> +</package> diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_common.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a09f764b9e52f724962c6041288a83f66110c277 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_common.cpp @@ -0,0 +1,58 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/camera_common.h" +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/join.hpp> +#include <vector> + +namespace image_transport { + +std::string getCameraInfoTopic(const std::string& base_topic) +{ + // Split into separate names + std::vector<std::string> names; + boost::algorithm::split(names, base_topic, boost::algorithm::is_any_of("/"), + boost::algorithm::token_compress_on); + // Get rid of empty tokens from trailing slashes + while (names.back().empty()) + names.pop_back(); + // Replace image name with "camera_info" + names.back() = "camera_info"; + // Join back together into topic name + return boost::algorithm::join(names, "/"); +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_publisher.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_publisher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..232905a568d53a2cd717cb735f3c8e12d4ff96d1 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_publisher.cpp @@ -0,0 +1,160 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/image_transport.h" +#include "image_transport/camera_common.h" + +namespace image_transport { + +struct CameraPublisher::Impl +{ + Impl() + : unadvertised_(false) + { + } + + ~Impl() + { + shutdown(); + } + + bool isValid() const + { + return !unadvertised_; + } + + void shutdown() + { + if (!unadvertised_) { + unadvertised_ = true; + image_pub_.shutdown(); + info_pub_.shutdown(); + } + } + + Publisher image_pub_; + ros::Publisher info_pub_; + bool unadvertised_; + //double constructed_; +}; + +CameraPublisher::CameraPublisher(ImageTransport& image_it, ros::NodeHandle& info_nh, + const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& image_connect_cb, + const SubscriberStatusCallback& image_disconnect_cb, + const ros::SubscriberStatusCallback& info_connect_cb, + const ros::SubscriberStatusCallback& info_disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch) + : impl_(new Impl) +{ + // Explicitly resolve name here so we compute the correct CameraInfo topic when the + // image topic is remapped (#4539). + std::string image_topic = info_nh.resolveName(base_topic); + std::string info_topic = getCameraInfoTopic(image_topic); + + impl_->image_pub_ = image_it.advertise(image_topic, queue_size, image_connect_cb, + image_disconnect_cb, tracked_object, latch); + impl_->info_pub_ = info_nh.advertise<sensor_msgs::CameraInfo>(info_topic, queue_size, info_connect_cb, + info_disconnect_cb, tracked_object, latch); +} + +uint32_t CameraPublisher::getNumSubscribers() const +{ + if (impl_ && impl_->isValid()) + return std::max(impl_->image_pub_.getNumSubscribers(), impl_->info_pub_.getNumSubscribers()); + return 0; +} + +std::string CameraPublisher::getTopic() const +{ + if (impl_) return impl_->image_pub_.getTopic(); + return std::string(); +} + +std::string CameraPublisher::getInfoTopic() const +{ + if (impl_) return impl_->info_pub_.getTopic(); + return std::string(); +} + +void CameraPublisher::publish(const sensor_msgs::Image& image, const sensor_msgs::CameraInfo& info) const +{ + if (!impl_ || !impl_->isValid()) { + ROS_ASSERT_MSG(false, "Call to publish() on an invalid image_transport::CameraPublisher"); + return; + } + + impl_->image_pub_.publish(image); + impl_->info_pub_.publish(info); +} + +void CameraPublisher::publish(const sensor_msgs::ImageConstPtr& image, + const sensor_msgs::CameraInfoConstPtr& info) const +{ + if (!impl_ || !impl_->isValid()) { + ROS_ASSERT_MSG(false, "Call to publish() on an invalid image_transport::CameraPublisher"); + return; + } + + impl_->image_pub_.publish(image); + impl_->info_pub_.publish(info); +} + +void CameraPublisher::publish(sensor_msgs::Image& image, sensor_msgs::CameraInfo& info, + ros::Time stamp) const +{ + if (!impl_ || !impl_->isValid()) { + ROS_ASSERT_MSG(false, "Call to publish() on an invalid image_transport::CameraPublisher"); + return; + } + + image.header.stamp = stamp; + info.header.stamp = stamp; + publish(image, info); +} + +void CameraPublisher::shutdown() +{ + if (impl_) { + impl_->shutdown(); + impl_.reset(); + } +} + +CameraPublisher::operator void*() const +{ + return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_subscriber.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_subscriber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a91a14ead5c05d3c7d9b994247735610e7dbf41c --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/camera_subscriber.cpp @@ -0,0 +1,160 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/camera_subscriber.h" +#include "image_transport/subscriber_filter.h" +#include "image_transport/camera_common.h" +#include <message_filters/subscriber.h> +#include <message_filters/time_synchronizer.h> + +inline void increment(int* value) +{ + ++(*value); +} + +namespace image_transport { + +struct CameraSubscriber::Impl +{ + Impl(uint32_t queue_size) + : sync_(queue_size), + unsubscribed_(false), + image_received_(0), info_received_(0), both_received_(0) + {} + + ~Impl() + { + shutdown(); + } + + bool isValid() const + { + return !unsubscribed_; + } + + void shutdown() + { + if (!unsubscribed_) { + unsubscribed_ = true; + image_sub_.unsubscribe(); + info_sub_.unsubscribe(); + } + } + + void checkImagesSynchronized() + { + int threshold = 3 * both_received_; + if (image_received_ > threshold || info_received_ > threshold) { + ROS_WARN_NAMED("sync", // Can suppress ros.image_transport.sync independent of anything else + "[image_transport] Topics '%s' and '%s' do not appear to be synchronized. " + "In the last 10s:\n" + "\tImage messages received: %d\n" + "\tCameraInfo messages received: %d\n" + "\tSynchronized pairs: %d", + image_sub_.getTopic().c_str(), info_sub_.getTopic().c_str(), + image_received_, info_received_, both_received_); + } + image_received_ = info_received_ = both_received_ = 0; + } + + SubscriberFilter image_sub_; + message_filters::Subscriber<sensor_msgs::CameraInfo> info_sub_; + message_filters::TimeSynchronizer<sensor_msgs::Image, sensor_msgs::CameraInfo> sync_; + bool unsubscribed_; + // For detecting when the topics aren't synchronized + ros::WallTimer check_synced_timer_; + int image_received_, info_received_, both_received_; +}; + +CameraSubscriber::CameraSubscriber(ImageTransport& image_it, ros::NodeHandle& info_nh, + const std::string& base_topic, uint32_t queue_size, + const Callback& callback, const ros::VoidPtr& tracked_object, + const TransportHints& transport_hints) + : impl_(new Impl(queue_size)) +{ + // Must explicitly remap the image topic since we then do some string manipulation on it + // to figure out the sibling camera_info topic. + std::string image_topic = info_nh.resolveName(base_topic); + std::string info_topic = getCameraInfoTopic(image_topic); + impl_->image_sub_.subscribe(image_it, image_topic, queue_size, transport_hints); + impl_->info_sub_ .subscribe(info_nh, info_topic, queue_size, transport_hints.getRosHints()); + impl_->sync_.connectInput(impl_->image_sub_, impl_->info_sub_); + // need for Boost.Bind here is kind of broken + impl_->sync_.registerCallback(boost::bind(callback, _1, _2)); + + // Complain every 10s if it appears that the image and info topics are not synchronized + impl_->image_sub_.registerCallback(boost::bind(increment, &impl_->image_received_)); + impl_->info_sub_.registerCallback(boost::bind(increment, &impl_->info_received_)); + impl_->sync_.registerCallback(boost::bind(increment, &impl_->both_received_)); + impl_->check_synced_timer_ = info_nh.createWallTimer(ros::WallDuration(10.0), + boost::bind(&Impl::checkImagesSynchronized, impl_.get())); +} + +std::string CameraSubscriber::getTopic() const +{ + if (impl_) return impl_->image_sub_.getTopic(); + return std::string(); +} + +std::string CameraSubscriber::getInfoTopic() const +{ + if (impl_) return impl_->info_sub_.getTopic(); + return std::string(); +} + +uint32_t CameraSubscriber::getNumPublishers() const +{ + /// @todo Fix this when message_filters::Subscriber has getNumPublishers() + //if (impl_) return std::max(impl_->image_sub_.getNumPublishers(), impl_->info_sub_.getNumPublishers()); + if (impl_) return impl_->image_sub_.getNumPublishers(); + return 0; +} + +std::string CameraSubscriber::getTransport() const +{ + if (impl_) return impl_->image_sub_.getTransport(); + return std::string(); +} + +void CameraSubscriber::shutdown() +{ + if (impl_) impl_->shutdown(); +} + +CameraSubscriber::operator void*() const +{ + return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/image_transport.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/image_transport.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88ba1254e49f6513c8f7c9d5b8cbd76940bb4d4e --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/image_transport.cpp @@ -0,0 +1,148 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/image_transport.h" +#include "image_transport/publisher_plugin.h" +#include "image_transport/subscriber_plugin.h" +#include <pluginlib/class_loader.h> +#include <boost/make_shared.hpp> +#include <boost/foreach.hpp> +#include <boost/algorithm/string/erase.hpp> + +namespace image_transport { + +struct ImageTransport::Impl +{ + ros::NodeHandle nh_; + PubLoaderPtr pub_loader_; + SubLoaderPtr sub_loader_; + + Impl(const ros::NodeHandle& nh) + : nh_(nh), + pub_loader_( boost::make_shared<PubLoader>("image_transport", "image_transport::PublisherPlugin") ), + sub_loader_( boost::make_shared<SubLoader>("image_transport", "image_transport::SubscriberPlugin") ) + { + } +}; + +ImageTransport::ImageTransport(const ros::NodeHandle& nh) + : impl_(new Impl(nh)) +{ +} + +ImageTransport::~ImageTransport() +{ +} + +Publisher ImageTransport::advertise(const std::string& base_topic, uint32_t queue_size, bool latch) +{ + return advertise(base_topic, queue_size, SubscriberStatusCallback(), + SubscriberStatusCallback(), ros::VoidPtr(), latch); +} + +Publisher ImageTransport::advertise(const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& connect_cb, + const SubscriberStatusCallback& disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch) +{ + return Publisher(impl_->nh_, base_topic, queue_size, connect_cb, disconnect_cb, tracked_object, latch, impl_->pub_loader_); +} + +Subscriber ImageTransport::subscribe(const std::string& base_topic, uint32_t queue_size, + const boost::function<void(const sensor_msgs::ImageConstPtr&)>& callback, + const ros::VoidPtr& tracked_object, const TransportHints& transport_hints) +{ + return Subscriber(impl_->nh_, base_topic, queue_size, callback, tracked_object, transport_hints, impl_->sub_loader_); +} + +CameraPublisher ImageTransport::advertiseCamera(const std::string& base_topic, uint32_t queue_size, bool latch) +{ + return advertiseCamera(base_topic, queue_size, + SubscriberStatusCallback(), SubscriberStatusCallback(), + ros::SubscriberStatusCallback(), ros::SubscriberStatusCallback(), + ros::VoidPtr(), latch); +} + +CameraPublisher ImageTransport::advertiseCamera(const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& image_connect_cb, + const SubscriberStatusCallback& image_disconnect_cb, + const ros::SubscriberStatusCallback& info_connect_cb, + const ros::SubscriberStatusCallback& info_disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch) +{ + return CameraPublisher(*this, impl_->nh_, base_topic, queue_size, image_connect_cb, image_disconnect_cb, + info_connect_cb, info_disconnect_cb, tracked_object, latch); +} + +CameraSubscriber ImageTransport::subscribeCamera(const std::string& base_topic, uint32_t queue_size, + const CameraSubscriber::Callback& callback, + const ros::VoidPtr& tracked_object, + const TransportHints& transport_hints) +{ + return CameraSubscriber(*this, impl_->nh_, base_topic, queue_size, callback, tracked_object, transport_hints); +} + +std::vector<std::string> ImageTransport::getDeclaredTransports() const +{ + std::vector<std::string> transports = impl_->sub_loader_->getDeclaredClasses(); + // Remove the "_sub" at the end of each class name. + BOOST_FOREACH(std::string& transport, transports) { + transport = boost::erase_last_copy(transport, "_sub"); + } + return transports; +} + +std::vector<std::string> ImageTransport::getLoadableTransports() const +{ + std::vector<std::string> loadableTransports; + + BOOST_FOREACH( const std::string& transportPlugin, impl_->sub_loader_->getDeclaredClasses() ) + { + // If the plugin loads without throwing an exception, add its + // transport name to the list of valid plugins, otherwise ignore + // it. + try + { + boost::shared_ptr<image_transport::SubscriberPlugin> sub = impl_->sub_loader_->createInstance(transportPlugin); + loadableTransports.push_back(boost::erase_last_copy(transportPlugin, "_sub")); // Remove the "_sub" at the end of each class name. + } + catch (const pluginlib::LibraryLoadException& e) {} + catch (const pluginlib::CreateClassException& e) {} + } + + return loadableTransports; + +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/list_transports.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/list_transports.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dba88127a8b0a1de374a300414f9a3231622a9ff --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/list_transports.cpp @@ -0,0 +1,141 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/publisher_plugin.h" +#include "image_transport/subscriber_plugin.h" +#include <pluginlib/class_loader.h> +#include <boost/foreach.hpp> +#include <boost/algorithm/string/erase.hpp> +#include <map> + +using namespace image_transport; +using namespace pluginlib; + +enum PluginStatus {SUCCESS, CREATE_FAILURE, LIB_LOAD_FAILURE, DOES_NOT_EXIST}; + +/// \cond +struct TransportDesc +{ + TransportDesc() + : pub_status(DOES_NOT_EXIST), sub_status(DOES_NOT_EXIST) + {} + + std::string package_name; + std::string pub_name; + PluginStatus pub_status; + std::string sub_name; + PluginStatus sub_status; +}; +/// \endcond + +int main(int argc, char** argv) +{ + ClassLoader<PublisherPlugin> pub_loader("image_transport", "image_transport::PublisherPlugin"); + ClassLoader<SubscriberPlugin> sub_loader("image_transport", "image_transport::SubscriberPlugin"); + typedef std::map<std::string, TransportDesc> StatusMap; + StatusMap transports; + + BOOST_FOREACH(const std::string& lookup_name, pub_loader.getDeclaredClasses()) { + std::string transport_name = boost::erase_last_copy(lookup_name, "_pub"); + transports[transport_name].pub_name = lookup_name; + transports[transport_name].package_name = pub_loader.getClassPackage(lookup_name); + try { + boost::shared_ptr<PublisherPlugin> pub = pub_loader.createInstance(lookup_name); + transports[transport_name].pub_status = SUCCESS; + } + catch (const LibraryLoadException& e) { + transports[transport_name].pub_status = LIB_LOAD_FAILURE; + } + catch (const CreateClassException& e) { + transports[transport_name].pub_status = CREATE_FAILURE; + } + } + + BOOST_FOREACH(const std::string& lookup_name, sub_loader.getDeclaredClasses()) { + std::string transport_name = boost::erase_last_copy(lookup_name, "_sub"); + transports[transport_name].sub_name = lookup_name; + transports[transport_name].package_name = sub_loader.getClassPackage(lookup_name); + try { + boost::shared_ptr<SubscriberPlugin> sub = sub_loader.createInstance(lookup_name); + transports[transport_name].sub_status = SUCCESS; + } + catch (const LibraryLoadException& e) { + transports[transport_name].sub_status = LIB_LOAD_FAILURE; + } + catch (const CreateClassException& e) { + transports[transport_name].sub_status = CREATE_FAILURE; + } + } + + bool problem_package = false; + printf("Declared transports:\n"); + BOOST_FOREACH(const StatusMap::value_type& value, transports) { + const TransportDesc& td = value.second; + printf("%s", value.first.c_str()); + if ((td.pub_status == CREATE_FAILURE || td.pub_status == LIB_LOAD_FAILURE) || + (td.sub_status == CREATE_FAILURE || td.sub_status == LIB_LOAD_FAILURE)) { + printf(" (*): Not available. Try 'catkin_make --pkg %s'.", td.package_name.c_str()); + problem_package = true; + } + printf("\n"); + } +#if 0 + if (problem_package) + printf("(*) \n"); +#endif + + printf("\nDetails:\n"); + BOOST_FOREACH(const StatusMap::value_type& value, transports) { + const TransportDesc& td = value.second; + printf("----------\n"); + printf("\"%s\"\n", value.first.c_str()); + if (td.pub_status == CREATE_FAILURE || td.sub_status == CREATE_FAILURE) { + printf("*** Plugins are built, but could not be loaded. The package may need to be rebuilt or may not be compatible with this release of image_common. ***\n"); + } + else if (td.pub_status == LIB_LOAD_FAILURE || td.sub_status == LIB_LOAD_FAILURE) { + printf("*** Plugins are not built. ***\n"); + } + printf(" - Provided by package: %s\n", td.package_name.c_str()); + if (td.pub_status == DOES_NOT_EXIST) + printf(" - No publisher provided\n"); + else + printf(" - Publisher: %s\n", pub_loader.getClassDescription(td.pub_name).c_str()); + if (td.sub_status == DOES_NOT_EXIST) + printf(" - No subscriber provided\n"); + else + printf(" - Subscriber: %s\n", sub_loader.getClassDescription(td.sub_name).c_str()); + } + + return 0; +} diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/manifest.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/manifest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40a8acddb86f5a11cf05a6c94528441db7579999 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/manifest.cpp @@ -0,0 +1,41 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include <pluginlib/class_list_macros.h> +#include "image_transport/raw_publisher.h" +#include "image_transport/raw_subscriber.h" + +PLUGINLIB_EXPORT_CLASS( image_transport::RawPublisher, image_transport::PublisherPlugin) + +PLUGINLIB_EXPORT_CLASS( image_transport::RawSubscriber, image_transport::SubscriberPlugin) diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/publisher.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/publisher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8822afe28f5bceff4671aacabe790f7648a96817 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/publisher.cpp @@ -0,0 +1,203 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/publisher.h" +#include "image_transport/publisher_plugin.h" +#include <pluginlib/class_loader.h> +#include <boost/foreach.hpp> +#include <boost/algorithm/string/erase.hpp> + +namespace image_transport { + +struct Publisher::Impl +{ + Impl() + : unadvertised_(false) + { + } + + ~Impl() + { + shutdown(); + } + + uint32_t getNumSubscribers() const + { + uint32_t count = 0; + BOOST_FOREACH(const boost::shared_ptr<PublisherPlugin>& pub, publishers_) + count += pub->getNumSubscribers(); + return count; + } + + std::string getTopic() const + { + return base_topic_; + } + + bool isValid() const + { + return !unadvertised_; + } + + void shutdown() + { + if (!unadvertised_) { + unadvertised_ = true; + BOOST_FOREACH(boost::shared_ptr<PublisherPlugin>& pub, publishers_) + pub->shutdown(); + publishers_.clear(); + } + } + + void subscriberCB(const SingleSubscriberPublisher& plugin_pub, + const SubscriberStatusCallback& user_cb) + { + SingleSubscriberPublisher ssp(plugin_pub.getSubscriberName(), getTopic(), + boost::bind(&Publisher::Impl::getNumSubscribers, this), + plugin_pub.publish_fn_); + user_cb(ssp); + } + + std::string base_topic_; + PubLoaderPtr loader_; + std::vector<boost::shared_ptr<PublisherPlugin> > publishers_; + bool unadvertised_; + //double constructed_; +}; + + +Publisher::Publisher(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const SubscriberStatusCallback& connect_cb, + const SubscriberStatusCallback& disconnect_cb, + const ros::VoidPtr& tracked_object, bool latch, + const PubLoaderPtr& loader) + : impl_(new Impl) +{ + // Resolve the name explicitly because otherwise the compressed topics don't remap + // properly (#3652). + impl_->base_topic_ = nh.resolveName(base_topic); + impl_->loader_ = loader; + + BOOST_FOREACH(const std::string& lookup_name, loader->getDeclaredClasses()) { + try { + boost::shared_ptr<PublisherPlugin> pub = loader->createInstance(lookup_name); + impl_->publishers_.push_back(pub); + pub->advertise(nh, impl_->base_topic_, queue_size, rebindCB(connect_cb), + rebindCB(disconnect_cb), tracked_object, latch); + } + catch (const std::runtime_error& e) { + ROS_DEBUG("Failed to load plugin %s, error string: %s", + lookup_name.c_str(), e.what()); + } + } + + if (impl_->publishers_.empty()) + throw Exception("No plugins found! Does `rospack plugins --attrib=plugin " + "image_transport` find any packages?"); +} + +uint32_t Publisher::getNumSubscribers() const +{ + if (impl_ && impl_->isValid()) return impl_->getNumSubscribers(); + return 0; +} + +std::string Publisher::getTopic() const +{ + if (impl_) return impl_->getTopic(); + return std::string(); +} + +void Publisher::publish(const sensor_msgs::Image& message) const +{ + if (!impl_ || !impl_->isValid()) { + ROS_ASSERT_MSG(false, "Call to publish() on an invalid image_transport::Publisher"); + return; + } + + BOOST_FOREACH(const boost::shared_ptr<PublisherPlugin>& pub, impl_->publishers_) { + if (pub->getNumSubscribers() > 0) + pub->publish(message); + } +} + +void Publisher::publish(const sensor_msgs::ImageConstPtr& message) const +{ + if (!impl_ || !impl_->isValid()) { + ROS_ASSERT_MSG(false, "Call to publish() on an invalid image_transport::Publisher"); + return; + } + + BOOST_FOREACH(const boost::shared_ptr<PublisherPlugin>& pub, impl_->publishers_) { + if (pub->getNumSubscribers() > 0) + pub->publish(message); + } +} + +void Publisher::shutdown() +{ + if (impl_) { + impl_->shutdown(); + impl_.reset(); + } +} + +Publisher::operator void*() const +{ + return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; +} + +void Publisher::weakSubscriberCb(const ImplWPtr& impl_wptr, + const SingleSubscriberPublisher& plugin_pub, + const SubscriberStatusCallback& user_cb) +{ + if (ImplPtr impl = impl_wptr.lock()) + impl->subscriberCB(plugin_pub, user_cb); +} + +SubscriberStatusCallback Publisher::rebindCB(const SubscriberStatusCallback& user_cb) +{ + // Note: the subscriber callback must be bound to the internal Impl object, not + // 'this'. Due to copying behavior the Impl object may outlive the original Publisher + // instance. But it should not outlive the last Publisher, so we use a weak_ptr. + if (user_cb) + { + ImplWPtr impl_wptr(impl_); + return boost::bind(&Publisher::weakSubscriberCb, impl_wptr, _1, user_cb); + } + else + return SubscriberStatusCallback(); +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/raw_publisher.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/raw_publisher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1eda7504474506815718124f7dd1eb5dc3be581 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/raw_publisher.cpp @@ -0,0 +1,140 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include <image_transport/raw_publisher.h> +#include <ros/static_assert.h> +#include <sensor_msgs/Image.h> + +/** The code in the following namespace copies a lof of code from cv_bridge + * It does not depend on cv_bridge to not depend on OpenCV + * It re-defines a CvImage so that we can publish that object and not a + * sensor_msgs::Image, which requires a memory copy + */ + +class ImageTransportImage +{ +public: + sensor_msgs::Image image_; //!< ROS header + const uint8_t* data_; //!< Image data for use with OpenCV + + /** + * \brief Empty constructor. + */ + ImageTransportImage() {} + + /** + * \brief Constructor. + */ + ImageTransportImage(const sensor_msgs::Image& image, const uint8_t* data) + : image_(image), data_(data) + { + } +}; + +/// @cond DOXYGEN_IGNORE +namespace ros { + +namespace message_traits { + +template<> struct MD5Sum<ImageTransportImage> +{ + static const char* value() { return MD5Sum<sensor_msgs::Image>::value(); } + static const char* value(const ImageTransportImage&) { return value(); } + + static const uint64_t static_value1 = MD5Sum<sensor_msgs::Image>::static_value1; + static const uint64_t static_value2 = MD5Sum<sensor_msgs::Image>::static_value2; + + // If the definition of sensor_msgs/Image changes, we'll get a compile error here. + ROS_STATIC_ASSERT(MD5Sum<sensor_msgs::Image>::static_value1 == 0x060021388200f6f0ULL); + ROS_STATIC_ASSERT(MD5Sum<sensor_msgs::Image>::static_value2 == 0xf447d0fcd9c64743ULL); +}; + +template<> struct DataType<ImageTransportImage> +{ + static const char* value() { return DataType<sensor_msgs::Image>::value(); } + static const char* value(const ImageTransportImage&) { return value(); } +}; + +template<> struct Definition<ImageTransportImage> +{ + static const char* value() { return Definition<sensor_msgs::Image>::value(); } + static const char* value(const ImageTransportImage&) { return value(); } +}; + +template<> struct HasHeader<ImageTransportImage> : TrueType {}; + +} // namespace ros::message_traits + +namespace serialization { + +template<> struct Serializer<ImageTransportImage> +{ + /// @todo Still ignoring endianness... + + template<typename Stream> + inline static void write(Stream& stream, const ImageTransportImage& m) + { + stream.next(m.image_.header); + stream.next((uint32_t)m.image_.height); // height + stream.next((uint32_t)m.image_.width); // width + stream.next(m.image_.encoding); + uint8_t is_bigendian = 0; + stream.next(is_bigendian); + stream.next((uint32_t)m.image_.step); + size_t data_size = m.image_.step*m.image_.height; + stream.next((uint32_t)data_size); + if (data_size > 0) + memcpy(stream.advance(data_size), m.data_, data_size); + } + + inline static uint32_t serializedLength(const ImageTransportImage& m) + { + size_t data_size = m.image_.step*m.image_.height; + return serializationLength(m.image_.header) + serializationLength(m.image_.encoding) + 17 + data_size; + } +}; + +} // namespace ros::serialization + +} // namespace ros + + +namespace image_transport { + +void RawPublisher::publish(const sensor_msgs::Image& message, const uint8_t* data) const +{ + getPublisher().publish(ImageTransportImage(message, data)); +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/republish.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/republish.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14fb276118a104e120c97370ed30c33ada111e44 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/republish.cpp @@ -0,0 +1,86 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/image_transport.h" +#include "image_transport/publisher_plugin.h" +#include <pluginlib/class_loader.h> + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "image_republisher", ros::init_options::AnonymousName); + if (argc < 2) { + printf("Usage: %s in_transport in:=<in_base_topic> [out_transport] out:=<out_base_topic>\n", argv[0]); + return 0; + } + ros::NodeHandle nh; + std::string in_topic = nh.resolveName("in"); + std::string in_transport = argv[1]; + std::string out_topic = nh.resolveName("out"); + + image_transport::ImageTransport it(nh); + image_transport::Subscriber sub; + + if (argc < 3) { + // Use all available transports for output + image_transport::Publisher pub = it.advertise(out_topic, 1); + + // Use Publisher::publish as the subscriber callback + typedef void (image_transport::Publisher::*PublishMemFn)(const sensor_msgs::ImageConstPtr&) const; + PublishMemFn pub_mem_fn = &image_transport::Publisher::publish; + sub = it.subscribe(in_topic, 1, boost::bind(pub_mem_fn, &pub, _1), ros::VoidPtr(), in_transport); + + ros::spin(); + } + else { + // Use one specific transport for output + std::string out_transport = argv[2]; + + // Load transport plugin + typedef image_transport::PublisherPlugin Plugin; + pluginlib::ClassLoader<Plugin> loader("image_transport", "image_transport::PublisherPlugin"); + std::string lookup_name = Plugin::getLookupName(out_transport); + boost::shared_ptr<Plugin> pub( loader.createInstance(lookup_name) ); + pub->advertise(nh, out_topic, 1, image_transport::SubscriberStatusCallback(), + image_transport::SubscriberStatusCallback(), ros::VoidPtr(), false); + + // Use PublisherPlugin::publish as the subscriber callback + typedef void (Plugin::*PublishMemFn)(const sensor_msgs::ImageConstPtr&) const; + PublishMemFn pub_mem_fn = &Plugin::publish; + sub = it.subscribe(in_topic, 1, boost::bind(pub_mem_fn, pub.get(), _1), pub, in_transport); + + ros::spin(); + } + + return 0; +} diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/single_subscriber_publisher.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/single_subscriber_publisher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10fc29433d6076df6066476d28584ebb715cc644 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/single_subscriber_publisher.cpp @@ -0,0 +1,74 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/single_subscriber_publisher.h" +#include "image_transport/publisher.h" + +namespace image_transport { + +SingleSubscriberPublisher::SingleSubscriberPublisher(const std::string& caller_id, const std::string& topic, + const GetNumSubscribersFn& num_subscribers_fn, + const PublishFn& publish_fn) + : caller_id_(caller_id), topic_(topic), + num_subscribers_fn_(num_subscribers_fn), + publish_fn_(publish_fn) +{ +} + +std::string SingleSubscriberPublisher::getSubscriberName() const +{ + return caller_id_; +} + +std::string SingleSubscriberPublisher::getTopic() const +{ + return topic_; +} + +uint32_t SingleSubscriberPublisher::getNumSubscribers() const +{ + return num_subscribers_fn_(); +} + +void SingleSubscriberPublisher::publish(const sensor_msgs::Image& message) const +{ + publish_fn_(message); +} + +void SingleSubscriberPublisher::publish(const sensor_msgs::ImageConstPtr& message) const +{ + publish_fn_(*message); +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/subscriber.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/subscriber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7ef654b7447b15a43d242ab7b9361abf1d4edf7 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/src/subscriber.cpp @@ -0,0 +1,142 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2009, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +#include "image_transport/subscriber.h" +#include "image_transport/subscriber_plugin.h" +#include <ros/names.h> +#include <pluginlib/class_loader.h> +#include <boost/scoped_ptr.hpp> + +namespace image_transport { + +struct Subscriber::Impl +{ + Impl() + : unsubscribed_(false) + { + } + + ~Impl() + { + shutdown(); + } + + bool isValid() const + { + return !unsubscribed_; + } + + void shutdown() + { + if (!unsubscribed_) { + unsubscribed_ = true; + if (subscriber_) + subscriber_->shutdown(); + } + } + + SubLoaderPtr loader_; + boost::shared_ptr<SubscriberPlugin> subscriber_; + bool unsubscribed_; + //double constructed_; +}; + +Subscriber::Subscriber(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size, + const boost::function<void(const sensor_msgs::ImageConstPtr&)>& callback, + const ros::VoidPtr& tracked_object, const TransportHints& transport_hints, + const SubLoaderPtr& loader) + : impl_(new Impl) +{ + // Load the plugin for the chosen transport. + std::string lookup_name = SubscriberPlugin::getLookupName(transport_hints.getTransport()); + try { + impl_->subscriber_ = loader->createInstance(lookup_name); + } + catch (pluginlib::PluginlibException& e) { + throw TransportLoadException(transport_hints.getTransport(), e.what()); + } + // Hang on to the class loader so our shared library doesn't disappear from under us. + impl_->loader_ = loader; + + // Try to catch if user passed in a transport-specific topic as base_topic. + std::string clean_topic = ros::names::clean(base_topic); + size_t found = clean_topic.rfind('/'); + if (found != std::string::npos) { + std::string transport = clean_topic.substr(found+1); + std::string plugin_name = SubscriberPlugin::getLookupName(transport); + std::vector<std::string> plugins = loader->getDeclaredClasses(); + if (std::find(plugins.begin(), plugins.end(), plugin_name) != plugins.end()) { + std::string real_base_topic = clean_topic.substr(0, found); + ROS_WARN("[image_transport] It looks like you are trying to subscribe directly to a " + "transport-specific image topic '%s', in which case you will likely get a connection " + "error. Try subscribing to the base topic '%s' instead with parameter ~image_transport " + "set to '%s' (on the command line, _image_transport:=%s). " + "See http://ros.org/wiki/image_transport for details.", + clean_topic.c_str(), real_base_topic.c_str(), transport.c_str(), transport.c_str()); + } + } + + // Tell plugin to subscribe. + impl_->subscriber_->subscribe(nh, base_topic, queue_size, callback, tracked_object, transport_hints); +} + +std::string Subscriber::getTopic() const +{ + if (impl_) return impl_->subscriber_->getTopic(); + return std::string(); +} + +uint32_t Subscriber::getNumPublishers() const +{ + if (impl_) return impl_->subscriber_->getNumPublishers(); + return 0; +} + +std::string Subscriber::getTransport() const +{ + if (impl_) return impl_->subscriber_->getTransportName(); + return std::string(); +} + +void Subscriber::shutdown() +{ + if (impl_) impl_->shutdown(); +} + +Subscriber::operator void*() const +{ + return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; +} + +} //namespace image_transport diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/CMakeLists.txt b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2ac34d9e2c8c20475ce58cc9cd53f9241db73d63 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 2.8) +project(image_transport_tutorial) + +find_package(catkin REQUIRED cv_bridge genmsg image_transport sensor_msgs) + +# add the resized image message +add_message_files(DIRECTORY msg + FILES ResizedImage.msg +) +generate_messages(DEPENDENCIES sensor_msgs) + +catkin_package() + +find_package(OpenCV) + +include_directories(include ${OpenCV_INCLUDE_DIRS}) + +# add the publisher example +add_executable(my_publisher src/my_publisher.cpp) +target_link_libraries(my_publisher ${catkin_LIBRARIES} ${OpenCV_LIBRARIES}) + +# add the subscriber example +add_executable(my_subscriber src/my_subscriber.cpp) +target_link_libraries(my_subscriber ${catkin_LIBRARIES} ${OpenCV_LIBRARIES}) + +# add the plugin examples +add_library(resized_publisher src/manifest.cpp src/resized_publisher.cpp src/resized_subscriber.cpp) +target_link_libraries(resized_publisher ${catkin_LIBRARIES} ${OpenCV_LIBRARIES}) diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/include/image_transport_tutorial/resized_publisher.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/include/image_transport_tutorial/resized_publisher.h new file mode 100644 index 0000000000000000000000000000000000000000..63ab3eb7dd6ebbf30a1e03eb9dd55a8579d498f4 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/include/image_transport_tutorial/resized_publisher.h @@ -0,0 +1,15 @@ +#include <image_transport/simple_publisher_plugin.h> +#include <image_transport_tutorial/ResizedImage.h> + +class ResizedPublisher : public image_transport::SimplePublisherPlugin<image_transport_tutorial::ResizedImage> +{ +public: + virtual std::string getTransportName() const + { + return "resized"; + } + +protected: + virtual void publish(const sensor_msgs::Image& message, + const PublishFn& publish_fn) const; +}; diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/include/image_transport_tutorial/resized_subscriber.h b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/include/image_transport_tutorial/resized_subscriber.h new file mode 100644 index 0000000000000000000000000000000000000000..94b55f54f434d771ef2f7a0e70873c80f421bcc7 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/include/image_transport_tutorial/resized_subscriber.h @@ -0,0 +1,17 @@ +#include <image_transport/simple_subscriber_plugin.h> +#include <image_transport_tutorial/ResizedImage.h> + +class ResizedSubscriber : public image_transport::SimpleSubscriberPlugin<image_transport_tutorial::ResizedImage> +{ +public: + virtual ~ResizedSubscriber() {} + + virtual std::string getTransportName() const + { + return "resized"; + } + +protected: + virtual void internalCallback(const typename image_transport_tutorial::ResizedImage::ConstPtr& message, + const Callback& user_cb); +}; diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/msg/ResizedImage.msg b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/msg/ResizedImage.msg new file mode 100644 index 0000000000000000000000000000000000000000..d8c8fadb21106dd3bd4e9224ab6b3b9145d92edc --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/msg/ResizedImage.msg @@ -0,0 +1,3 @@ +uint32 original_height +uint32 original_width +sensor_msgs/Image image diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/package.xml b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..67ef5b09ba8b2327f391aed671e1dd15a615a8dd --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/package.xml @@ -0,0 +1,25 @@ +<package> + <name>image_transport_tutorial</name> + <version>0.0.0</version> + <description>Tutorial for image_transport. This is useful for the tutorials at http://wiki.ros.org/image_transport/Tutorials/</description> + <author>Vincent Rabaud</author> + <maintainer email="vincent.rabaud@gmail.com">Vincent Rabaud</maintainer> + <license>Apache 2.0</license> + + <build_depend>cv_bridge</build_depend> + <build_depend>image_transport</build_depend> + <build_depend>message_generation</build_depend> + <build_depend>opencv2</build_depend> + <build_depend>sensor_msgs</build_depend> + + <run_depend>cv_bridge</run_depend> + <run_depend>image_transport</run_depend> + <run_depend>message_runtime</run_depend> + <run_depend>opencv2</run_depend> + + <buildtool_depend>catkin</buildtool_depend> + + <export> + <image_transport plugin="${prefix}/resized_plugins.xml"/> + </export> +</package> diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/resized_plugins.xml b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/resized_plugins.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd2dff1a9e532f00fa9b0fd62222e681e9b7d7ba --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/resized_plugins.xml @@ -0,0 +1,13 @@ +<library path="lib/libresized_image_transport"> + <class name="resized_pub" type="ResizedPublisher" base_class_type="image_transport::PublisherPlugin"> + <description> + This plugin publishes a decimated version of the image. + </description> + </class> + + <class name="resized_sub" type="ResizedSubscriber" base_class_type="image_transport::SubscriberPlugin"> + <description> + This plugin rescales a decimated image to its original size. + </description> + </class> +</library> diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/manifest.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/manifest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c13b09242ad66c541655fb0058c6f6cf936f460 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/manifest.cpp @@ -0,0 +1,8 @@ +#include <pluginlib/class_list_macros.h> +#include <image_transport_tutorial/resized_publisher.h> +#include <image_transport_tutorial/resized_subscriber.h> + +PLUGINLIB_REGISTER_CLASS(resized_pub, ResizedPublisher, image_transport::PublisherPlugin) + +PLUGINLIB_REGISTER_CLASS(resized_sub, ResizedSubscriber, image_transport::SubscriberPlugin) + diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/my_publisher.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/my_publisher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..701dbddfd9f20710e6017cbb27979c87d0fe4b42 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/my_publisher.cpp @@ -0,0 +1,23 @@ +#include <ros/ros.h> +#include <image_transport/image_transport.h> +#include <opencv2/highgui/highgui.hpp> +#include <cv_bridge/cv_bridge.h> + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "image_publisher"); + ros::NodeHandle nh; + image_transport::ImageTransport it(nh); + image_transport::Publisher pub = it.advertise("camera/image", 1); + + cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR); + sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg(); + + ros::Rate loop_rate(5); + while (nh.ok()) { + pub.publish(msg); + ros::spinOnce(); + loop_rate.sleep(); + } +} + diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/my_subscriber.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/my_subscriber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50573b9853823a7d91b3e32c6cff8109a9135b41 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/my_subscriber.cpp @@ -0,0 +1,28 @@ +#include <ros/ros.h> +#include <image_transport/image_transport.h> +#include <opencv2/highgui/highgui.hpp> +#include <cv_bridge/cv_bridge.h> + +void imageCallback(const sensor_msgs::ImageConstPtr& msg) +{ + try + { + cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image); + } + catch (cv_bridge::Exception& e) + { + ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str()); + } +} + +int main(int argc, char **argv) +{ + ros::init(argc, argv, "image_listener"); + ros::NodeHandle nh; + cv::namedWindow("view"); + cv::startWindowThread(); + image_transport::ImageTransport it(nh); + image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); + ros::spin(); + cv::destroyWindow("view"); +} diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/resized_publisher.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/resized_publisher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..178f482141b425577c96cd5344cbe1a0fea0fb6a --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/resized_publisher.cpp @@ -0,0 +1,37 @@ +#include <image_transport_tutorial/resized_publisher.h> +#include <opencv2/imgproc/imgproc.hpp> +#include <cv_bridge/cv_bridge.h> + +void ResizedPublisher::publish(const sensor_msgs::Image& message, + const PublishFn& publish_fn) const +{ + cv::Mat cv_image; + boost::shared_ptr<void const> tracked_object; + try + { + cv_image = cv_bridge::toCvShare(message, tracked_object, message.encoding)->image; + } + catch (cv::Exception &e) + { + ROS_ERROR("Could not convert from '%s' to '%s'.", message.encoding.c_str(), message.encoding.c_str()); + return; + } + + // Retrieve subsampling factor from the parameter server + double subsampling_factor; + std::string param_name; + nh().param<double>("resized_image_transport_subsampling_factor", subsampling_factor, 2.0); + + // Rescale image + int new_width = cv_image.cols / subsampling_factor + 0.5; + int new_height = cv_image.rows / subsampling_factor + 0.5; + cv::Mat buffer; + cv::resize(cv_image, buffer, cv::Size(new_width, new_height)); + + // Set up ResizedImage and publish + image_transport_tutorial::ResizedImage resized_image; + resized_image.original_height = cv_image.rows; + resized_image.original_width = cv_image.cols; + resized_image.image = *(cv_bridge::CvImage(message.header, "bgr8", cv_image).toImageMsg()); + publish_fn(resized_image); +} diff --git a/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/resized_subscriber.cpp b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/resized_subscriber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..299dc83d7fa379366d4385f3c028225dca722105 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/image_common/image_transport/tutorial/src/resized_subscriber.cpp @@ -0,0 +1,18 @@ +#include <image_transport_tutorial/resized_subscriber.h> +#include <cv_bridge/cv_bridge.h> +#include <opencv2/imgproc/imgproc.hpp> + +void ResizedSubscriber::internalCallback(const image_transport_tutorial::ResizedImage::ConstPtr& msg, + const Callback& user_cb) +{ + // This is only for optimization, not to copy the image + boost::shared_ptr<void const> tracked_object_tmp; + cv::Mat img_rsz = cv_bridge::toCvShare(msg->image, tracked_object_tmp)->image; + // Resize the image to its original size + cv::Mat img_restored; + cv::resize(img_rsz, img_restored, cv::Size(msg->original_width, msg->original_height)); + + // Call the user callback with the restored image + cv_bridge::CvImage cv_img(msg->image.header, msg->image.encoding, img_restored); + user_cb(cv_img.toImageMsg()); +}; diff --git a/Robot_Development/catkin_ws/libraries/serialization/Detection.h b/Robot_Development/catkin_ws/libraries/serialization/Detection.h new file mode 100644 index 0000000000000000000000000000000000000000..7355b7295b50808dd2850d65e92a2dc7e965d174 --- /dev/null +++ b/Robot_Development/catkin_ws/libraries/serialization/Detection.h @@ -0,0 +1,130 @@ +#include<iostream> +#include<sstream> +#include<string> +#include<iterator> +#include<map> + +using namespace std; + +class Detection { +public: + string _name; + float _prob; + int _cx; + int _cy; + int _w; + int _h; + Detection() { + + } + Detection(string name, float prob, int cx,int cy, int w, int h) { + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + } + Detection(string serialization) { + string whitespace = removeSpaces(serialization); + cout << whitespace << endl; + string unbraced = whitespace.substr(1, whitespace.length()-2); + cout << unbraced << endl; + string arr[5]; + + string str1 = unbraced; + string str2 = "name:"; + string str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "prob:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cx:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "cy:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "w:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + str2 = "h:"; + str3 = ""; + str1.replace(str1.find(str2),str2.length(),str3); + + cout << str1 << endl; + + string name = str1.substr(0,str1.find(',')); + cout << name << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + float prob = stof(str1.substr(0,str1.find(','))); + cout << prob << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cx = stoi(str1.substr(0,str1.find(','))); + cout << cx << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int cy = stoi(str1.substr(0,str1.find(','))); + cout << cy << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int w = stoi(str1.substr(0,str1.find(','))); + cout << w << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + int h = stoi(str1.substr(0,str1.find(','))); + cout << h << endl; + str1 = str1.substr(str1.find(',')+1, str1.length()-1); + + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + + } + string removeSpaces(string str) + { + string s = ""; + // To keep track of non-space character count + int count = 0; + + // Traverse the given string. If current character + // is not space, then place it at index 'count++' + for (int i = 0; i < str.length() ; i++) + if (str.at(i) != ' ') + s = s + str.at(i); + // incremented + return s; + } + + template <size_t N> + void splitString(string (&arr)[N], string str) + { + int n = 0; + istringstream iss(str); + for (auto it = istream_iterator<string>(iss); it != istream_iterator<string>() && n < N; ++it, ++n) + arr[n] = *it; + } + + + string to_string() { + string s0 = "name=" + _name + ","; + string s1 = "prob=" + std::to_string(_prob) + ","; + string s2 = "cx=" + std::to_string(_cx) + ","; + string s3 = "cy=" + std::to_string(_cy) + ","; + string s4 = "w=" + std::to_string(_w) + ","; + string s5 = "h=" + std::to_string(_h) + ","; + string s = s0 + s1 + s2 + s3 + s4 + s5; + return s; + } +}; + diff --git a/Robot_Development/catkin_ws/object_detection/CMakeLists.txt b/Robot_Development/catkin_ws/object_detection/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..31f4a7e93451b9d87ce14552e81003ada83eab33 --- /dev/null +++ b/Robot_Development/catkin_ws/object_detection/CMakeLists.txt @@ -0,0 +1,200 @@ +cmake_minimum_required(VERSION 2.8.3) +project(object_detection) + +## Compile as C++11, supported in ROS Kinetic and newer +# add_compile_options(-std=c++11) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED COMPONENTS + roscpp + rospy + std_msgs +) + +## System dependencies are found with CMake's conventions +# find_package(Boost REQUIRED COMPONENTS system) + + +## Uncomment this if the package has a setup.py. This macro ensures +## modules and global scripts declared therein get installed +## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html +# catkin_python_setup() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +## To declare and build messages, services or actions from within this +## package, follow these steps: +## * Let MSG_DEP_SET be the set of packages whose message types you use in +## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). +## * In the file package.xml: +## * add a build_depend tag for "message_generation" +## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET +## * If MSG_DEP_SET isn't empty the following dependency has been pulled in +## but can be declared for certainty nonetheless: +## * add a exec_depend tag for "message_runtime" +## * In this file (CMakeLists.txt): +## * add "message_generation" and every package in MSG_DEP_SET to +## find_package(catkin REQUIRED COMPONENTS ...) +## * add "message_runtime" and every package in MSG_DEP_SET to +## catkin_package(CATKIN_DEPENDS ...) +## * uncomment the add_*_files sections below as needed +## and list every .msg/.srv/.action file to be processed +## * uncomment the generate_messages entry below +## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) + +## Generate messages in the 'msg' folder +# add_message_files( +# FILES +# Message1.msg +# Message2.msg +# ) + +## Generate services in the 'srv' folder +# add_service_files( +# FILES +# Service1.srv +# Service2.srv +# ) + +## Generate actions in the 'action' folder +# add_action_files( +# FILES +# Action1.action +# Action2.action +# ) + +## Generate added messages and services with any dependencies listed here +# generate_messages( +# DEPENDENCIES +# std_msgs +# ) + +################################################ +## Declare ROS dynamic reconfigure parameters ## +################################################ + +## To declare and build dynamic reconfigure parameters within this +## package, follow these steps: +## * In the file package.xml: +## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" +## * In this file (CMakeLists.txt): +## * add "dynamic_reconfigure" to +## find_package(catkin REQUIRED COMPONENTS ...) +## * uncomment the "generate_dynamic_reconfigure_options" section below +## and list every .cfg file to be processed + +## Generate dynamic reconfigure parameters in the 'cfg' folder +# generate_dynamic_reconfigure_options( +# cfg/DynReconf1.cfg +# cfg/DynReconf2.cfg +# ) + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if your package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES object_detection +# CATKIN_DEPENDS roscpp rospy std_msgs +# DEPENDS system_lib +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +include_directories( +# include + ${catkin_INCLUDE_DIRS} +) + +## Declare a C++ library +# add_library(${PROJECT_NAME} +# src/${PROJECT_NAME}/object_detection.cpp +# ) + +## Add cmake target dependencies of the library +## as an example, code may need to be generated before libraries +## either from message generation or dynamic reconfigure +# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Declare a C++ executable +## With catkin_make all packages are built within a single CMake context +## The recommended prefix ensures that target names across packages don't collide +# add_executable(${PROJECT_NAME}_node src/object_detection_node.cpp) + +## Rename C++ executable without prefix +## The above recommended prefix causes long target names, the following renames the +## target back to the shorter version for ease of user use +## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" +# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") + +## Add cmake target dependencies of the executable +## same as for the library above +# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Specify libraries to link a library or executable target against +# target_link_libraries(${PROJECT_NAME}_node +# ${catkin_LIBRARIES} +# ) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_object_detection.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) +set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") diff --git a/Robot_Development/catkin_ws/object_detection/a.out b/Robot_Development/catkin_ws/object_detection/a.out new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Robot_Development/catkin_ws/object_detection/app b/Robot_Development/catkin_ws/object_detection/app new file mode 100755 index 0000000000000000000000000000000000000000..1ce1ce9a5c83444d2040ff4293414eab6545ba4f Binary files /dev/null and b/Robot_Development/catkin_ws/object_detection/app differ diff --git a/Robot_Development/catkin_ws/object_detection/blah.cpp b/Robot_Development/catkin_ws/object_detection/blah.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af0e4de448186b2313af5c2af2c28834233031ff --- /dev/null +++ b/Robot_Development/catkin_ws/object_detection/blah.cpp @@ -0,0 +1,64 @@ +#include<iostream> +#include<sstream> +#include<string> +#include<map> +using namespace std; + +class Detection { + public: + string _name; + float _prob; + int _cx; + int _cy; + int _w; + int _h; + Detection() { + + } + Detection(string name, float prob, int cx,int cy, int w, int h) { + _name = name; + _prob = prob; + _cx = cx; + _cy = cy; + _w = w; + _h = h; + } + Detection(string serialization) { + string whitespace = removeSpaces(&serialization[0]); + cout << whitespace << endl; + + } + string removeSpaces(char *str) + { + // To keep track of non-space character count + int count = 0; + + // Traverse the given string. If current character + // is not space, then place it at index 'count++' + for (int i = 0; str[i]; i++) + if (str[i] != ' ') + str[count++] = str[i]; // here count is + // incremented + str[count] = '\0'; + } + + string to_string() { + string s0 = "name=" + _name + ","; + string s1 = "prob=" + std::to_string(_prob) + ","; + string s2 = "cx=" + std::to_string(_cx) + ","; + string s3 = "cy=" + std::to_string(_cy) + ","; + string s4 = "w=" + std::to_string(_w) + ","; + string s5 = "h=" + std::to_string(_h) + ","; + string s = s0 + s1 + s2 + s3 + s4 + s5; + return s; + } +}; + + +int main() { + string str = "{ name : name , prob : 0.001, cx : 40, cy 40: , w : 40 , h : 40 }"; + cout << str << endl; + Detection d = Detection(str); + + return 0; +} diff --git a/Robot_Development/catkin_ws/object_detection/launch/object_detection.launch b/Robot_Development/catkin_ws/object_detection/launch/object_detection.launch new file mode 100644 index 0000000000000000000000000000000000000000..1189deeb71f684f9f178f4acf2280929cbf8d630 --- /dev/null +++ b/Robot_Development/catkin_ws/object_detection/launch/object_detection.launch @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<launch> + <node name="object_detection" pkg="object_detection" type="object_detect.py" output="screen"/> +</launch> diff --git a/Robot_Development/catkin_ws/object_detection/package.xml b/Robot_Development/catkin_ws/object_detection/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a686f8ae4b6a0c4b96b594dab2f8dd3c19c6125 --- /dev/null +++ b/Robot_Development/catkin_ws/object_detection/package.xml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<package format="2"> + <name>object_detection</name> + <version>0.0.0</version> + <description>The object_detection package</description> + + <!-- One maintainer tag required, multiple allowed, one person per tag --> + <!-- Example: --> + <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> + <maintainer email="nvidia@todo.todo">nvidia</maintainer> + + + <!-- One license tag required, multiple allowed, one license per tag --> + <!-- Commonly used license strings: --> + <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> + <license>TODO</license> + + + <!-- Url tags are optional, but multiple are allowed, one per tag --> + <!-- Optional attribute type can be: website, bugtracker, or repository --> + <!-- Example: --> + <!-- <url type="website">http://wiki.ros.org/object_detection</url> --> + + + <!-- Author tags are optional, multiple are allowed, one per tag --> + <!-- Authors do not have to be maintainers, but could be --> + <!-- Example: --> + <!-- <author email="jane.doe@example.com">Jane Doe</author> --> + + + <!-- The *depend tags are used to specify dependencies --> + <!-- Dependencies can be catkin packages or system dependencies --> + <!-- Examples: --> + <!-- Use depend as a shortcut for packages that are both build and exec dependencies --> + <!-- <depend>roscpp</depend> --> + <!-- Note that this is equivalent to the following: --> + <!-- <build_depend>roscpp</build_depend> --> + <!-- <exec_depend>roscpp</exec_depend> --> + <!-- Use build_depend for packages you need at compile time: --> + <!-- <build_depend>message_generation</build_depend> --> + <!-- Use build_export_depend for packages you need in order to build against this package: --> + <!-- <build_export_depend>message_generation</build_export_depend> --> + <!-- Use buildtool_depend for build tool packages: --> + <!-- <buildtool_depend>catkin</buildtool_depend> --> + <!-- Use exec_depend for packages you need at runtime: --> + <!-- <exec_depend>message_runtime</exec_depend> --> + <!-- Use test_depend for packages you need only for testing: --> + <!-- <test_depend>gtest</test_depend> --> + <!-- Use doc_depend for packages you need only for building documentation: --> + <!-- <doc_depend>doxygen</doc_depend> --> + <buildtool_depend>catkin</buildtool_depend> + <build_depend>roscpp</build_depend> + <build_depend>rospy</build_depend> + <build_depend>std_msgs</build_depend> + <build_export_depend>roscpp</build_export_depend> + <build_export_depend>rospy</build_export_depend> + <build_export_depend>std_msgs</build_export_depend> + <exec_depend>roscpp</exec_depend> + <exec_depend>rospy</exec_depend> + <exec_depend>std_msgs</exec_depend> + + + <!-- The export tag contains other, unspecified, tags --> + <export> + <!-- Other tools can request additional information be placed here --> + + </export> +</package> diff --git a/Robot_Development/catkin_ws/object_detection/src/bad.list b/Robot_Development/catkin_ws/object_detection/src/bad.list new file mode 100644 index 0000000000000000000000000000000000000000..a635cef13a0bb8e8be9ea0dea424201a4900d468 --- /dev/null +++ b/Robot_Development/catkin_ws/object_detection/src/bad.list @@ -0,0 +1,760 @@ +data/labels/32_0.png +data/labels/33_0.png +data/labels/34_0.png +data/labels/35_0.png +data/labels/36_0.png +data/labels/37_0.png +data/labels/38_0.png +data/labels/39_0.png +data/labels/40_0.png +data/labels/41_0.png +data/labels/42_0.png +data/labels/43_0.png +data/labels/44_0.png +data/labels/45_0.png +data/labels/46_0.png +data/labels/47_0.png +data/labels/48_0.png +data/labels/49_0.png +data/labels/50_0.png +data/labels/51_0.png +data/labels/52_0.png +data/labels/53_0.png +data/labels/54_0.png +data/labels/55_0.png +data/labels/56_0.png +data/labels/57_0.png +data/labels/58_0.png +data/labels/59_0.png +data/labels/60_0.png +data/labels/61_0.png +data/labels/62_0.png +data/labels/63_0.png +data/labels/64_0.png +data/labels/65_0.png +data/labels/66_0.png +data/labels/67_0.png +data/labels/68_0.png +data/labels/69_0.png +data/labels/70_0.png +data/labels/71_0.png +data/labels/72_0.png +data/labels/73_0.png +data/labels/74_0.png +data/labels/75_0.png +data/labels/76_0.png +data/labels/77_0.png +data/labels/78_0.png +data/labels/79_0.png +data/labels/80_0.png +data/labels/81_0.png +data/labels/82_0.png +data/labels/83_0.png +data/labels/84_0.png +data/labels/85_0.png +data/labels/86_0.png +data/labels/87_0.png +data/labels/88_0.png +data/labels/89_0.png +data/labels/90_0.png +data/labels/91_0.png +data/labels/92_0.png +data/labels/93_0.png +data/labels/94_0.png +data/labels/95_0.png +data/labels/96_0.png +data/labels/97_0.png +data/labels/98_0.png +data/labels/99_0.png +data/labels/100_0.png +data/labels/101_0.png +data/labels/102_0.png +data/labels/103_0.png +data/labels/104_0.png +data/labels/105_0.png +data/labels/106_0.png +data/labels/107_0.png +data/labels/108_0.png +data/labels/109_0.png +data/labels/110_0.png +data/labels/111_0.png +data/labels/112_0.png +data/labels/113_0.png +data/labels/114_0.png +data/labels/115_0.png +data/labels/116_0.png +data/labels/117_0.png +data/labels/118_0.png +data/labels/119_0.png +data/labels/120_0.png +data/labels/121_0.png +data/labels/122_0.png +data/labels/123_0.png +data/labels/124_0.png +data/labels/125_0.png +data/labels/126_0.png +data/labels/32_1.png +data/labels/33_1.png +data/labels/34_1.png +data/labels/35_1.png +data/labels/36_1.png +data/labels/37_1.png +data/labels/38_1.png +data/labels/39_1.png +data/labels/40_1.png +data/labels/41_1.png +data/labels/42_1.png +data/labels/43_1.png +data/labels/44_1.png +data/labels/45_1.png +data/labels/46_1.png +data/labels/47_1.png +data/labels/48_1.png +data/labels/49_1.png +data/labels/50_1.png +data/labels/51_1.png +data/labels/52_1.png +data/labels/53_1.png +data/labels/54_1.png +data/labels/55_1.png +data/labels/56_1.png +data/labels/57_1.png +data/labels/58_1.png +data/labels/59_1.png +data/labels/60_1.png +data/labels/61_1.png +data/labels/62_1.png +data/labels/63_1.png +data/labels/64_1.png +data/labels/65_1.png +data/labels/66_1.png +data/labels/67_1.png +data/labels/68_1.png +data/labels/69_1.png +data/labels/70_1.png +data/labels/71_1.png +data/labels/72_1.png +data/labels/73_1.png +data/labels/74_1.png +data/labels/75_1.png +data/labels/76_1.png +data/labels/77_1.png +data/labels/78_1.png +data/labels/79_1.png +data/labels/80_1.png +data/labels/81_1.png +data/labels/82_1.png +data/labels/83_1.png +data/labels/84_1.png +data/labels/85_1.png +data/labels/86_1.png +data/labels/87_1.png +data/labels/88_1.png +data/labels/89_1.png +data/labels/90_1.png +data/labels/91_1.png +data/labels/92_1.png +data/labels/93_1.png +data/labels/94_1.png +data/labels/95_1.png +data/labels/96_1.png +data/labels/97_1.png +data/labels/98_1.png +data/labels/99_1.png +data/labels/100_1.png +data/labels/101_1.png +data/labels/102_1.png +data/labels/103_1.png +data/labels/104_1.png +data/labels/105_1.png +data/labels/106_1.png +data/labels/107_1.png +data/labels/108_1.png +data/labels/109_1.png +data/labels/110_1.png +data/labels/111_1.png +data/labels/112_1.png +data/labels/113_1.png +data/labels/114_1.png +data/labels/115_1.png +data/labels/116_1.png +data/labels/117_1.png +data/labels/118_1.png +data/labels/119_1.png +data/labels/120_1.png +data/labels/121_1.png +data/labels/122_1.png +data/labels/123_1.png +data/labels/124_1.png +data/labels/125_1.png +data/labels/126_1.png +data/labels/32_2.png +data/labels/33_2.png +data/labels/34_2.png +data/labels/35_2.png +data/labels/36_2.png +data/labels/37_2.png +data/labels/38_2.png +data/labels/39_2.png +data/labels/40_2.png +data/labels/41_2.png +data/labels/42_2.png +data/labels/43_2.png +data/labels/44_2.png +data/labels/45_2.png +data/labels/46_2.png +data/labels/47_2.png +data/labels/48_2.png +data/labels/49_2.png +data/labels/50_2.png +data/labels/51_2.png +data/labels/52_2.png +data/labels/53_2.png +data/labels/54_2.png +data/labels/55_2.png +data/labels/56_2.png +data/labels/57_2.png +data/labels/58_2.png +data/labels/59_2.png +data/labels/60_2.png +data/labels/61_2.png +data/labels/62_2.png +data/labels/63_2.png +data/labels/64_2.png +data/labels/65_2.png +data/labels/66_2.png +data/labels/67_2.png +data/labels/68_2.png +data/labels/69_2.png +data/labels/70_2.png +data/labels/71_2.png +data/labels/72_2.png +data/labels/73_2.png +data/labels/74_2.png +data/labels/75_2.png +data/labels/76_2.png +data/labels/77_2.png +data/labels/78_2.png +data/labels/79_2.png +data/labels/80_2.png +data/labels/81_2.png +data/labels/82_2.png +data/labels/83_2.png +data/labels/84_2.png +data/labels/85_2.png +data/labels/86_2.png +data/labels/87_2.png +data/labels/88_2.png +data/labels/89_2.png +data/labels/90_2.png +data/labels/91_2.png +data/labels/92_2.png +data/labels/93_2.png +data/labels/94_2.png +data/labels/95_2.png +data/labels/96_2.png +data/labels/97_2.png +data/labels/98_2.png +data/labels/99_2.png +data/labels/100_2.png +data/labels/101_2.png +data/labels/102_2.png +data/labels/103_2.png +data/labels/104_2.png +data/labels/105_2.png +data/labels/106_2.png +data/labels/107_2.png +data/labels/108_2.png +data/labels/109_2.png +data/labels/110_2.png +data/labels/111_2.png +data/labels/112_2.png +data/labels/113_2.png +data/labels/114_2.png +data/labels/115_2.png +data/labels/116_2.png +data/labels/117_2.png +data/labels/118_2.png +data/labels/119_2.png +data/labels/120_2.png +data/labels/121_2.png +data/labels/122_2.png +data/labels/123_2.png +data/labels/124_2.png +data/labels/125_2.png +data/labels/126_2.png +data/labels/32_3.png +data/labels/33_3.png +data/labels/34_3.png +data/labels/35_3.png +data/labels/36_3.png +data/labels/37_3.png +data/labels/38_3.png +data/labels/39_3.png +data/labels/40_3.png +data/labels/41_3.png +data/labels/42_3.png +data/labels/43_3.png +data/labels/44_3.png +data/labels/45_3.png +data/labels/46_3.png +data/labels/47_3.png +data/labels/48_3.png +data/labels/49_3.png +data/labels/50_3.png +data/labels/51_3.png +data/labels/52_3.png +data/labels/53_3.png +data/labels/54_3.png +data/labels/55_3.png +data/labels/56_3.png +data/labels/57_3.png +data/labels/58_3.png +data/labels/59_3.png +data/labels/60_3.png +data/labels/61_3.png +data/labels/62_3.png +data/labels/63_3.png +data/labels/64_3.png +data/labels/65_3.png +data/labels/66_3.png +data/labels/67_3.png +data/labels/68_3.png +data/labels/69_3.png +data/labels/70_3.png +data/labels/71_3.png +data/labels/72_3.png +data/labels/73_3.png +data/labels/74_3.png +data/labels/75_3.png +data/labels/76_3.png +data/labels/77_3.png +data/labels/78_3.png +data/labels/79_3.png +data/labels/80_3.png +data/labels/81_3.png +data/labels/82_3.png +data/labels/83_3.png +data/labels/84_3.png +data/labels/85_3.png +data/labels/86_3.png +data/labels/87_3.png +data/labels/88_3.png +data/labels/89_3.png +data/labels/90_3.png +data/labels/91_3.png +data/labels/92_3.png +data/labels/93_3.png +data/labels/94_3.png +data/labels/95_3.png +data/labels/96_3.png +data/labels/97_3.png +data/labels/98_3.png +data/labels/99_3.png +data/labels/100_3.png +data/labels/101_3.png +data/labels/102_3.png +data/labels/103_3.png +data/labels/104_3.png +data/labels/105_3.png +data/labels/106_3.png +data/labels/107_3.png +data/labels/108_3.png +data/labels/109_3.png +data/labels/110_3.png +data/labels/111_3.png +data/labels/112_3.png +data/labels/113_3.png +data/labels/114_3.png +data/labels/115_3.png +data/labels/116_3.png +data/labels/117_3.png +data/labels/118_3.png +data/labels/119_3.png +data/labels/120_3.png +data/labels/121_3.png +data/labels/122_3.png +data/labels/123_3.png +data/labels/124_3.png +data/labels/125_3.png +data/labels/126_3.png +data/labels/32_4.png +data/labels/33_4.png +data/labels/34_4.png +data/labels/35_4.png +data/labels/36_4.png +data/labels/37_4.png +data/labels/38_4.png +data/labels/39_4.png +data/labels/40_4.png +data/labels/41_4.png +data/labels/42_4.png +data/labels/43_4.png +data/labels/44_4.png +data/labels/45_4.png +data/labels/46_4.png +data/labels/47_4.png +data/labels/48_4.png +data/labels/49_4.png +data/labels/50_4.png +data/labels/51_4.png +data/labels/52_4.png +data/labels/53_4.png +data/labels/54_4.png +data/labels/55_4.png +data/labels/56_4.png +data/labels/57_4.png +data/labels/58_4.png +data/labels/59_4.png +data/labels/60_4.png +data/labels/61_4.png +data/labels/62_4.png +data/labels/63_4.png +data/labels/64_4.png +data/labels/65_4.png +data/labels/66_4.png +data/labels/67_4.png +data/labels/68_4.png +data/labels/69_4.png +data/labels/70_4.png +data/labels/71_4.png +data/labels/72_4.png +data/labels/73_4.png +data/labels/74_4.png +data/labels/75_4.png +data/labels/76_4.png +data/labels/77_4.png +data/labels/78_4.png +data/labels/79_4.png +data/labels/80_4.png +data/labels/81_4.png +data/labels/82_4.png +data/labels/83_4.png +data/labels/84_4.png +data/labels/85_4.png +data/labels/86_4.png +data/labels/87_4.png +data/labels/88_4.png +data/labels/89_4.png +data/labels/90_4.png +data/labels/91_4.png +data/labels/92_4.png +data/labels/93_4.png +data/labels/94_4.png +data/labels/95_4.png +data/labels/96_4.png +data/labels/97_4.png +data/labels/98_4.png +data/labels/99_4.png +data/labels/100_4.png +data/labels/101_4.png +data/labels/102_4.png +data/labels/103_4.png +data/labels/104_4.png +data/labels/105_4.png +data/labels/106_4.png +data/labels/107_4.png +data/labels/108_4.png +data/labels/109_4.png +data/labels/110_4.png +data/labels/111_4.png +data/labels/112_4.png +data/labels/113_4.png +data/labels/114_4.png +data/labels/115_4.png +data/labels/116_4.png +data/labels/117_4.png +data/labels/118_4.png +data/labels/119_4.png +data/labels/120_4.png +data/labels/121_4.png +data/labels/122_4.png +data/labels/123_4.png +data/labels/124_4.png +data/labels/125_4.png +data/labels/126_4.png +data/labels/32_5.png +data/labels/33_5.png +data/labels/34_5.png +data/labels/35_5.png +data/labels/36_5.png +data/labels/37_5.png +data/labels/38_5.png +data/labels/39_5.png +data/labels/40_5.png +data/labels/41_5.png +data/labels/42_5.png +data/labels/43_5.png +data/labels/44_5.png +data/labels/45_5.png +data/labels/46_5.png +data/labels/47_5.png +data/labels/48_5.png +data/labels/49_5.png +data/labels/50_5.png +data/labels/51_5.png +data/labels/52_5.png +data/labels/53_5.png +data/labels/54_5.png +data/labels/55_5.png +data/labels/56_5.png +data/labels/57_5.png +data/labels/58_5.png +data/labels/59_5.png +data/labels/60_5.png +data/labels/61_5.png +data/labels/62_5.png +data/labels/63_5.png +data/labels/64_5.png +data/labels/65_5.png +data/labels/66_5.png +data/labels/67_5.png +data/labels/68_5.png +data/labels/69_5.png +data/labels/70_5.png +data/labels/71_5.png +data/labels/72_5.png +data/labels/73_5.png +data/labels/74_5.png +data/labels/75_5.png +data/labels/76_5.png +data/labels/77_5.png +data/labels/78_5.png +data/labels/79_5.png +data/labels/80_5.png +data/labels/81_5.png +data/labels/82_5.png +data/labels/83_5.png +data/labels/84_5.png +data/labels/85_5.png +data/labels/86_5.png +data/labels/87_5.png +data/labels/88_5.png +data/labels/89_5.png +data/labels/90_5.png +data/labels/91_5.png +data/labels/92_5.png +data/labels/93_5.png +data/labels/94_5.png +data/labels/95_5.png +data/labels/96_5.png +data/labels/97_5.png +data/labels/98_5.png +data/labels/99_5.png +data/labels/100_5.png +data/labels/101_5.png +data/labels/102_5.png +data/labels/103_5.png +data/labels/104_5.png +data/labels/105_5.png +data/labels/106_5.png +data/labels/107_5.png +data/labels/108_5.png +data/labels/109_5.png +data/labels/110_5.png +data/labels/111_5.png +data/labels/112_5.png +data/labels/113_5.png +data/labels/114_5.png +data/labels/115_5.png +data/labels/116_5.png +data/labels/117_5.png +data/labels/118_5.png +data/labels/119_5.png +data/labels/120_5.png +data/labels/121_5.png +data/labels/122_5.png +data/labels/123_5.png +data/labels/124_5.png +data/labels/125_5.png +data/labels/126_5.png +data/labels/32_6.png +data/labels/33_6.png +data/labels/34_6.png +data/labels/35_6.png +data/labels/36_6.png +data/labels/37_6.png +data/labels/38_6.png +data/labels/39_6.png +data/labels/40_6.png +data/labels/41_6.png +data/labels/42_6.png +data/labels/43_6.png +data/labels/44_6.png +data/labels/45_6.png +data/labels/46_6.png +data/labels/47_6.png +data/labels/48_6.png +data/labels/49_6.png +data/labels/50_6.png +data/labels/51_6.png +data/labels/52_6.png +data/labels/53_6.png +data/labels/54_6.png +data/labels/55_6.png +data/labels/56_6.png +data/labels/57_6.png +data/labels/58_6.png +data/labels/59_6.png +data/labels/60_6.png +data/labels/61_6.png +data/labels/62_6.png +data/labels/63_6.png +data/labels/64_6.png +data/labels/65_6.png +data/labels/66_6.png +data/labels/67_6.png +data/labels/68_6.png +data/labels/69_6.png +data/labels/70_6.png +data/labels/71_6.png +data/labels/72_6.png +data/labels/73_6.png +data/labels/74_6.png +data/labels/75_6.png +data/labels/76_6.png +data/labels/77_6.png +data/labels/78_6.png +data/labels/79_6.png +data/labels/80_6.png +data/labels/81_6.png +data/labels/82_6.png +data/labels/83_6.png +data/labels/84_6.png +data/labels/85_6.png +data/labels/86_6.png +data/labels/87_6.png +data/labels/88_6.png +data/labels/89_6.png +data/labels/90_6.png +data/labels/91_6.png +data/labels/92_6.png +data/labels/93_6.png +data/labels/94_6.png +data/labels/95_6.png +data/labels/96_6.png +data/labels/97_6.png +data/labels/98_6.png +data/labels/99_6.png +data/labels/100_6.png +data/labels/101_6.png +data/labels/102_6.png +data/labels/103_6.png +data/labels/104_6.png +data/labels/105_6.png +data/labels/106_6.png +data/labels/107_6.png +data/labels/108_6.png +data/labels/109_6.png +data/labels/110_6.png +data/labels/111_6.png +data/labels/112_6.png +data/labels/113_6.png +data/labels/114_6.png +data/labels/115_6.png +data/labels/116_6.png +data/labels/117_6.png +data/labels/118_6.png +data/labels/119_6.png +data/labels/120_6.png +data/labels/121_6.png +data/labels/122_6.png +data/labels/123_6.png +data/labels/124_6.png +data/labels/125_6.png +data/labels/126_6.png +data/labels/32_7.png +data/labels/33_7.png +data/labels/34_7.png +data/labels/35_7.png +data/labels/36_7.png +data/labels/37_7.png +data/labels/38_7.png +data/labels/39_7.png +data/labels/40_7.png +data/labels/41_7.png +data/labels/42_7.png +data/labels/43_7.png +data/labels/44_7.png +data/labels/45_7.png +data/labels/46_7.png +data/labels/47_7.png +data/labels/48_7.png +data/labels/49_7.png +data/labels/50_7.png +data/labels/51_7.png +data/labels/52_7.png +data/labels/53_7.png +data/labels/54_7.png +data/labels/55_7.png +data/labels/56_7.png +data/labels/57_7.png +data/labels/58_7.png +data/labels/59_7.png +data/labels/60_7.png +data/labels/61_7.png +data/labels/62_7.png +data/labels/63_7.png +data/labels/64_7.png +data/labels/65_7.png +data/labels/66_7.png +data/labels/67_7.png +data/labels/68_7.png +data/labels/69_7.png +data/labels/70_7.png +data/labels/71_7.png +data/labels/72_7.png +data/labels/73_7.png +data/labels/74_7.png +data/labels/75_7.png +data/labels/76_7.png +data/labels/77_7.png +data/labels/78_7.png +data/labels/79_7.png +data/labels/80_7.png +data/labels/81_7.png +data/labels/82_7.png +data/labels/83_7.png +data/labels/84_7.png +data/labels/85_7.png +data/labels/86_7.png +data/labels/87_7.png +data/labels/88_7.png +data/labels/89_7.png +data/labels/90_7.png +data/labels/91_7.png +data/labels/92_7.png +data/labels/93_7.png +data/labels/94_7.png +data/labels/95_7.png +data/labels/96_7.png +data/labels/97_7.png +data/labels/98_7.png +data/labels/99_7.png +data/labels/100_7.png +data/labels/101_7.png +data/labels/102_7.png +data/labels/103_7.png +data/labels/104_7.png +data/labels/105_7.png +data/labels/106_7.png +data/labels/107_7.png +data/labels/108_7.png +data/labels/109_7.png +data/labels/110_7.png +data/labels/111_7.png +data/labels/112_7.png +data/labels/113_7.png +data/labels/114_7.png +data/labels/115_7.png +data/labels/116_7.png +data/labels/117_7.png +data/labels/118_7.png +data/labels/119_7.png +data/labels/120_7.png +data/labels/121_7.png +data/labels/122_7.png +data/labels/123_7.png +data/labels/124_7.png +data/labels/125_7.png +data/labels/126_7.png diff --git a/Robot_Development/catkin_ws/object_detection/src/object_detect.py b/Robot_Development/catkin_ws/object_detection/src/object_detect.py new file mode 100755 index 0000000000000000000000000000000000000000..8641b48085082953a10c569a4e040de4c3d084e2 --- /dev/null +++ b/Robot_Development/catkin_ws/object_detection/src/object_detect.py @@ -0,0 +1,71 @@ +#!/usr/bin/python + +import numpy as np +import time +import csv +import json +import rospy +import matplotlib.pyplot as plt +import cv2 +from imutils.video import WebcamVideoStream +from imutils.video import FPS +from std_msgs.msg import String +from std_msgs.msg import Float64 + +pub = rospy.Publisher('object_detection', String, queue_size=10) +rospy.init_node('object_detection') +rate = rospy.Rate(500) # 10hz +width = 325 +detections_file_path = "/tmp/detections.csv" + +class Detection: + def __init__(self): + return None + # Constructor call + def __init__(self, name, prob, cx, cy, w, h): + self.vars = { "name" : name , "prob" : prob, "cx" : cx, "cy" : cy , "w" : w , "h" : h } + + def __str__(self): + s0 = "name:" + self.vars["name"] + ","; + s1 = "prob:" + self.vars["prob"] + ","; + s2 = "cx:" + self.vars["cx"] + "," + s3 = "cy:" + self.vars["cy"] + "," + s4 = "w:" + self.vars["w"] + "," + s5 = "h:" + self.vars["h"] + s = "{" + s0 + s1 + s2 + s3 + s4 + s5 + "}" + return s + +def main(): + while not rospy.is_shutdown(): + get_detections(detections_file_path) + +def publish_detection(detection): + rospy.loginfo(detection) + pub.publish(detection) + rate.sleep() + +def get_detections(fpath): + with open(fpath) as csv_file: + csv_reader = csv.reader(csv_file, delimiter=',') + line_count = 0 + time.sleep(0.05) + for row in csv_reader: + # print(row); + if(len(row) != 6): + print("row length != 6") + continue; + name = row[0] + prob = row[1] + c_x = row[2] + c_y = row[3] + w = row[4] + h = row[5] + d = Detection(name, prob, c_x, c_y, w, h) + obj = d.__str__(); + #print(obj); + publish_detection(obj) + +if __name__ == "__main__": + main() + + diff --git a/Robot_Development/catkin_ws/rosjet/TK1_Installation.pdf b/Robot_Development/catkin_ws/rosjet/TK1_Installation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7f16092aea5f4f2bb2f32a895e7e138bb255309b Binary files /dev/null and b/Robot_Development/catkin_ws/rosjet/TK1_Installation.pdf differ diff --git a/Robot_Development/catkin_ws/rosjet/TK1_README.pdf b/Robot_Development/catkin_ws/rosjet/TK1_README.pdf new file mode 100644 index 0000000000000000000000000000000000000000..67f6b39b91e5d3c882a76dc5862a0a1f80bdb49e Binary files /dev/null and b/Robot_Development/catkin_ws/rosjet/TK1_README.pdf differ diff --git a/Robot_Development/catkin_ws/rosjet/TX1_Installation.pdf b/Robot_Development/catkin_ws/rosjet/TX1_Installation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e36187b338acde8428263efc3a8ba86e3f746373 Binary files /dev/null and b/Robot_Development/catkin_ws/rosjet/TX1_Installation.pdf differ diff --git a/Robot_Development/catkin_ws/rosjet/TX1_README.pdf b/Robot_Development/catkin_ws/rosjet/TX1_README.pdf new file mode 100644 index 0000000000000000000000000000000000000000..01a216c06b9ade033c9bfebb374a7fdb8b5e0c6e Binary files /dev/null and b/Robot_Development/catkin_ws/rosjet/TX1_README.pdf differ diff --git a/Robot_Development/catkin_ws/rosjet/TX1_rosjet.rosinstall b/Robot_Development/catkin_ws/rosjet/TX1_rosjet.rosinstall new file mode 100644 index 0000000000000000000000000000000000000000..ff5778de1e5f37cfd3a032e1e01dcb2037c77752 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/TX1_rosjet.rosinstall @@ -0,0 +1,13 @@ +# Image Dependencies +- tar: + local-name: libraries/image_common/camera_info_manager + uri: https://github.com/ros-gbp/image_common-release/archive/release/kinetic/camera_info_manager/1.11.10-0.tar.gz + version: image_common-release-release-kinetic-camera_info_manager-1.11.10-0 +- tar: + local-name: libraries/image_common/image_transport + uri: https://github.com/ros-gbp/image_common-release/archive/release/kinetic/image_transport/1.11.10-0.tar.gz + version: image_common-release-release-kinetic-image_transport-1.11.10-0 +- tar: + local-name: libraries/vision_opencv/cv_bridge + uri: https://github.com/ros-gbp/vision_opencv-release/archive/release/kinetic/cv_bridge/1.11.12-0.tar.gz + version: vision_opencv-release-release-kinetic-cv_bridge-1.11.12-0 diff --git a/Robot_Development/catkin_ws/rosjet/TX1_rosjet_install.sh b/Robot_Development/catkin_ws/rosjet/TX1_rosjet_install.sh new file mode 100755 index 0000000000000000000000000000000000000000..50123084827ddf1b8ebe01e37a72d7f46c4f231a --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/TX1_rosjet_install.sh @@ -0,0 +1,134 @@ +#Ros Prerequisites +sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' +sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116 +sudo apt-get update + +#Ros installation (Kinetic for ubuntu 16.04) +sudo apt-get -y install ros-kinetic-ros-base --allow-unauthenticated + +#Python Dependencies +sudo apt-get -y install python-rosdep python-dev python-pip python-rosinstall python-wstool --allow-unauthenticated + +sudo c_rehash /etc/ssl/certs #TX1 has problems with the imaging of its certificates. If this step is not followed rosdep init will fail + +sudo rosdep init +rosdep update +echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc +source ~/.bashrc + +#Ros packages +sudo apt-get -y install ros-kinetic-rosserial-arduino --allow-unauthenticated +sudo apt-get -y install ros-kinetic-rosserial --allow-unauthenticated +sudo apt-get -y install ros-kinetic-eigen-conversions --allow-unauthenticated +sudo apt-get -y install ros-kinetic-tf2-geometry-msgs --allow-unauthenticated +sudo apt-get -y install ros-kinetic-angles --allow-unauthenticated +sudo apt-get -y install ros-kinetic-web-video-server --allow-unauthenticated +sudo apt-get -y install ros-kinetic-rosbridge-suite --allow-unauthenticated +sudo apt-get -y install ros-kinetic-rospy-tutorials --allow-unauthenticated +sudo apt-get -y install ros-kinetic-joy --allow-unauthenticated +sudo apt-get -y install ros-kinetic-teleop-twist-joy --allow-unauthenticated +sudo apt-get -y install ros-kinetic-roslint --allow-unauthenticated +sudo apt-get -y install ros-kinetic-controller-manager --allow-unauthenticated +sudo apt-get -y install ros-kinetic-camera-calibration-parsers --allow-unauthenticated +sudo apt-get -y install ros-kinetic-xacro --allow-unauthenticated +sudo apt-get -y install ros-kinetic-robot-state-publisher --allow-unauthenticated +sudo apt-get -y install ros-kinetic-diff-drive-controller --allow-unauthenticated +sudo apt-get -y install ros-kinetic-ros-control --allow-unauthenticated +sudo apt-get -y install ros-kinetic-dynamic-reconfigure --allow-unauthenticated +sudo apt-get -y install ros-kinetic-fake-localization --allow-unauthenticated +sudo apt-get -y install ros-kientic-joint-state-controller --allow-unauthenticated + +#USB_CAM package is not integrated in ROS Kinectic repository, you need to install it from source +cd ~/catkin_ws/src +git clone https://github.com/bosch-ros-pkg/usb_cam.git +cd .. + +# Configure Catkin Workspace +source /opt/ros/kinetic/setup.bash +cd ~/catkin_ws/src +catkin_init_workspace + +#Install Ros Opencv bindings from source (If the vision_opencv package fails compilation, please download it and move to your catkin workspace and catkin_make) +cd ~/catkin_ws +wstool init src src/rosjet/TX1_rosjet.rosinstall +wstool merge -t src src/rosjet/TX1_rosjet.rosinstall +wstool update -t src + +#Install Caffe +sudo add-apt-repository universe +sudo apt-get update -y +/bin/echo -e "\e[1;32mLoading Caffe Dependencies.\e[0m" +sudo apt-get install cmake -y +# General Dependencies +sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev \ +libhdf5-serial-dev protobuf-compiler -y +sudo apt-get install --no-install-recommends libboost-all-dev -y +# BLAS +sudo apt-get install libatlas-base-dev -y +# Remaining Dependencies +sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev -y +sudo apt-get install python-dev python-numpy -y + +sudo usermod -a -G video $USER +/bin/echo -e "\e[1;32mCloning Caffe into the home directory\e[0m" +# Place caffe in the home directory +cd $HOME +# Git clone Caffe +git clone https://github.com/BVLC/caffe.git +cd caffe +cp Makefile.config.example Makefile.config +# Regen the makefile; On 16.04, aarch64 has issues with a static cuda runtime +cmake -DCUDA_USE_STATIC_CUDA_RUNTIME=OFF +# Include the hdf5 directory for the includes; 16.04 has issues for some reason +echo "INCLUDE_DIRS += /usr/include/hdf5/serial/" >> Makefile.config +/bin/echo -e "\e[1;32mCompiling Caffe\e[0m" +make -j4 all + +# Run the tests to make sure everything works - This takes a really long time, so comment it if you want to run it later. +#/bin/echo -e "\e[1;32mRunning Caffe Tests\e[0m" +#make -j4 runtest + +# System Optimizations +gsettings set org.gnome.settings-daemon.plugins.power button-power shutdown +gsettings set org.gnome.desktop.screensaver lock-enabled false +sudo apt-get -y install compizconfig-settings-manager +gsettings set org.gnome.desktop.interface enable-animations false +gsettings set com.canonical.Unity.Lenses remote-content-search none +echo -e '[SeatDefaults]\nautologin-user=ubuntu' > login_file; sudo mv login_file /etc/lightdm/lightdm.conf +gsettings set org.gnome.Vino enabled true +gsettings set org.gnome.Vino disable-background true +gsettings set org.gnome.Vino prompt-enabled false +gsettings set org.gnome.Vino require-encryption false + +echo "alias sr='source ~/catkin_ws/devel/setup.bash'" >> ~/.bashrc + +cd ~/catkin_ws +catkin_make && source devel/setup.sh + +#Before starting with ROS, you might want to remove OpenCV4Tegra if you had flashed that from JetPack, and install OpenCV 3.1 instead as there are some configurations issues that needs to be resolved for using OpenCV4Tegra with ROS Kinetic. (Note: OpenCV4Tegra is designed in such a way that it utilizes the power of the Nvidia GPU. OpenCV 3.1 only uses CPU.) +#Comment out all the lines from below if you want to continue with OpenCV4Tegra. + +#Uninstalling OpenCV4Tegra +sudo apt-get purge libopencv4tegra-dev libopencv4tegra +sudo apt-get purge libopencv4tegra-repo +sudo apt-get update + +#OpenCV 3.1 Installation +sudo apt-get install build-essential +sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev +sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev +sudo apt-get install python2.7-dev +sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev +sudo apt-get install libgtkglext1 libgtkglext1-dev +sudo apt-get install qtbase5-dev +sudo apt-get install libv4l-dev v4l-utils qv4l2 v4l2ucp +git clone https://github.com/opencv/opencv.git +curl -L https://github.com/opencv/opencv/archive/3.2.0.zip -o opencv-3.2.0.zip +unzip opencv-3.2.0.zip +cd opencv-3.2.0 +mkdir release +cd release +cmake -D WITH_CUDA=ON -D CUDA_ARCH_BIN="5.3" -D CUDA_ARCH_PTX="" -D WITH_OPENGL=ON -D WITH_LIBV4L=ON -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .. +make -j4 +sudo make install + diff --git a/Robot_Development/catkin_ws/rosjet/jet_bringup/CMakeLists.txt b/Robot_Development/catkin_ws/rosjet/jet_bringup/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..131c9d09f82adfc95c5d17ab50ea0d48ad863cb9 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_bringup/CMakeLists.txt @@ -0,0 +1,181 @@ +cmake_minimum_required(VERSION 2.8.3) +project(jet_bringup) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED) + +## System dependencies are found with CMake's conventions +# find_package(Boost REQUIRED COMPONENTS system) + + +## Uncomment this if the package has a setup.py. This macro ensures +## modules and global scripts declared therein get installed +## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html +# catkin_python_setup() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +## To declare and build messages, services or actions from within this +## package, follow these steps: +## * Let MSG_DEP_SET be the set of packages whose message types you use in +## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). +## * In the file package.xml: +## * add a build_depend tag for "message_generation" +## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET +## * If MSG_DEP_SET isn't empty the following dependency has been pulled in +## but can be declared for certainty nonetheless: +## * add a run_depend tag for "message_runtime" +## * In this file (CMakeLists.txt): +## * add "message_generation" and every package in MSG_DEP_SET to +## find_package(catkin REQUIRED COMPONENTS ...) +## * add "message_runtime" and every package in MSG_DEP_SET to +## catkin_package(CATKIN_DEPENDS ...) +## * uncomment the add_*_files sections below as needed +## and list every .msg/.srv/.action file to be processed +## * uncomment the generate_messages entry below +## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) + +## Generate messages in the 'msg' folder +# add_message_files( +# FILES +# Message1.msg +# Message2.msg +# ) + +## Generate services in the 'srv' folder +# add_service_files( +# FILES +# Service1.srv +# Service2.srv +# ) + +## Generate actions in the 'action' folder +# add_action_files( +# FILES +# Action1.action +# Action2.action +# ) + +## Generate added messages and services with any dependencies listed here +# generate_messages( +# DEPENDENCIES +# std_msgs # Or other packages containing msgs +# ) + +################################################ +## Declare ROS dynamic reconfigure parameters ## +################################################ + +## To declare and build dynamic reconfigure parameters within this +## package, follow these steps: +## * In the file package.xml: +## * add a build_depend and a run_depend tag for "dynamic_reconfigure" +## * In this file (CMakeLists.txt): +## * add "dynamic_reconfigure" to +## find_package(catkin REQUIRED COMPONENTS ...) +## * uncomment the "generate_dynamic_reconfigure_options" section below +## and list every .cfg file to be processed + +## Generate dynamic reconfigure parameters in the 'cfg' folder +# generate_dynamic_reconfigure_options( +# cfg/DynReconf1.cfg +# cfg/DynReconf2.cfg +# ) + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if you package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES jet_bringup +# CATKIN_DEPENDS other_catkin_pkg +# DEPENDS system_lib +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +# include_directories(include) + +## Declare a C++ library +# add_library(jet_bringup +# src/${PROJECT_NAME}/jet_bringup.cpp +# ) + +## Add cmake target dependencies of the library +## as an example, code may need to be generated before libraries +## either from message generation or dynamic reconfigure +# add_dependencies(jet_bringup ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Declare a C++ executable +# add_executable(jet_bringup_node src/jet_bringup_node.cpp) + +## Add cmake target dependencies of the executable +## same as for the library above +# add_dependencies(jet_bringup_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) + +## Specify libraries to link a library or executable target against +# target_link_libraries(jet_bringup_node +# ${catkin_LIBRARIES} +# ) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +# install(TARGETS jet_bringup jet_bringup_node +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_jet_bringup.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) diff --git a/Robot_Development/catkin_ws/rosjet/jet_bringup/launch/jet_gazebo.launch b/Robot_Development/catkin_ws/rosjet/jet_bringup/launch/jet_gazebo.launch new file mode 100644 index 0000000000000000000000000000000000000000..e5a1eff69f64691ae54bd418d418e78505a2a264 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_bringup/launch/jet_gazebo.launch @@ -0,0 +1,8 @@ +<launch> + <include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" /> + + <include file="$(find jet_description)/launch/jet_upload.launch"/> + + <include file="$(find jet_control)/launch/jet_control.launch"/> + +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_bringup/launch/jet_real.launch b/Robot_Development/catkin_ws/rosjet/jet_bringup/launch/jet_real.launch new file mode 100644 index 0000000000000000000000000000000000000000..0c65c755fdd061ff242ec4eadf564f546b42b16c --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_bringup/launch/jet_real.launch @@ -0,0 +1,29 @@ +<launch> + + <include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" /> + <include file="$(find jet_serial)/launch/jet_serial.launch" /> + + <node pkg="joy" type="joy_node" name="joy_node"> + <param name="dev" value="/dev/input/js4" /> + <param name="deadzone" value="0.2" /> + <param name="autorepeat_rate" value="20" /> + </node> + + <node pkg="teleop_twist_joy" name="teleop_twist_joy" type="teleop_node"> + <param name="axis_linear" value="1" /> + <param name="axis_angular" value="0" /> + <param name="scale_linear" value="1" /> + <param name="scale_angular" value="-2.5" /> + </node> + + <include file="$(find jet_description)/launch/jet_upload.launch"/> + + <include file="$(find jet_control)/launch/jet_control.launch"/> + + <include file="$(find jet_driver)/launch/jet_driver.launch"/> + + <include file="$(find lane_detection)/launch/lane_detection.launch"/> + + <include file="$(find object_detection)/launch/object_detection.launch"/> + +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_bringup/package.xml b/Robot_Development/catkin_ws/rosjet/jet_bringup/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..70af591263034685b763eb31376b169001382bb1 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_bringup/package.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<package> + <name>jet_bringup</name> + <version>1.1.6</version> + <description> + Launch scripts for Jet Robot + </description> + + <author>Jeremy Kerfs</author> + <author email="jkerfs@calpoly.edu">Jeremy Kerfs</author> + <maintainer email="jkerfs@calpoly.edu">Jeremy Kerfs</maintainer> + + <license>MIT</license> + + <buildtool_depend>catkin</buildtool_depend> + <run_depend>urdf</run_depend> + + <export> + </export> +</package> diff --git a/Robot_Development/catkin_ws/rosjet/jet_control/CMakeLists.txt b/Robot_Development/catkin_ws/rosjet/jet_control/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..cafe4c0aac887e99f126a0e1ebfc378d71019bc2 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_control/CMakeLists.txt @@ -0,0 +1,15 @@ + +cmake_minimum_required(VERSION 2.8.3) +project(jet_control) + +find_package(catkin REQUIRED) + +catkin_package() + +install(DIRECTORY config + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) + +install(DIRECTORY launch + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) + + diff --git a/Robot_Development/catkin_ws/rosjet/jet_control/config/jet_control.yaml b/Robot_Development/catkin_ws/rosjet/jet_control/config/jet_control.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2dcf021cb359613152f3e9322b3ff5a5951998fb --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_control/config/jet_control.yaml @@ -0,0 +1,46 @@ + # Publish all joint states ----------------------------------- +joint_state_controller: + type: joint_state_controller/JointStateController + publish_rate: 50 + + # Position Controllers --------------------------------------- +jet_drive_controller: + #type: "icart_mini_controller/ICartMiniController" + type : "diff_drive_controller/DiffDriveController" + left_wheel : 'left_wheel_joint' + right_wheel : 'right_wheel_joint' + publish_rate: 100 + + enable_odom_tf: true + + pose_covariance_diagonal : [0.00001, 0.00001, 1000000000000.0, 1000000000000.0, 1000000000000.0, 0.001] + twist_covariance_diagonal: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + + # Wheel separation and radius multipliers + wheel_separation: .39 + wheel_radius: .077 + wheel_separation_multiplier: 1.0 # default: 1.0 + wheel_radius_multiplier : 1.0 # default: 1.0 + + # Velocity commands timeout [s], default 0.5 + cmd_vel_timeout: 1.0 + + # Base frame_id + base_frame_id: base_link + + # Velocity and acceleration limits + # Whenever a min_* is unspecified, default to -max_* + linear: + x: + has_velocity_limits : true + max_velocity : 0.9 # m/s + min_velocity : -0.9 # m/s + has_acceleration_limits: false + #max_acceleration : 1.7 # m/s^2 + #min_acceleration : -0.4 # m/s^2 + angular: + z: + has_velocity_limits : false + #max_velocity : 0.5 # rad/s + has_acceleration_limits: false + #max_acceleration : 1.5 # rad/s^2 diff --git a/Robot_Development/catkin_ws/rosjet/jet_control/launch/jet_control.launch b/Robot_Development/catkin_ws/rosjet/jet_control/launch/jet_control.launch new file mode 100644 index 0000000000000000000000000000000000000000..208fe76134433f553f2595ff3fc0d51ea266554d --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_control/launch/jet_control.launch @@ -0,0 +1,18 @@ +<launch> + + <!-- Load joint controller configurations from YAML file to parameter server --> + <rosparam file="$(find jet_control)/config/jet_control.yaml" command="load"/> + + <!-- load the controllers --> + <node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false" + output="screen" args="jet_drive_controller joint_state_controller"/> + + <!-- convert joint states to TF transforms for rviz, etc --> + <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" + respawn="false" output="screen"> + </node> + + <node name="cmdvelrelay" pkg="topic_tools" type="relay" args="/cmd_vel /jet_drive_controller/cmd_vel"/> + <node name="odomrelay" pkg="topic_tools" type="relay" args="/jet_drive_controller/odom /odom"/> + +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_control/package.xml b/Robot_Development/catkin_ws/rosjet/jet_control/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..470902fb3c6e45a2eacf5a11ce5264c3d91eccae --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_control/package.xml @@ -0,0 +1,60 @@ +<?xml version="1.0"?> +<package> + <name>jet_control</name> + <version>0.0.0</version> + <description>The jet_control package</description> + + <!-- One maintainer tag required, multiple allowed, one person per tag --> + <!-- Example: --> + <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> + <maintainer email="jeremy@todo.todo">jeremy</maintainer> + + + <!-- One license tag required, multiple allowed, one license per tag --> + <!-- Commonly used license strings: --> + <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> + <license>TODO</license> + + + <!-- Url tags are optional, but mutiple are allowed, one per tag --> + <!-- Optional attribute type can be: website, bugtracker, or repository --> + <!-- Example: --> + <!-- <url type="website">http://wiki.ros.org/jet_control</url> --> + + + <!-- Author tags are optional, mutiple are allowed, one per tag --> + <!-- Authors do not have to be maintianers, but could be --> + <!-- Example: --> + <!-- <author email="jane.doe@example.com">Jane Doe</author> --> + + + <!-- The *_depend tags are used to specify dependencies --> + <!-- Dependencies can be catkin packages or system dependencies --> + <!-- Examples: --> + <!-- Use build_depend for packages you need at compile time: --> + <!-- <build_depend>message_generation</build_depend> --> + <!-- Use buildtool_depend for build tool packages: --> + <!-- <buildtool_depend>catkin</buildtool_depend> --> + <!-- Use run_depend for packages you need at runtime: --> + <!-- <run_depend>message_runtime</run_depend> --> + <!-- Use test_depend for packages you need only for testing: --> + <!-- <test_depend>gtest</test_depend> --> + <buildtool_depend>catkin</buildtool_depend> + <build_depend>controller_interface</build_depend> + <build_depend>diff_drive_controller</build_depend> + + <run_depend>diff_drive_controller</run_depend> + <run_depend>controller_manager</run_depend> + <run_depend>joint_state_controller</run_depend> + <run_depend>robot_state_publisher</run_depend> + <run_depend>controller_interface</run_depend> + <run_depend>rqt_gui</run_depend> + <run_depend>effort_controllers</run_depend> + + + <!-- The export tag contains other, unspecified, tags --> + <export> + <!-- Other tools can request additional information be placed here --> + + </export> +</package> diff --git a/Robot_Development/catkin_ws/rosjet/jet_description/CMakeLists.txt b/Robot_Development/catkin_ws/rosjet/jet_description/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..972e7b1e3b4946c78c70689c31c6861c462f28fe --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_description/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.3) +project(jet_description) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED) + +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES ur_description +# CATKIN_DEPENDS urdf +# DEPENDS system_lib +) + + +install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) +install(DIRECTORY urdf DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) +#install(DIRECTORY meshes DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) diff --git a/Robot_Development/catkin_ws/rosjet/jet_description/launch/jet_rviz.launch b/Robot_Development/catkin_ws/rosjet/jet_description/launch/jet_rviz.launch new file mode 100644 index 0000000000000000000000000000000000000000..d2f690ad8a8424953dd968f5a7c5a4193c255fc4 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_description/launch/jet_rviz.launch @@ -0,0 +1,18 @@ +<launch> + <!-- send robot urdf to param server --> + <include file="$(find jet_description)/launch/jet_upload.launch"> + </include> + + <!-- send fake joint values --> + <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"> + <param name="use_gui" value="TRUE"/> + </node> + + <!-- Combine joint values --> + <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher"/> + + <!-- Show in Rviz + <node name="rviz" pkg="rviz" type="rviz" args="-d $(find jet_description)/launch/jet.rviz"/> + --> + +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_description/launch/jet_upload.launch b/Robot_Development/catkin_ws/rosjet/jet_description/launch/jet_upload.launch new file mode 100644 index 0000000000000000000000000000000000000000..144f0795d4b33f22a30fab6dfaff5a4bb32721b8 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_description/launch/jet_upload.launch @@ -0,0 +1,7 @@ +<?xml version="1.0"?> +<launch> +<!-- Convert an xacro and put on parameter server --> +<param name="robot_description" + command="$(find xacro)/xacro.py '$(find jet_description)/urdf/jet.xacro'" /> + +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_description/package.xml b/Robot_Development/catkin_ws/rosjet/jet_description/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..fc11645d5fe94486a3169d4e897767514d1ed088 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_description/package.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<package> + <name>jet_description</name> + <version>1.1.6</version> + <description> + URDF description for Jet Robot + </description> + + <author>Jeremy Kerfs</author> + <author email="jkerfs@calpoly.edu">Jeremy Kerfs</author> + <maintainer email="jkerfs@calpoly.edu">Jeremy Kerfs</maintainer> + + <license>MIT</license> + + <buildtool_depend>catkin</buildtool_depend> + <run_depend>urdf</run_depend> + + <export> + </export> +</package> diff --git a/Robot_Development/catkin_ws/rosjet/jet_description/urdf/jet.gazebo b/Robot_Development/catkin_ws/rosjet/jet_description/urdf/jet.gazebo new file mode 100644 index 0000000000000000000000000000000000000000..b9d7b5f5a0d084c2b9b530d94df3df46dfa8da49 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_description/urdf/jet.gazebo @@ -0,0 +1,186 @@ +<?xml version="1.0"?> +<robot> + <gazebo> + <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so"> + <robotNamespace>/</robotNamespace> + <robotSimType>gazebo_ros_control/DefaultRobotHWSim</robotSimType> + </plugin> + </gazebo> + + <gazebo reference="base_link"> + <material>Gazebo/Green</material> + </gazebo> + <gazebo reference="right_wheel"> + <material>Gazebo/Grey</material> + </gazebo> + <gazebo reference="left_wheel"> + <material>Gazebo/Grey</material> + </gazebo> + <gazebo reference="camera_link"> + <material>Gazebo/Red</material> + </gazebo> + + <gazebo reference="camera_link"> + <sensor type="camera" name="camera1"> + <update_rate>30.0</update_rate> + <camera name="head"> + <pose>0.0 0.0 0.0 0.0 0.0 -1.57075</pose> + <horizontal_fov>1.3962634</horizontal_fov> + <image> + <width>800</width> + <height>800</height> + <format>R8G8B8</format> + </image> + <clip> + <near>0.02</near> + <far>300</far> + </clip> + <noise> + <type>gaussian</type> + <mean>0.0</mean> + <stddev>0.007</stddev> + </noise> + </camera> + <plugin name="camera_controller" filename="libgazebo_ros_camera.so"> + <alwaysOn>true</alwaysOn> + <updateRate>0.0</updateRate> + <cameraName>camera1</cameraName> + <imageTopicName>image_raw</imageTopicName> + <cameraInfoTopicName>camera_info</cameraInfoTopicName> + <frameName>camera_link</frameName> + <hackBaseline>0.07</hackBaseline> + <distortionK1>0.0</distortionK1> + <distortionK2>0.0</distortionK2> + <distortionK3>0.0</distortionK3> + <distortionT1>0.0</distortionT1> + <distortionT2>0.0</distortionT2> + </plugin> + </sensor> + </gazebo> + + <gazebo reference="sonar1_link"> + <sensor type="ray" name="sonar1"> + <pose>0 0 0 0 0 0</pose> + <update_rate>5</update_rate> + <ray> + <scan> + <horizontal> + <samples>5</samples> + <resolution>1.0</resolution> + <min_angle>-0.25</min_angle> + <max_angle>0.25</max_angle> + </horizontal> + <vertical> + <samples>5</samples> + <resolution>1</resolution> + <min_angle>-0.25</min_angle> + <max_angle>0.25</max_angle> + </vertical> + </scan> + <range> + <min>0.01</min> + <max>3.00</max> + <resolution>0.01</resolution> + </range> + </ray> + <plugin filename="libgazebo_ros_range.so" name="gazebo_ros_range1"> + <gaussianNoise>0.005</gaussianNoise> + <alwaysOn>true</alwaysOn> + <updateRate>5</updateRate> + <topicName>sonar1</topicName> + <frameName>sonar1_link</frameName> + <fov>.5</fov> + <radiation>ultrasound</radiation> + </plugin> + </sensor> + </gazebo> + + <gazebo reference="sonar2_link"> + <sensor type="ray" name="sonar1"> + <pose>0 0 0 0 0 0</pose> + <update_rate>5</update_rate> + <ray> + <scan> + <horizontal> + <samples>5</samples> + <resolution>1.0</resolution> + <min_angle>-0.25</min_angle> + <max_angle>0.25</max_angle> + </horizontal> + <vertical> + <samples>5</samples> + <resolution>1</resolution> + <min_angle>-0.25</min_angle> + <max_angle>0.25</max_angle> + </vertical> + </scan> + <range> + <min>0.01</min> + <max>3.00</max> + <resolution>0.01</resolution> + </range> + </ray> + <plugin filename="libgazebo_ros_range.so" name="gazebo_ros_range2"> + <gaussianNoise>0.005</gaussianNoise> + <alwaysOn>true</alwaysOn> + <updateRate>5</updateRate> + <topicName>sonar2</topicName> + <frameName>sonar2_link</frameName> + <fov>.5</fov> + <radiation>ultrasound</radiation> + </plugin> + </sensor> + </gazebo> + + <gazebo reference="sonar3_link"> + <sensor type="ray" name="sonar1"> + <pose>0 0 0 0 0 0</pose> + <update_rate>5</update_rate> + <ray> + <scan> + <horizontal> + <samples>5</samples> + <resolution>1.0</resolution> + <min_angle>-0.25</min_angle> + <max_angle>0.25</max_angle> + </horizontal> + <vertical> + <samples>5</samples> + <resolution>1</resolution> + <min_angle>-0.25</min_angle> + <max_angle>0.25</max_angle> + </vertical> + </scan> + <range> + <min>0.01</min> + <max>3.00</max> + <resolution>0.01</resolution> + </range> + </ray> + <plugin filename="libgazebo_ros_range.so" name="gazebo_ros_range3"> + <gaussianNoise>0.005</gaussianNoise> + <alwaysOn>true</alwaysOn> + <updateRate>5</updateRate> + <topicName>sonar3</topicName> + <frameName>sonar3_link</frameName> + <fov>.5</fov> + <radiation>ultrasound</radiation> + </plugin> + </sensor> + </gazebo> + + <gazebo> + + <plugin name="imu_controller" filename="libhector_gazebo_ros_imu.so"> + <alwaysOn>true</alwaysOn> + <updateRate>50.0</updateRate> + <bodyName>gyro_link</bodyName> + <topicName>imu_data</topicName> + <gaussianNoise>2.89e-08</gaussianNoise> + <xyzOffsets>0 0 0</xyzOffsets> + <rpyOffsets>0 0 0</rpyOffsets> + </plugin> + + </gazebo> + +</robot> diff --git a/Robot_Development/catkin_ws/rosjet/jet_description/urdf/jet.xacro b/Robot_Development/catkin_ws/rosjet/jet_description/urdf/jet.xacro new file mode 100644 index 0000000000000000000000000000000000000000..f6597b33d9f263e579aa714ea70418f9358d3d02 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_description/urdf/jet.xacro @@ -0,0 +1,254 @@ +<?xml version="1.0"?> +<robot name="Jet" xmlns:xacro="http://www.ros.org/wiki/xacro"> + + <!-- Import all Gazebo-customization elements, including Gazebo colors --> + <xacro:include filename="$(find jet_description)/urdf/jet.gazebo"/> + <!-- Import Rviz colors --> + <xacro:include filename="$(find jet_description)/urdf/materials.xacro"/> + + <link name="base_link"> + </link> + + <link name="body_link"> + <visual> + <origin rpy="0 0 0" xyz="0 0 0"/> + <geometry> + <box size=".35 .25 .05"/> + </geometry> + <material name="green"> + <color rgba="0 .8 .0 .8"/> + </material> + </visual> + <collision> + <origin rpy="0 0 0" xyz="0 0 0"/> + <geometry> + <box size=".35 .25 .05"/> + </geometry> + </collision> + <inertial> + <mass value="1"/> + <inertia ixx="1e-3" ixy="0.0" ixz="0.0" iyy="1e-3" iyz="0.0" izz="1e-3"/> + </inertial> + </link> + + <link name="caster"> + <visual name='caster_visual'> + <origin rpy="0 0 0" xyz="0 0 0"/> + <geometry> + <cylinder radius="0.03" length="0.12"/> + </geometry> + </visual> + <collision name='caster_collision'> + <origin rpy="0 0 0" xyz="0 0 0"/> + <geometry> + <cylinder radius="0.03" length="0.12"/> + </geometry> + + <surface> + <friction> + <ode> + <mu>0</mu> + <mu2>0</mu2> + <slip1>1.0</slip1> + <slip2>1.0</slip2> + </ode> + </friction> + </surface> + </collision> + <inertial> + <mass value="10"/> + <inertia ixx=".01425" ixy="0.0" ixz="0.0" iyy=".01425" iyz="0.0" izz=".0045"/> + </inertial> + </link> + + <link name="right_wheel"> + <visual> + <geometry> + <cylinder length="0.03" radius="0.1"/> + </geometry> + <origin rpy="0 1.57075 1.57075" xyz="0 0 0"/> + <material name="gray"> + <color rgba=".1 .1 .1 1"/> + </material> + </visual> + <collision> + <geometry> + <cylinder length="0.03" radius="0.1"/> + </geometry> + <origin rpy="0 1.57075 1.57075" xyz="0 0 0"/> + </collision> + <inertial> + <mass value="1"/> + <inertia ixx="1e-3" ixy="0.0" ixz="0.0" iyy="1e-3" iyz="0.0" izz="1e-3"/> + </inertial> + </link> + + <link name="left_wheel"> + <visual> + <geometry> + <cylinder length="0.03" radius="0.1"/> + </geometry> + <origin rpy="0 1.57075 1.57075" xyz="0 0 0"/> + <material name="gray"> + <color rgba=".1 .1 .1 1"/> + </material> + </visual> + <collision> + <geometry> + <cylinder length="0.03" radius="0.1"/> + </geometry> + <origin rpy="0 1.57075 1.57075" xyz="0 0 0"/> + </collision> + <inertial> + <mass value="10"/> + <inertia ixx="1e-3" ixy="0.0" ixz="0.0" iyy="1e-3" iyz="0.0" izz="1e-3"/> + </inertial> + </link> + + <link name="sonar1_link"> + <inertial> + <mass value="1e-5" /> + <origin xyz="0 0 0" rpy="0 0 0"/> + <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" /> + </inertial> + </link> + + <link name="sonar2_link"> + <inertial> + <mass value="1e-5" /> + <origin xyz="0 0 0" rpy="0 0 0"/> + <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" /> + </inertial> + </link> + + <link name="sonar3_link"> + <inertial> + <mass value="1e-5" /> + <origin xyz="0 0 0" rpy="0 0 0"/> + <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" /> + </inertial> + </link> + + <link name="camera_link"> + <collision> + <origin xyz="0 0 0" rpy="0 0 0"/> + <geometry> + <box size=".05 .02 .05"/> + </geometry> + </collision> + + <visual> + <origin xyz="0 0 0" rpy="0 0 0"/> + <geometry> + <box size=".05 .02 .05"/> + </geometry> + <material name="red"> + <color rgba="1.0 0 0 1"/> + </material> + </visual> + + <inertial> + <mass value="1e-5" /> + <origin xyz="0 0 0" rpy="0 0 0"/> + <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" /> + </inertial> + </link> + + + <link name="gyro_link"> + <inertial> + <mass value="0.001"/> + <origin rpy="0 0 0" xyz="0 0 0"/> + <inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.000001" iyz="0" izz="0.0001"/> + </inertial> + </link> + + <joint name="body_base" type="fixed"> + <axis xyz="1 0 0"/> + <origin xyz="0 0 0"/> + <parent link="base_link"/> + <child link="body_link"/> + </joint> + + <joint name="imu_joint" type="fixed"> + <axis xyz="1 0 0"/> + <origin xyz="0 0 0"/> + <parent link="body_link"/> + <child link="gyro_link"/> + </joint> + + <joint name="sonar1_joint" type="fixed"> + <axis xyz="0 1 0" /> + <origin xyz="-.1 -.15 -.05" rpy="0 0 -2.356125"/> + <parent link="body_link"/> + <child link="sonar1_link"/> + </joint> + + <joint name="sonar2_joint" type="fixed"> + <axis xyz="0 1 0" /> + <origin xyz="0 -.15 -.05" rpy="0 0 -1.57075"/> + <parent link="body_link"/> + <child link="sonar2_link"/> + </joint> + + <joint name="sonar3_joint" type="fixed"> + <axis xyz="0 1 0" /> + <origin xyz=".1 -.15 -.05" rpy="0 0 -.785375"/> + <parent link="body_link"/> + <child link="sonar3_link"/> + </joint> + + <joint name="camera_joint" type="fixed"> + <axis xyz="1 0 0" /> + <origin xyz=".15 0 .05" rpy="0 0 0"/> + <parent link="body_link"/> + <child link="camera_link"/> + </joint> + + <joint name="caster_base_joint" type="fixed"> + <parent link="body_link"/> + <child link="caster"/> + <origin xyz="-.15 0 -.05"/> + <axis xyz="0 0 1"/> + </joint> + + <joint name="right_wheel_joint" type="revolute"> + <parent link="body_link"/> + <child link="right_wheel"/> + <origin xyz="0.08 -.15 -.03"/> + <axis xyz="0 1 0"/> + <limit effort="100" velocity="100.0" lower="-5000" upper="5000" /> + </joint> + + <joint name="left_wheel_joint" type="revolute"> + <parent link="body_link"/> + <child link="left_wheel"/> + <origin xyz="0.08 .15 -.03"/> + <axis xyz="0 1 0"/> + <limit effort="100" velocity="100.0" lower="-5000" upper="5000"/> + </joint> + + <transmission name="tran_left_wheel"> + <type>transmission_interface/SimpleTransmission</type> + <joint name="left_wheel_joint"> + <hardwareInterface>VelocityJointInterface</hardwareInterface> + </joint> + <actuator name="motor_left"> + <hardwareInterface>VelocityJointInterface</hardwareInterface> + <mechanicalReduction>1</mechanicalReduction> + </actuator> + </transmission> + + <transmission name="tran_right_wheel"> + <type>transmission_interface/SimpleTransmission</type> + <joint name="right_wheel_joint"> + <hardwareInterface>VelocityJointInterface</hardwareInterface> + </joint> + <actuator name="motor_right"> + <hardwareInterface>VelocityJointInterface</hardwareInterface> + <mechanicalReduction>1</mechanicalReduction> + </actuator> + </transmission> + +</robot> + diff --git a/Robot_Development/catkin_ws/rosjet/jet_description/urdf/materials.xacro b/Robot_Development/catkin_ws/rosjet/jet_description/urdf/materials.xacro new file mode 100644 index 0000000000000000000000000000000000000000..311c3cdd81628f93edc5733d14190a404a37098d --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_description/urdf/materials.xacro @@ -0,0 +1,36 @@ +<?xml version="1.0"?> +<robot> + + <material name="black"> + <color rgba="0.0 0.0 0.0 1.0"/> + </material> + + <material name="blue"> + <color rgba="0.0 0.0 0.8 1.0"/> + </material> + + <material name="green"> + <color rgba="0.0 0.8 0.0 1.0"/> + </material> + + <material name="grey"> + <color rgba="0.2 0.2 0.2 1.0"/> + </material> + + <material name="orange"> + <color rgba="${255/255} ${108/255} ${10/255} 1.0"/> + </material> + + <material name="brown"> + <color rgba="${222/255} ${207/255} ${195/255} 1.0"/> + </material> + + <material name="red"> + <color rgba="0.8 0.0 0.0 1.0"/> + </material> + + <material name="white"> + <color rgba="1.0 1.0 1.0 1.0"/> + </material> + +</robot> diff --git a/Robot_Development/catkin_ws/rosjet/jet_driver/CMakeLists.txt b/Robot_Development/catkin_ws/rosjet/jet_driver/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3f09f552a1b86c9848151ab1feb1ab2733f46f70 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_driver/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 2.8.3) +project(jet_driver) + +find_package(catkin REQUIRED COMPONENTS + controller_manager + hardware_interface + roscpp +) + + +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES jet_driver +# CATKIN_DEPENDS controller_manager hardware_interface roscpp +# DEPENDS system_lib +) + +include_directories( + ${catkin_INCLUDE_DIRS} +) +add_executable(jet_driver_node src/jet_driver_node.cpp) + + +target_link_libraries(jet_driver_node + ${catkin_LIBRARIES} +) + diff --git a/Robot_Development/catkin_ws/rosjet/jet_driver/launch/jet_driver.launch b/Robot_Development/catkin_ws/rosjet/jet_driver/launch/jet_driver.launch new file mode 100644 index 0000000000000000000000000000000000000000..a9105b29513f1eaa66de8ae0651fab1ca5410945 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_driver/launch/jet_driver.launch @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<launch> + <node name="jet_driver_node" pkg="jet_driver" type="jet_driver_node" output="screen"/> +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_driver/package.xml b/Robot_Development/catkin_ws/rosjet/jet_driver/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..25e6a857503c91b88ead1d69a3ad670cebe155f3 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_driver/package.xml @@ -0,0 +1,56 @@ +<?xml version="1.0"?> +<package> + <name>jet_driver</name> + <version>0.0.0</version> + <description>The jet_driver package</description> + + <!-- One maintainer tag required, multiple allowed, one person per tag --> + <!-- Example: --> + <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> + <maintainer email="ubuntu@todo.todo">ubuntu</maintainer> + + + <!-- One license tag required, multiple allowed, one license per tag --> + <!-- Commonly used license strings: --> + <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> + <license>TODO</license> + + + <!-- Url tags are optional, but mutiple are allowed, one per tag --> + <!-- Optional attribute type can be: website, bugtracker, or repository --> + <!-- Example: --> + <!-- <url type="website">http://wiki.ros.org/jet_driver</url> --> + + + <!-- Author tags are optional, mutiple are allowed, one per tag --> + <!-- Authors do not have to be maintianers, but could be --> + <!-- Example: --> + <!-- <author email="jane.doe@example.com">Jane Doe</author> --> + + + <!-- The *_depend tags are used to specify dependencies --> + <!-- Dependencies can be catkin packages or system dependencies --> + <!-- Examples: --> + <!-- Use build_depend for packages you need at compile time: --> + <!-- <build_depend>message_generation</build_depend> --> + <!-- Use buildtool_depend for build tool packages: --> + <!-- <buildtool_depend>catkin</buildtool_depend> --> + <!-- Use run_depend for packages you need at runtime: --> + <!-- <run_depend>message_runtime</run_depend> --> + <!-- Use test_depend for packages you need only for testing: --> + <!-- <test_depend>gtest</test_depend> --> + <buildtool_depend>catkin</buildtool_depend> + <build_depend>controller_manager</build_depend> + <build_depend>hardware_interface</build_depend> + <build_depend>roscpp</build_depend> + <run_depend>controller_manager</run_depend> + <run_depend>hardware_interface</run_depend> + <run_depend>roscpp</run_depend> + + + <!-- The export tag contains other, unspecified, tags --> + <export> + <!-- Other tools can request additional information be placed here --> + + </export> +</package> \ No newline at end of file diff --git a/Robot_Development/catkin_ws/rosjet/jet_driver/src/jet_driver_node.cpp b/Robot_Development/catkin_ws/rosjet/jet_driver/src/jet_driver_node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..edabf0fd927b214c66702dff8414a963ea7ed866 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_driver/src/jet_driver_node.cpp @@ -0,0 +1,112 @@ +#include <ros/ros.h> +#include <controller_manager/controller_manager.h> +#include <hardware_interface/joint_command_interface.h> +#include <hardware_interface/joint_state_interface.h> +#include <hardware_interface/robot_hw.h> +#include <std_msgs/UInt64.h> +#include <std_msgs/Int16.h> + +#define TICKS_PER_REVOLUTION 300 +#define REVOLUTIONS_PER_TICK .0033333333333 + +class JetRobot : public hardware_interface::RobotHW +{ +public: + double velocity_multiplier; + JetRobot(ros::NodeHandle nh) + { + + ros::NodeHandle pnh("~"); + + pnh.param<double>("velocity_multiplier", velocity_multiplier, 10.0); + ROS_INFO("velocity multiplier: %f", velocity_multiplier); + + hardware_interface::JointStateHandle state_handle_left("left_wheel_joint", &pos[0], &vel[0], &eff[0]); + jnt_state_interface.registerHandle(state_handle_left); + + hardware_interface::JointStateHandle state_handle_right("right_wheel_joint", &pos[1], &vel[1], &eff[1]); + jnt_state_interface.registerHandle(state_handle_right); + + registerInterface(&jnt_state_interface); + + hardware_interface::JointHandle vel_handle_left(jnt_state_interface.getHandle("left_wheel_joint"), &cmd[0]); + jnt_vel_interface.registerHandle(vel_handle_left); + + hardware_interface::JointHandle vel_handle_right(jnt_state_interface.getHandle("right_wheel_joint"), &cmd[1]); + jnt_vel_interface.registerHandle(vel_handle_right); + + registerInterface(&jnt_vel_interface); + + motor_left_pub = nh.advertise<std_msgs::Int16>("/arduino/motor_left_speed",10); + motor_right_pub = nh.advertise<std_msgs::Int16>("/arduino/motor_right_speed",10); + encoder_left_sub = nh.subscribe<std_msgs::UInt64>("/arduino/encoder_left_value", 10, &JetRobot::leftEncoderCB, this); + encoder_right_sub = nh.subscribe<std_msgs::UInt64>("/arduino/encoder_right_value", 10, &JetRobot::rightEncoderCB, this); + + + prev_left = 0; + prev_right = 0; + encoder_left = 0; + encoder_right = 0; + pos[0] = 0; + pos[1] = 0; + } + ros::Time getTime() const {return ros::Time::now();} + ros::Duration getPeriod() const{return ros::Duration(0.01);} + void leftEncoderCB(const std_msgs::UInt64::ConstPtr& val) { + encoder_left = (double)val->data; + } + void rightEncoderCB(const std_msgs::UInt64::ConstPtr& val) { + encoder_right = (double)val->data; + } + void read() { + left_msg.data = (int)(velocity_multiplier * cmd[0]); + right_msg.data = (int)(velocity_multiplier * cmd[1]); + motor_left_pub.publish(left_msg); + motor_right_pub.publish(right_msg); + } + void write() { + vel[0] = REVOLUTIONS_PER_TICK * (encoder_left - prev_left) / getPeriod().toSec(); + vel[1] = REVOLUTIONS_PER_TICK * (encoder_right - prev_right) / getPeriod().toSec(); + pos[0] += REVOLUTIONS_PER_TICK * (encoder_left - prev_left); + pos[1] += REVOLUTIONS_PER_TICK * (encoder_right - prev_right); + prev_left = encoder_left; + prev_right = encoder_right; + } + +private: + hardware_interface::VelocityJointInterface jnt_vel_interface; + hardware_interface::JointStateInterface jnt_state_interface; + double pos[2]; + double vel[2]; + double eff[2]; + double cmd[2]; + std_msgs::Int16 left_msg, right_msg; + double encoder_left, encoder_right, prev_left, prev_right; + ros::Publisher motor_left_pub; + ros::Publisher motor_right_pub; + ros::Subscriber encoder_left_sub; + ros::Subscriber encoder_right_sub; +}; + +int main(int argc, char * argv[]) +{ + ros::init(argc, argv, "jet_driver_node"); + ros::NodeHandle nh; + + JetRobot jet(nh); + controller_manager::ControllerManager cm(&jet, nh); + + ros::Rate rate(1.0 / jet.getPeriod().toSec()); + ros::AsyncSpinner spinner(1); + spinner.start(); + + while(ros::ok()) + { + jet.read(); + jet.write(); + cm.update(jet.getTime(), jet.getPeriod()); + rate.sleep(); + } + spinner.stop(); + return 0; +} diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/CMakeLists.txt b/Robot_Development/catkin_ws/rosjet/jet_navigation/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b7b481ff212374511e79d01cbb51e0ff376b6d73 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_navigation/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.3) +project(jet_navigation) + +find_package(catkin REQUIRED COMPONENTS + controller_manager + hardware_interface + roscpp + rospy +) + +catkin_package( +# INCLUDE_DIRS include +# CATKIN_DEPENDS rospy +# DEPENDS system_lib +) + +include_directories( + ${catkin_INCLUDE_DIRS} +) +add_executable(stationary_controller src/stationary_controller.cpp) +target_link_libraries(stationary_controller ${catkin_LIBRARIES}) diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/launch/jet_navigation.launch b/Robot_Development/catkin_ws/rosjet/jet_navigation/launch/jet_navigation.launch new file mode 100644 index 0000000000000000000000000000000000000000..1e04d9183cf056fbaab11cb3a9bb7570bf8b191f --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_navigation/launch/jet_navigation.launch @@ -0,0 +1,46 @@ +<launch> + <arg name="delta_x" default="0.0"/> + <arg name="delta_y" default="0.0"/> + <arg name="stationary" default="true"/> + <arg name="map_file"/> + + <include file="$(find jet_bringup)/launch/jet_gazebo.launch"/> + + <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" /> + + <group if="$(arg stationary)"> + <node name="stationary_controller" pkg="jet_navigation" type="stationary_controller"/> + </group> + + <node name="fakeodom_relay" pkg="topic_tools" type="relay" args="odom base_pose_ground_truth"/> + <node name="fake_localization" pkg="fake_localization" type="fake_localization"> + <param name="delta_x" value="$(arg delta_x)"/> + <param name="delta_y" value="$(arg delta_y)"/> + </node> + + + <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen"> + <rosparam file="$(find jet_navigation)/param/costmap_common_params.yaml" command="load" ns="global_costmap" /> + <rosparam file="$(find jet_navigation)/param/costmap_common_params.yaml" command="load" ns="local_costmap" /> + <rosparam file="$(find jet_navigation)/param/local_costmap_params.yaml" command="load" /> + <rosparam file="$(find jet_navigation)/param/global_costmap_params.yaml" command="load" /> + <!--<rosparam file="$(find turtlebot_navigation)/param/dwa_local_planner_params.yaml" command="load" /> + <rosparam file="$(find turtlebot_navigation)/param/move_base_params.yaml" command="load" /> + <rosparam file="$(find turtlebot_navigation)/param/global_planner_params.yaml" command="load" /> + <rosparam file="$(find turtlebot_navigation)/param/navfn_global_planner_params.yaml" command="load" /> + + <rosparam file="$(arg custom_param_file)" command="load" /> + + <param name="global_costmap/global_frame" value="$(arg global_frame_id)"/> + <param name="global_costmap/robot_base_frame" value="$(arg base_frame_id)"/> + <param name="local_costmap/global_frame" value="$(arg odom_frame_id)"/> + <param name="local_costmap/robot_base_frame" value="$(arg base_frame_id)"/> + <param name="DWAPlannerROS/global_frame_id" value="$(arg odom_frame_id)"/> + + <remap from="cmd_vel" to="navigation_velocity_smoother/raw_cmd_vel"/> + <remap from="odom" to="$(arg odom_topic)"/> + <remap from="scan" to="$(arg laser_topic)"/>--> + <param name="base_global_planner" value="global_planner/GlobalPlanner"/> + </node> + +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/package.xml b/Robot_Development/catkin_ws/rosjet/jet_navigation/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..6d03b0649b6b5367afab2e98c52fe300e0aaa4f8 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_navigation/package.xml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> +<package> + <name>jet_navigation</name> + <version>0.0.0</version> + <description>The jet_navigation package</description> + + <maintainer email="jkerfs@calpoly.edu">jeremy</maintainer> + + <license>MIT</license> + + <buildtool_depend>catkin</buildtool_depend> + + <buildtool_depend>catkin</buildtool_depend> + <build_depend>controller_manager</build_depend> + <build_depend>hardware_interface</build_depend> + <build_depend>roscpp</build_depend> + <build_depend>rospy</build_depend> + <run_depend>controller_manager</run_depend> + <run_depend>hardware_interface</run_depend> + <run_depend>roscpp</run_depend> + <run_depend>rospy</run_depend> + + <export> + </export> +</package> diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/param/costmap_common_params.yaml b/Robot_Development/catkin_ws/rosjet/jet_navigation/param/costmap_common_params.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e315a22fe8085234b2dc474f73feca7e1e0aae48 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_navigation/param/costmap_common_params.yaml @@ -0,0 +1,49 @@ +max_obstacle_height: 0.60 # assume something like an arm is mounted on top of the robot + +# Obstacle Cost Shaping (http://wiki.ros.org/costmap_2d/hydro/inflation) +robot_radius: 0.10 # distance a circular robot should be clear of the obstacle (kobuki: 0.18) +# footprint: [[x0, y0], [x1, y1], ... [xn, yn]] # if the robot is not circular + +map_type: voxel + +# obstacle_layer: +# enabled: true +# max_obstacle_height: 0.6 +# origin_z: 0.0 +# z_resolution: 0.2 +# z_voxels: 2 +# unknown_threshold: 15 +# mark_threshold: 0 +# combination_method: 1 +# track_unknown_space: true #true needed for disabling global path planning through unknown space +# obstacle_range: 2.5 +# raytrace_range: 3.0 +# origin_z: 0.0 +# z_resolution: 0.2 +# z_voxels: 2 +# publish_voxel_map: false +# observation_sources: scan bump +# scan: +# data_type: LaserScan +# topic: scan +# marking: true +# clearing: true +# min_obstacle_height: 0.25 +# max_obstacle_height: 0.35 +# bump: +# data_type: PointCloud2 +# topic: mobile_base/sensors/bumper_pointcloud +# marking: true +# clearing: false +# min_obstacle_height: 0.0 +# max_obstacle_height: 0.15 + # for debugging only, let's you see the entire voxel grid + +#cost_scaling_factor and inflation_radius were now moved to the inflation_layer ns +inflation_layer: + enabled: true + cost_scaling_factor: 10.0 # exponential rate at which the obstacle cost drops off (default: 10) + inflation_radius: 0.25 # max. distance from an obstacle at which costs are incurred for planning paths. + +static_layer: + enabled: true diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/param/dummy.yaml b/Robot_Development/catkin_ws/rosjet/jet_navigation/param/dummy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/param/global_costmap_params.yaml b/Robot_Development/catkin_ws/rosjet/jet_navigation/param/global_costmap_params.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9cd34f3e5a441405d8b4ca8debcc4055b58bd5be --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_navigation/param/global_costmap_params.yaml @@ -0,0 +1,11 @@ +global_costmap: + global_frame: /map + robot_base_frame: /base_link + update_frequency: 1.0 + publish_frequency: 0.5 + static_map: true + transform_tolerance: 0.5 + plugins: + - {name: static_layer, type: "costmap_2d::StaticLayer"} + - {name: obstacle_layer, type: "costmap_2d::VoxelLayer"} + - {name: inflation_layer, type: "costmap_2d::InflationLayer"} diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/param/local_costmap_params.yaml b/Robot_Development/catkin_ws/rosjet/jet_navigation/param/local_costmap_params.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8aef660f63f6c365c09a12d5de7385a3a47957ac --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_navigation/param/local_costmap_params.yaml @@ -0,0 +1,14 @@ +local_costmap: + global_frame: odom + robot_base_frame: /base_link + update_frequency: 5.0 + publish_frequency: 2.0 + static_map: false + rolling_window: true + width: 4.0 + height: 4.0 + resolution: 0.05 + transform_tolerance: 0.5 + plugins: + - {name: obstacle_layer, type: "costmap_2d::VoxelLayer"} + - {name: inflation_layer, type: "costmap_2d::InflationLayer"} diff --git a/Robot_Development/catkin_ws/rosjet/jet_navigation/src/stationary_controller.cpp b/Robot_Development/catkin_ws/rosjet/jet_navigation/src/stationary_controller.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e71fa0a58b9bb962287eb356df98975f1d1dce80 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_navigation/src/stationary_controller.cpp @@ -0,0 +1,67 @@ +#include <ros/ros.h> +#include <controller_manager/controller_manager.h> +#include <hardware_interface/joint_command_interface.h> +#include <hardware_interface/joint_state_interface.h> +#include <hardware_interface/robot_hw.h> +#include <std_msgs/UInt64.h> +#include <std_msgs/Int16.h> + +#define TICKS_PER_REVOLUTION 300 +#define REVOLUTIONS_PER_TICK .0033333333333 + +class JetRobot : public hardware_interface::RobotHW +{ +public: + JetRobot(ros::NodeHandle nh) + { + hardware_interface::JointStateHandle state_handle_left("left_wheel_joint", &pos[0], &vel[0], &eff[0]); + jnt_state_interface.registerHandle(state_handle_left); + + hardware_interface::JointStateHandle state_handle_right("right_wheel_joint", &pos[1], &vel[1], &eff[1]); + jnt_state_interface.registerHandle(state_handle_right); + + registerInterface(&jnt_state_interface); + + hardware_interface::JointHandle vel_handle_left(jnt_state_interface.getHandle("left_wheel_joint"), &cmd[0]); + jnt_vel_interface.registerHandle(vel_handle_left); + + hardware_interface::JointHandle vel_handle_right(jnt_state_interface.getHandle("right_wheel_joint"), &cmd[1]); + jnt_vel_interface.registerHandle(vel_handle_right); + + registerInterface(&jnt_vel_interface); + + } + + +private: + hardware_interface::VelocityJointInterface jnt_vel_interface; + hardware_interface::JointStateInterface jnt_state_interface; + double pos[2]; + double vel[2]; + double eff[2]; + double cmd[2]; +}; + +int main(int argc, char * argv[]) +{ + ros::init(argc, argv, "stationary_controller"); + ros::NodeHandle nh; + + JetRobot jet(nh); + controller_manager::ControllerManager cm(&jet, nh); + + ros::Duration period = ros::Duration(0.01); + + ros::Rate rate(1.0 / period.toSec()); + ros::AsyncSpinner spinner(1); + spinner.start(); + + while(ros::ok()) + { + cm.update(ros::Time::now(), period); + rate.sleep(); + } + spinner.stop(); + + return 0; +} diff --git a/Robot_Development/catkin_ws/rosjet/jet_serial/CMakeLists.txt b/Robot_Development/catkin_ws/rosjet/jet_serial/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b453e4d909e6e8acb8be0199425ef1d428292e5 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_serial/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.3) +project(jet_serial) + +find_package(catkin REQUIRED COMPONENTS + rospy +) + +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES jet_arduino +# CATKIN_DEPENDS rospy +# DEPENDS system_lib +) + +include_directories( + ${catkin_INCLUDE_DIRS} +) diff --git a/Robot_Development/catkin_ws/rosjet/jet_serial/launch/jet_serial.launch b/Robot_Development/catkin_ws/rosjet/jet_serial/launch/jet_serial.launch new file mode 100644 index 0000000000000000000000000000000000000000..644346958643ab1e8ae56b768b230c9d51fddf43 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_serial/launch/jet_serial.launch @@ -0,0 +1,9 @@ +<?xml version="1.0"?> + <launch> + + <node pkg="rosserial_python" name="serial_node" type="serial_node.py"> + <param name="port" value="/dev/ttyACM0" /> + <param name="baud" value="115200" /> + </node> + +</launch> diff --git a/Robot_Development/catkin_ws/rosjet/jet_serial/package.xml b/Robot_Development/catkin_ws/rosjet/jet_serial/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..1cb5a53508286660c56f68a4c2989750ae924577 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/jet_serial/package.xml @@ -0,0 +1,17 @@ +<?xml version="1.0"?> +<package> + <name>jet_serial</name> + <version>0.0.0</version> + <description>The jet_serial package</description> + + <maintainer email="jkerfs@calpoly.edu">jeremy</maintainer> + + <license>MIT</license> + + <buildtool_depend>catkin</buildtool_depend> + <build_depend>rospy</build_depend> + <run_depend>rospy</run_depend> + + <export> + </export> +</package> diff --git a/Robot_Development/catkin_ws/rosjet/rosjet.rosinstall b/Robot_Development/catkin_ws/rosjet/rosjet.rosinstall new file mode 100644 index 0000000000000000000000000000000000000000..657d7ac0cab53344841dab680da7170c30005fd4 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/rosjet.rosinstall @@ -0,0 +1,17 @@ +# Image Dependencies +- tar: + local-name: libraries/image_common/camera_info_manager + uri: https://github.com/ros-gbp/image_common-release/archive/release/indigo/camera_info_manager/1.11.10-0.tar.gz + version: image_common-release-release-indigo-camera_info_manager-1.11.10-0 +- tar: + local-name: libraries/image_common/image_transport + uri: https://github.com/ros-gbp/image_common-release/archive/release/indigo/image_transport/1.11.10-0.tar.gz + version: image_common-release-release-indigo-image_transport-1.11.10-0 +- tar: + local-name: libraries/usb_cam + uri: https://github.com/bosch-ros-pkg-release/usb_cam-release/archive/release/indigo/usb_cam/0.3.4-0.tar.gz + version: usb_cam-release-release-indigo-usb_cam-0.3.4-0 +- tar: + local-name: libraries/vision_opencv/cv_bridge + uri: https://github.com/ros-gbp/vision_opencv-release/archive/release/indigo/cv_bridge/1.11.12-0.tar.gz + version: vision_opencv-release-release-indigo-cv_bridge-1.11.12-0 diff --git a/Robot_Development/catkin_ws/rosjet/rosjet_install.sh b/Robot_Development/catkin_ws/rosjet/rosjet_install.sh new file mode 100644 index 0000000000000000000000000000000000000000..0b318ba76ba07deae0b89d45d74d048b13d023b3 --- /dev/null +++ b/Robot_Development/catkin_ws/rosjet/rosjet_install.sh @@ -0,0 +1,98 @@ +if [[ "$(uname -a)" =~ ^.*aarch64.*$ ]]; then + ISTX1=true +else + ISTX1=false +fi + +# Install Grinch Kernel if Tk1 +if ! $ISTX1 +then + cd ~/; git clone https://github.com/jetsonhacks/installGrinch.git + cd installGrinch; ./installGrinch.sh +fi + +#Configure time-zone +sudo dpkg-reconfigure tzdata + +#Ros Prerequisites +sudo update-locale LANG=C LANGUAGE=C LC_ALL=C LC_MESSAGES=POSIX +sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu trusty main" > /etc/apt/sources.list.d/ros-latest.list' +wget https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -O - | sudo apt-key add - +sudo apt-get update + +#Ros Jade Base +sudo apt-get -y install ros-jade-ros-base + +#Python Dependencies +sudo apt-get -y install python-rosdep python-dev python-pip python-rosinstall python-wstool + +sudo rosdep init +rosdep update +echo "source /opt/ros/jade/setup.bash" >> ~/.bashrc +source ~/.bashrc + +#Ros packages +sudo apt-get -y install ros-jade-rosserial-arduino +sudo apt-get -y install ros-jade-rosserial +sudo apt-get -y install ros-jade-eigen-conversions +sudo apt-get -y install ros-jade-tf2-geometry-msgs +sudo apt-get -y install ros-jade-angles +sudo apt-get -y install ros-jade-web-video-server +sudo apt-get -y install ros-jade-rosbridge-suite +sudo apt-get -y install ros-jade-rospy-tutorials +sudo apt-get -y install ros-jade-joy +sudo apt-get -y install ros-jade-teleop-twist-joy +sudo apt-get -y install ros-jade-roslint +sudo apt-get -y install ros-jade-controller-manager +sudo apt-get -y install ros-jade-camera-calibration-parsers +sudo apt-get -y install ros-jade-xacro +sudo apt-get -y install ros-jade-robot-state-publisher +sudo apt-get -y install ros-jade-diff-drive-controller +sudo apt-get -y install ros-jade-usb-cam +sudo apt-get -y install ros-jade-ros-control +sudo apt-get -y install ros-jade-dynamic-reconfigure +sudo apt-get -y install ros-jade-fake-localization +sudo apt-get -y install ros-jade-joint-state-controller + +# Configure Catkin Workspace +source /opt/ros/jade/setup.bash +cd ~/catkin_ws/src +catkin_init_workspace + +#Install Ros Opencv bindings from source +cd ~/catkin_ws +wstool init src +wstool merge -t src src/rosjet/rosjet.rosinstall +wstool update -t src + +#Install Caffe (https://gist.github.com/jetsonhacks/acf63b993b44e1fb9528) +sudo add-apt-repository universe +sudo apt-get update +sudo apt-get install libprotobuf-dev protobuf-compiler gfortran \ +libboost-dev cmake libleveldb-dev libsnappy-dev \ +libboost-thread-dev libboost-system-dev \ +libatlas-base-dev libhdf5-serial-dev libgflags-dev \ +libgoogle-glog-dev liblmdb-dev -y +sudo usermod -a -G video $USER +cd ~/ +git clone https://github.com/BVLC/caffe.git +cd caffe && git checkout dev +cp Makefile.config.example Makefile.config +make -j 4 all + +# System Optimizations +gsettings set org.gnome.settings-daemon.plugins.power button-power shutdown +gsettings set org.gnome.desktop.screensaver lock-enabled false +sudo apt-get -y install compizconfig-settings-manager +gsettings set org.gnome.desktop.interface enable-animations false +gsettings set com.canonical.Unity.Lenses remote-content-search none +echo -e '[SeatDefaults]\nautologin-user=ubuntu' > login_file; sudo mv login_file /etc/lightdm/lightdm.conf +gsettings set org.gnome.Vino enabled true +gsettings set org.gnome.Vino disable-background true +gsettings set org.gnome.Vino prompt-enabled false +gsettings set org.gnome.Vino require-encryption false + +echo "alias sr='source ~/catkin_ws/devel/setup.bash'" >> ~/.bashrc + +cd ~/catkin_ws +catkin_make && source devel/setup.sh diff --git a/Robot_Development/catkin_ws/src/lane_detection/src/detect_plot.py b/Robot_Development/catkin_ws/src/lane_detection/src/detect_plot.py index fb0ba974ae24b23614495ef9757799c8991af782..25c74f6047a0e601bb283600f6ad5fa6174be61b 100755 --- a/Robot_Development/catkin_ws/src/lane_detection/src/detect_plot.py +++ b/Robot_Development/catkin_ws/src/lane_detection/src/detect_plot.py @@ -50,7 +50,7 @@ def detect_edge(pic): def ROI_real(pic): height = pic.shape[0] width = pic.shape[1] - triangle = np.array([[(0, height), (135, 250), (515, 250), (width, height)]], dtype=np.int32) #shape of a trapazoid + triangle = np.array([[(0, height), (0, 250), (width, 250), (width, height)]], dtype=np.int32) #shape of a trapazoid mask = np.zeros_like(pic) cv2.fillPoly(mask, triangle, 255) roi = cv2.bitwise_and(pic, mask) @@ -294,21 +294,20 @@ while not rospy.is_shutdown(): else: print("No midpoint calculated") - plt.scatter(300, 350) - + plt.scatter(300, 350) plt.imshow(frame, zorder=0) - plt.pause(.001) - #lane = applyLines(frame, lines) - #cv2.imshow("thresh",test) - #cv2.imshow("cropped_2",cropped_2) + + #lane = applyLines(frame, lines) + cv2.imshow("thresh",test) + cv2.imshow("cropped_2",cropped_2) # cv2.imshow("edges", wEdges) # cv2.imshow("cropped", cropped) # cv2.imshow("frame", lane) - #key = cv2.waitKey(1) - #if key == 27: - #break + key = cv2.waitKey(1) + if key == 27: + break #video.release() #cv2.destroyAllWindows()