Blob Blame Raw
From 51d99dbce5b422eb43a14b6120017c72178dd477 Mon Sep 17 00:00:00 2001
From: Geoffrey Biggs <git@killbots.net>
Date: Thu, 9 Nov 2017 11:28:08 +0900
Subject: [PATCH] Fix Python version conflict and add Python 3 support (Fixes
 #17)

---
 python/CMakeLists.txt              |  94 ++++++++------------
 python/test/hokuyo_aist_example.py | 135 ++++++++++++++++++-----------
 2 files changed, 120 insertions(+), 109 deletions(-)

diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index b82a1f0..0bee33e 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -1,62 +1,40 @@
 # Find the Python libraries and headers
-FIND_PACKAGE (PythonLibs)
-if(NOT PYTHON_LIBRARIES)
-	MESSAGE (STATUS "Python libaries not found. Cannot build Python bindings for HokuyoAIST.")
-endif(NOT PYTHON_LIBRARIES)
+SET (TARGET_PYTHON_VERSION 3)
+FIND_PACKAGE (PythonLibs ${TARGET_PYTHON_VERSION})
+if (NOT PYTHON_LIBRARIES)
+  MESSAGE (STATUS "Python libaries not found. Cannot build Python bindings for HokuyoAIST.")
+endif (NOT PYTHON_LIBRARIES)
+STRING (REGEX MATCH "^[23]\\.[0-9]" PYTHON_MAJORMINOR_VERSION "${PYTHONLIBS_VERSION_STRING}")
 
 # Find Boost::Python
-# There is a new, much better, FindBoost.cmake since 2.6
-if(CMAKE_MAJOR_VERSION EQUAL 2 AND CMAKE_MINOR_VERSION GREATER 5)
-	OPTION (Boost_USE_STATIC_LIBS "Use the static versions of the Boost libraries" OFF)
-	MARK_AS_ADVANCED (Boost_USE_STATIC_LIBS)
-
-	SET (BOOST_COMPONENTS python)
-	FIND_PACKAGE (Boost COMPONENTS ${BOOST_COMPONENTS})
-	if(Boost_FOUND)
-		INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIR})
-		LINK_DIRECTORIES (${Boost_LIBRARY_DIRS})
-
-		if(Boost_PYTHON_FOUND)
-			set(boostPythonLib ${Boost_PYTHON_LIBRARY})
-		else(Boost_PYTHON_FOUND)
-			MESSAGE (STATUS
-				"Boost::Python library was not found. Cannot build Python bindings for HokuyoAIST.")
-		endif(Boost_PYTHON_FOUND)
-	else(Boost_FOUND)
-		MESSAGE (STATUS
-				"Boost libraries were not found. Cannot build Python bindings for HokuyoAIST.")
-	endif(Boost_FOUND)
-else(CMAKE_MAJOR_VERSION EQUAL 2 AND CMAKE_MINOR_VERSION GREATER 5)
-	FIND_PACKAGE (Boost)
-	if(Boost_FOUND)
-		# For 2.4, assume that if boost is found then boost::python is present
-		OPTION (Boost_USE_MULTITHREAD "Use the multithreaded versions of the Boost libraries" ON)
-		MARK_AS_ADVANCED (Boost_USE_MULTITHREAD)
-		SET (BOOST_LIB_SUFFIX "" CACHE STRING "Boost library name suffix")
-		MARK_AS_ADVANCED (BOOST_LIB_SUFFIX)
-
-		SET (boostPythonLib boost_python${BOOST_LIB_SUFFIX})
-		INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIRS})
-		LINK_DIRECTORIES (${Boost_LIBRARY_DIRS})
-	else(Boost_FOUND)
-		MESSAGE (STATUS
-				"Boost libraries were not found. Cannot build Python bindings for HokuyoAIST.")
-	endif(Boost_FOUND)
-endif(CMAKE_MAJOR_VERSION EQUAL 2 AND CMAKE_MINOR_VERSION GREATER 5)
-
-if(PYTHON_LIBRARIES AND Boost_FOUND AND LIB_TYPE STREQUAL SHARED)
-	MESSAGE (STATUS "HokuyoAIST Python bindings will be built.")
-	SET (srcs	hokuyo_aist.cpp)
-
-	SET (pyModuleTarget hokuyoaist_py)
-    INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include/hokuyoaist ${PYTHON_INCLUDE_PATH})
-	add_library(${pyModuleTarget} MODULE ${srcs})
-	TARGET_LINK_LIBRARIES (${pyModuleTarget} hokuyoaist ${boostPythonLib} ${PYTHON_LIBRARIES})
-	SET_TARGET_PROPERTIES (${pyModuleTarget} PROPERTIES PREFIX "" OUTPUT_NAME "hokuyoaist")
-	install(TARGETS ${pyModuleTarget} LIBRARY DESTINATION lib/python/site-packages)
-
-	ADD_SUBDIRECTORY (test)
+OPTION (Boost_USE_STATIC_LIBS "Use the static versions of the Boost libraries" OFF)
+MARK_AS_ADVANCED (Boost_USE_STATIC_LIBS)
+
+STRING (REGEX REPLACE "[^0-9]" "" BOOST_PY_VERSION ${PYTHON_MAJORMINOR_VERSION})
+FIND_PACKAGE (Boost COMPONENTS python${TARGET_PYTHON_VERSION})
+if(Boost_FOUND)
+  if(NOT Boost_PYTHON${TARGET_PYTHON_VERSION}_FOUND)
+    MESSAGE (STATUS
+      "Boost::Python library was not found. Cannot build Python bindings for HokuyoAIST.")
+  endif(NOT Boost_PYTHON${TARGET_PYTHON_VERSION}_FOUND)
+else(Boost_FOUND)
+  MESSAGE (STATUS
+      "Boost libraries were not found. Cannot build Python bindings for HokuyoAIST.")
+endif(Boost_FOUND)
+
+if(PYTHON_LIBRARIES AND Boost_PYTHON${TARGET_PYTHON_VERSION}_FOUND AND LIB_TYPE STREQUAL SHARED)
+  MESSAGE (STATUS "HokuyoAIST Python bindings will be built.")
+
+  SET (pyModuleTarget hokuyoaist_py)
+  INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIRS})
+  INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include/hokuyoaist ${PYTHON_INCLUDE_PATH})
+  add_library(${pyModuleTarget} MODULE hokuyo_aist.cpp)
+  TARGET_LINK_LIBRARIES (${pyModuleTarget} hokuyoaist Boost::python${TARGET_PYTHON_VERSION} ${PYTHON_LIBRARIES})
+  SET_TARGET_PROPERTIES (${pyModuleTarget} PROPERTIES PREFIX "" OUTPUT_NAME "hokuyoaist")
+  install(TARGETS ${pyModuleTarget} LIBRARY DESTINATION
+    ${LIB_INSTALL_DIR}/python${PYTHON_MAJORMINOR_VERSION}/site-packages)
+
+  ADD_SUBDIRECTORY (test)
 ELSEIF(NOT LIB_TYPE STREQUAL SHARED)
-	MESSAGE (STATUS "HokuyoAIST Python bindings will not be built - must build hokuyoaist as a shared library.")
-endif(PYTHON_LIBRARIES AND Boost_FOUND AND LIB_TYPE STREQUAL SHARED)
-
+  MESSAGE (STATUS "HokuyoAIST Python bindings will not be built - must build hokuyoaist as a shared library.")
+endif(PYTHON_LIBRARIES AND Boost_PYTHON-PY${BOOST_PY_VERSION}_FOUND AND LIB_TYPE STREQUAL SHARED)
diff --git a/python/test/hokuyo_aist_example.py b/python/test/hokuyo_aist_example.py
index 1eeab14..95cbd58 100755
--- a/python/test/hokuyo_aist_example.py
+++ b/python/test/hokuyo_aist_example.py
@@ -1,91 +1,124 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
+
+import argparse
 import hokuyoaist
-from optparse import OptionParser
+
 
 def main():
-    parser = OptionParser()
-    parser.add_option('-c', '--clustercount', dest='cluster_count',
-            type='int', default='1',
-            help='Cluster count [default: %default]')
-    parser.add_option('-e', '--endangle', dest='end_angle', type='float',
-            default='0',
-            help='End angle to get ranges to [default: %default]')
-    parser.add_option('-f', '--firststep', dest='first_step', type='int',
-            default='-1',
-            help='First step to get ranges from [default: %default]')
-    parser.add_option('-l', '--laststep', dest='last_step', type='int',
-            default='-1',
-            help='Last step to get ranges to [default: %default]')
-    parser.add_option('-n', '--new', dest='get_new', action='store_true',
-            default='False', help='Get new ranges instead of latest \
-ranges [default: %default]')
-    parser.add_option('-o', '--portoptions', dest='port_options', type='string',
-            default='type=serial,device=/dev/ttyACM0,timeout=1',
-            help='Port options (see flexiport library) [default: %default]')
-    parser.add_option('-s', '--startangle', dest='start_angle', type='float',
-            default='0',
-            help='Start angle to get ranges from [default: %default]')
-    parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
-            default='False',
-            help='Put the hokuyoaist library into verbose mode \
-[Default: %default]')
+    parser = argparse.ArgumentParser(
+        description="HokuyoAIST Python bindings demo")
+    parser.add_argument(
+        '-c',
+        '--cluster-count',
+        type=int,
+        default='1',
+        help='Cluster count [default: %(default)s]')
+    parser.add_argument(
+        '-e',
+        '--end-angle',
+        type=float,
+        default='0',
+        help='End angle to get ranges to [default: %(default)s]')
+    parser.add_argument(
+        '-f',
+        '--first-step',
+        type=int,
+        default='-1',
+        help='First step to get ranges from [default: %(default)s]')
+    parser.add_argument(
+        '-l',
+        '--last-step',
+        type=int,
+        default='-1',
+        help='Last step to get ranges to [default: %(default)s]')
+    parser.add_argument(
+        '-n',
+        '--get-new',
+        action='store_true',
+        default='False',
+        help='Get new ranges instead of latest ranges [default: %(default)s]')
+    parser.add_argument(
+        '-o',
+        '--port-options',
+        type=str,
+        default='type=serial,device=/dev/ttyACM0,timeout=1',
+        help='Port options (see flexiport library) [default: %(default)s]')
+    parser.add_argument(
+        '-s',
+        '--start-angle',
+        type=float,
+        default='0',
+        help='Start angle to get ranges from [default: %(default)s]')
+    parser.add_argument(
+        '-v',
+        '--verbose',
+        action='store_true',
+        default='False',
+        help='Put the hokuyoaist library into verbose mode [Default: %(default)s]')
 
     # Scan command line arguments
-    options, args = parser.parse_args()
+    args = parser.parse_args()
 
     try:
         # Create an instance of a laser scanner object
         laser = hokuyoaist.Sensor()
-        if options.verbose == True:
+        if args.verbose:
             # Set verbose mode so we see more information in stderr
             laser.set_verbose(True)
 
         # Open the laser
-        laser.open(options.port_options)
+        laser.open(args.port_options)
         # Turn the laser on
         laser.set_power(True)
 
         # Get some laser info
-        #print 'Laser sensor information:'
-        #info = hokuyoaist.SensorInfo info()
-        #laser.get_sensor_info(info)
-        #print info.as_string()
+        # print('Laser sensor information:')
+        # info = hokuyoaist.SensorInfo info()
+        # laser.get_sensor_info(info)
+        # print(info.as_string())
 
         # Get range data
         data = hokuyoaist.ScanData()
-        if (options.first_step == -1 and options.last_step == -1) and \
-                (options.start_angle == 0 and options.end_angle == 0):
+        if ((args.first_step == -1 and args.last_step == -1) and
+                (args.start_angle == 0 and args.end_angle == 0)):
             # Get all ranges
-            if options.get_new == True:
-                laser.get_new_ranges(data, -1, -1, options.cluster_count)
+            if args.get_new:
+                laser.get_new_ranges(data, -1, -1, args.cluster_count)
             else:
-                laser.get_ranges(data, -1, -1, options.cluster_count)
-        elif options.first_step != -1 or options.last_step != -1:
+                laser.get_ranges(data, -1, -1, args.cluster_count)
+        elif args.first_step != -1 or args.last_step != -1:
             # Get by step
-            if options.get_new == True:
-                laser.get_new_ranges(data, options.first_step, options.last_step, options.cluster_count)
+            if args.get_new:
+                laser.get_new_ranges(data, args.first_step, args.last_step, args.cluster_count)
             else:
-                laser.get_ranges(data, options.first_step, options.last_step, options.cluster_count)
+                laser.get_ranges(data, args.first_step, args.last_step, args.cluster_count)
         else:
             # Get by angle
-            if options.get_new == True:
-                laser.get_new_ranges_by_angle(data, options.start_angle, options.end_angle, options.cluster_count)
+            if args.get_new:
+                laser.get_new_ranges_by_angle(
+                    data,
+                    args.start_angle,
+                    args.end_angle,
+                    args.cluster_count)
             else:
-                laser.get_ranges_by_angle(data, options.start_angle, options.end_angle, options.cluster_count)
+                laser.get_ranges_by_angle(
+                    data,
+                    args.start_angle,
+                    args.end_angle,
+                    args.cluster_count)
 
-        print 'Laser range data:'
-        print data.as_string()
+        print('Laser range data:', data.as_string())
 
         # Close the laser
         laser.close()
 
-    except hokuyoaist.BaseError, e:
-        print 'Caught exception: ' + e.what()
+    except hokuyoaist.BaseError as e:
+        print('Caught exception:', e.what())
         return 1
     return 0
 
 
 if __name__ == '__main__':
     main()
-