Choreonoidについて
Simple Wiki Based Contents Management System
関心分野 >> Choreonoidについて

Choreonidについて

Choreonoidは、産総研の中岡主任研究員の開発したロボットソフトウェア開発の統合環境です。詳しくはオフィシャルサイトを参照してください。
ここでは、ChoreonoidをWindows上でビルドしたときに行った手順を記載しておきます。
ここに記載する内容は、2017年6月末日までのアップデートが施されたバージョン1.6ベータ(64bit版)を対象にしていきます。
&color(red){Choreonoid バージョン1.6は、2017年11月1日にリリースされています。}

準備

Choreonoidのビルドにあたり、Visual C++と必要なライブラリを整備します。オフィシャルサイトによると現在サポートしているのは、VisualStuido2013と2015になりますので、ここではVisualStudio2015を使用します。現在 VisualStudoの最新版は、VS2017なのですが、オフィシャルサイトで動作確認できているバージョンにしています。
VS2017では、まだまだChoreonoidとAssimpライブラリに不具合がありビルドに失敗します。いくつかの修正を加えることでビルドできました。(2017/07/06)
VisualStudio対応のリポジトリ(fork版)をここで公開しています。このリポジトリのPythonPluginというブランチのソースコードには、下記の修正がすべて当っています。
Choreonoidは、さまざまなプラグインで機能拡張ができるのですが、デフォルトでは下記のライブラリが必要です。 (VS2015用のバイナリをこのページに添付していますので、展開して使うことができます)
また、Choreonoid-1.6からは、Collada形式の3Dモデルファイルの利用やPythonによる内部のモデルの取り扱いなどが可能になっていますので、これらの機能を提供するライブラリとして、下記を用意します。
ここでは、Choreonoidを64ビットアプリケーションとしてビルドしますので、上記のライブラリは、すべて64ビットバージョンを用意します。ただし、Assimpのみは。バイナリがありませんでしたので、ソースコードをダウンロードしてビルド&インストールします。
CMake, Boost, Qt5, Pythonは、msiまたはexeファイルによるインストーラですので、適当な場所にインストールしてください。私の場合は、Boostは C:\loalの下、Qt5は C:\Qtの下、Pythonは、C:\Python27x64の下ににインストールしました。CMakeはC:\Program Filesの下で問題ないと思います。
Eigenは、zip形式のファイルですので、C:\localの下に展開すればOKです。
Assimpに関しては、ソースコードをC:\develに展開し、CMakeをGUIモードで起動してConfigure, GenerateでVS2015用のソリューションファイルを生成し、ビルド&インストールすればよいと思います。このとき、インストールする場所をC:\local\Assimpとしておいた方が後々良いかと思います。
以上で準備完了です。

Choreonoidのビルド

Choreonoidをビルドするために開発のリポジトリからソースコードをダウンロードします。ソースコードのダウンロードは、Assimpをビルドした時と同じように、 のボタンを押下してダウンロードしてください。
ダウンロードが終われば、適当なディレクトリに展開します。ここでは、"C:/devel/"の下に展開したいと思います。
バージョン1.6のリリース版では、下記の修正のほとんどが対応ずみです。リリース版をダウンロードしてビルドすることができるようになっています。

ソースコードの修正

現在(2017/07/07)の時点で、Choreonoidのリポジトリのソースコードは、VS2015でコンパイルする場合にいくつかの不具合があります。ここでは、特に、AssimpプラグインとPythonプラグインの生成に関しては、開発チームでも対応が追いついていないようですので、私のメモとしてここに記載しておきます。
なお、この修正は、VS2017への対応も同時に行っていますので、ご承知おきください。修正の全体については、 'git diff' での出力をこのページの最後に添付資料としてつけておきますので、ダウンロードしPatchコマンド等でパッチを当ててください。

CMakeList.txtの修正

トップ
cmakeに関して、現在のままでは、Waring等が多く発生すること、boostライブラリの自動検索がうまく働かないこと、VS2017への対応のため '/EHsc' というコンパイルオプションが必要であるために、最上部のCMakeList.txtに対して下記の修正を行う必要があります。
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7a4529af..f27ee5ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,9 @@
 
 cmake_minimum_required(VERSION 2.6)
 cmake_policy(SET CMP0003 NEW)
+cmake_policy(SET CMP0020 NEW)
+cmake_policy(SET CMP0043 NEW)
+
 set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
 
 include(FindPkgConfig)
@@ -151,6 +154,8 @@ if(MSVC)
   endif()
   set(ext_linker_options "")
 
+  set(ext_compiler_options "${ext_compiler_options} /EHsc")
+
   option(MSVC_ENABLE_GLOBAL_OPTIMIZATION "Global optimization with compiler option /GL and linker option /LTCG" ON)
   if(MSVC_ENABLE_GLOBAL_OPTIMIZATION)
     set(ext_compiler_options "${ext_compiler_options} /GL")
@@ -323,7 +328,7 @@ endif()
 # set(Boost_NO_SYSTEM_PATHS true)
 
 set(Boost_USE_STATIC_LIBS OFF)
-set(Boost_ADDITIONAL_VERSIONS "1.42" "1.42.0" "1.43" "1.43.0" "1.44" "1.44.0" "1.45" "1.45.0" "1.46" "1.46.0" "1.46.1" "1.47" "1.47.0" "1.48" "1.48.0" "1.49.0" "1.50.0")
+set(Boost_ADDITIONAL_VERSIONS "1.42" "1.42.0" "1.43" "1.43.0" "1.44" "1.44.0" "1.45" "1.45.0" "1.46" "1.46.0" "1.46.1" "1.47" "1.47.0" "1.48" "1.48.0" "1.49.0" "1.50.0" "1.64.0")
 
 
 if(MSVC)
@@ -355,7 +360,7 @@ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE BOOST_DISABLE
 
 install_external_libraries(${Boost_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS}
   ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_THREAD_LIBRARY} 
-  ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_PYTHON_LIBRARY} 
+  ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_PYTHON_LIBRARY} ${Boost_BZIP2_LIBRARY}
   ${Boost_IOSTREAMS_LIBRARY} ${Boost_ZLIB_LIBRARY})
 
AssimpPlugin
AssimpPluginのCMakeList.txtは、現在はWIN32では機能しておらずCMakeを実行しても選択もできなくなっています。そこで、Windows用にCMakeList.txtを下記のものと置き換えてください。
また、VS2017の場合には、うまくVCのバージョンが取れていないようですので、Assimpのライブラリのassimp-config.cmakeを修正するか、ソリューションの生成後にプロパティを手動で修正してください。(VC++のバージョンですが、VS2015 → 14.0、VS2017 → 14.1 になっています)
&color(blue){現在は、VS2107の場合にも"assimp-vc140-mt.dll"が生成されるようなので特に修正の必要はありません。}
#
#if(NOT UNIX)
#  return()
#endif()

pkg_check_modules(ASSIMP QUIET assimp>=3.2)
if(ASSIMP_FOUND)
  option(BUILD_ASSIMP_PLUGIN "Building ASSIMPPlugin" ON)
else()
  option(BUILD_ASSIMP_PLUGIN "Building ASSIMPPlugin" OFF)
endif()

if(NOT BUILD_ASSIMP_PLUGIN)
  return()
endif()



set(ASSIMP_DIR ${ASSIMP_DIR} CACHE PATH "set the top directory of the ASSIMP ")
if(UNIX)
  if(NOT ASSIMP_DIR)
    pkg_check_modules(ASSIMP REQUIRED assimp>=3.2)
  endif()
elseif(MSVC)
  if(NOT ASSIMP_DIR)
    message(FATAL_ERROR "Please specify the directory of the ASSIMP to ASSIMP_DIR.")
  endif()
endif()


if(NOT ASSIMP_FOUND )
  if(MSVC)
    find_file(ASSIMP_CONFIG assimp-config.cmake HINTS ${ASSIMP_DIR}/lib/cmake/* )

    if (ASSIMP_CONFIG)
      include(${ASSIMP_CONFIG})
    else()
      message(FATAL_ERROR "NO ASSIMP_CONFIG file found.")
    endif()

	if(INSTALL_RUNTIME_DEPENDENCIES)
        install(PROGRAMS ${ASSIMP_DIR}/bin/assimp${ASSIMP_LIBRARY_SUFFIX}.dll DESTINATION bin
	      CONFIGURATIONS Release RelWithDebInfo MinSizeRel Debug)
      
        if(INSTALL_SDK_WITH_EXTLIBS)
	      install(FILES ${ASSIMP_DIR}/lib/assimp${ASSIMP_LIBRARY_SUFFIX}.lib DESTINATION lib
	        CONFIGURATIONS Release RelWithDebInfo MinSizeRel Debug)
	      install(DIRECTORY ${ASSIMP_DIR}/include/assimp DESTINATION ${CNOID_HEADER_SUBDIR})
        endif()
	endif()
  else()
    set(ASSIMP_LIBRARIES assimp)
    set(ASSIMP_INCLUDE_DIRS ${ASSIMP_DIR}/include)
    set(ASSIMP_LIBRARY_DIRS ${ASSIMP_DIR}/lib)
  endif()
endif()

set(target CnoidAssimpPlugin)

include_directories(${ASSIMP_INCLUDE_DIRS})
link_directories(${ASSIMP_LIBRARY_DIRS})

set(sources
  AssimpPlugin.cpp
  AssimpSceneLoader.cpp
)

set(headers )

make_gettext_mofiles(${target} mofiles) 
add_cnoid_plugin(${target} SHARED ${sources} ${headers} ${mofiles})
target_link_libraries(${target} CnoidBase ${ASSIMP_LIBRARIES})
apply_common_setting_for_plugin(${target} "${headers}")

不具合の修正

単純なバグ
単純なバグとしては、src/Util/SceneRenderer.cppの中のSceneRenderer::pick(int x, int y)関数で、返り値がないものがありますので、
diff --git a/src/Util/SceneRenderer.cpp b/src/Util/SceneRenderer.cpp
index 0c099d79..fc696daa 100644
--- a/src/Util/SceneRenderer.cpp
+++ b/src/Util/SceneRenderer.cpp
@@ -256,6 +256,7 @@ bool SceneRenderer::pick(int x, int y)
     impl->isRendering = true;
     bool result = doPick(x, y);
     impl->isRendering = false;
+    return true;
 }

のような修正を行う必要があります。
あとは、VisualC++では、 64ビットでコンパイルする場合には、 "WIN32"というプリプロセッサは定義されません。そのため、sample/GRobotPlugin/GRobotController.cpp, sample/GRobotPlugin/GRobotController.h, src/Base/MultiAffine3SeqItem.cpp,src/Base/MultiSE3SeqItem.cpp, src/Base/MultiValueSeqItem.cpp, src/MediaPlugin/MediaPlugin.cpp, src/MediaPlugin/python/PyMedia.cpp, src/Util/Referenced.h, src/Util/Sleep.h に対して
 "WIN32"  -> "_WIN32"

のような変更を行う必要があります。
DesktopOpenGLモードにする
次に、Choreonoidのシーンビューで使っているOpenGLに関する修正です。この修正は大半のWindowsでは必要ありませんが、Qt5の方でOpenGLではなくOpenGLESを検出してしまった場合にセグメンテーションフォルトで終了してしまう場合があります。
セグメンテーションフォルトの部分は、ソースコードの修正で、終了しなくなるのですが、画面が真っ黒で表示できません。この不具合は、WindowsSDKをインストールしていた場合に生じるようです。
そのため、Windowsの場合には、Qt5のライブラリの自動検出ではなく、明示的にOpenGLを使う指定をすれば問題なくなります。もちろん、この修正を加えても本来OpenGLを自動検出する場合に影響を与えることはありません。
セグメンテーションフォルトへの対応
このバグは、何も検証なしに strlen関数をコールしているために生じるバグです。
diff --git a/src/Base/gl_1_5.c b/src/Base/gl_1_5.c
index 3f9953ae..a53bb448 100644
--- a/src/Base/gl_1_5.c
+++ b/src/Base/gl_1_5.c
@@ -1513,6 +1513,7 @@ static void LoadExtByName(const char *extensionName)
 
 static void ProcExtsFromExtString(const char *strExtList)
 {
+	if (strExtList == NULL) return;
 	size_t iExtListLen = strlen(strExtList);
 	const char *strExtListEnd = strExtList + iExtListLen;
 	const char *strCurrPos = strExtList;

Qt5のライブラリにOpenGLを使うように指定
diff --git a/src/Base/App.cpp b/src/Base/App.cpp
index d5b23a22..2619fa19 100644
--- a/src/Base/App.cpp
+++ b/src/Base/App.cpp
@@ -142,6 +142,9 @@ AppImpl::AppImpl(App* self, int& argc, char**& argv)
 #endif
 
     QCoreApplication::setAttribute(Qt::AA_X11InitThreads);
+#if defined(_WIN32) || defined(_WIN64)
+	QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
+#endif
 
     doQuit = false;

PythonPluginに対する修正

最後に、PythonPluginをコンパイルするための修正を行います。VS2017でビルドする場合には、この修正は必要ありませんが、VS2015 Update3の場合には、BoostPythonを使い場合に、外部のDLL内で定義されているクラスオブジェクトをPython側から呼び出す場合にエラーを生じる場合があります。
そのために、
CNOID_PYTHON_DEFINE_GET_POINTER

というマクロが src/Util/python/PyUtil.h の中で下のように定義されています。(詳細はhttp://stackoverflow.com/questions/38261530/unresolved-external-symbols-since-visual-studio-2015-update-3-boost-python-linkを参照してください)
#ifdef _MSC_VER
#define CNOID_PYTHON_DEFINE_GET_POINTER(CLASS) namespace boost { template <> CLASS const volatile * get_pointer<class CLASS const volatile >(class CLASS const volatile *c){ return c; } } 
#else
#define CNOID_PYTHON_DEFINE_GET_POINTER(classname)
#endif

したがって、PythonPluginから呼び出すC++のクラス定義を行っているソースファイルにCNOID_PYTHON_DEFINE_GET_POINTERのエントリーを追記していきます。また、このとき、純粋仮想関数を有するクラスは、この定義の影響でPython側から呼び出すことができなくなりますので、その修正も加えていきます。
なお、VS2015の場合には、 プリプロセッサ_MSC_VERは、1900となりますので(VS2017では、1910)下のように修正していきます。
diff --git a/src/Base/AbstractSeqItem.cpp b/src/Base/AbstractSeqItem.cpp
index 476cc47b..725936f7 100644
--- a/src/Base/AbstractSeqItem.cpp
+++ b/src/Base/AbstractSeqItem.cpp
@@ -127,3 +127,12 @@ void AbstractMultiSeqItem::doPutProperties(PutPropertyFunction& putProperty)
     AbstractSeqItem::doPutProperties(putProperty);
     putProperty(_("Num parts"), seq->getNumParts());
 }
+#if _MSC_VER == 1900
+AbstractMultiSeqPtr AbstractMultiSeqItem::abstractMultiSeq() {
+	return NULL;
+}
+
+AbstractSeqPtr AbstractSeqItem::abstractSeq() {
+	return NULL;
+}
+#endif
diff --git a/src/Base/AbstractSeqItem.h b/src/Base/AbstractSeqItem.h
index 309e1753..d0b89213 100644
--- a/src/Base/AbstractSeqItem.h
+++ b/src/Base/AbstractSeqItem.h
@@ -19,8 +19,12 @@ public:
     AbstractSeqItem(const AbstractSeqItem& org);
     virtual ~AbstractSeqItem();
 
-    virtual AbstractSeqPtr abstractSeq() = 0;
-
+#if _MSC_VER == 1900
+	virtual AbstractSeqPtr abstractSeq();
+#else
+	virtual AbstractSeqPtr abstractSeq() = 0;
+#endif
+ 
 protected:
     virtual void doPutProperties(PutPropertyFunction& putProperty);
     virtual bool store(Archive& archive);
@@ -38,7 +42,11 @@ public:
     virtual ~AbstractMultiSeqItem();
 
     virtual AbstractSeqPtr abstractSeq();
-    virtual AbstractMultiSeqPtr abstractMultiSeq() = 0;
+#if _MSC_VER == 1900
+    virtual AbstractMultiSeqPtr abstractMultiSeq();
+#else
+	virtual AbstractMultiSeqPtr abstractMultiSeq() = 0;
+#endif
 
 protected:
     virtual void doPutProperties(PutPropertyFunction& putProperty);
diff --git a/src/Base/AbstractTextItem.h b/src/Base/AbstractTextItem.h
index 360a8fd1..e9925ce9 100644
--- a/src/Base/AbstractTextItem.h
+++ b/src/Base/AbstractTextItem.h
@@ -17,7 +17,11 @@ public:
     AbstractTextItem();
     AbstractTextItem(const AbstractTextItem& org);
 
-    virtual const std::string& textFilename() const = 0;
+#if _MSC_VER == 1900
+	virtual const std::string& textFilename() { return ""; };
+#else
+	virtual const std::string& textFilename() const = 0;
+#endif
 
 protected:
     virtual ~AbstractTextItem();
diff --git a/src/Base/ScriptItem.cpp b/src/Base/ScriptItem.cpp
index 5fc50529..6fb7ad95 100644
--- a/src/Base/ScriptItem.cpp
+++ b/src/Base/ScriptItem.cpp
@@ -77,3 +77,25 @@ std::string ScriptItem::resultString() const
 {
     return string();
 }
+
+#if _MSC_VER == 1900
+const std::string& ScriptItem::scriptFilename() const {
+	return "";
+}
+
+void ScriptItem::setBackgroundMode(bool on) {
+	return;
+}
+
+bool ScriptItem::execute() {
+	return true;
+}
+
+SignalProxy<void()> ScriptItem::sigScriptFinished() {
+	return __sigScriptFinished__;
+}
+
+bool ScriptItem::terminate() {
+	return true;
+}
+#endif
diff --git a/src/Base/ScriptItem.h b/src/Base/ScriptItem.h
index 526cbdd8..84f212e6 100644
--- a/src/Base/ScriptItem.h
+++ b/src/Base/ScriptItem.h
@@ -18,16 +18,27 @@ public:
     ScriptItem(const ScriptItem& org);
 
     virtual const std::string& textFilename() const;
-    virtual const std::string& scriptFilename() const = 0;
+#if _MSC_VER == 1900
+	virtual const std::string& scriptFilename() const;
+#else
+	virtual const std::string& scriptFilename() const = 0;
+#endif
 
     virtual std::string identityName() const;
 
-    virtual void setBackgroundMode(bool on) = 0;
+#if _MSC_VER == 1900
+    virtual void setBackgroundMode(bool on);
+#else
+	virtual void setBackgroundMode(bool on) = 0;
+#endif
     virtual bool isBackgroundMode() const;
     virtual bool isRunning() const;
-        
-    virtual bool execute() = 0;
 
+#if _MSC_VER == 1900  
+    virtual bool execute();
+#else
+	virtual bool execute() = 0;
+#endif
     /**
        This function executes the code in the same namespace as that of the script exection.
        @note Implementing this function is optional.
    */
@@ -44,12 +55,21 @@ public:
         
     virtual std::string resultString() const;
 
-    virtual SignalProxy<void()> sigScriptFinished() = 0;
-        
-    virtual bool terminate() = 0;
+#if _MSC_VER == 1900
+	virtual SignalProxy<void()> sigScriptFinished();
+
+	virtual bool terminate();
+#else
+	virtual SignalProxy<void()> sigScriptFinished() = 0;
+
+	virtual bool terminate() = 0;
+#endif
 
 protected:
     virtual ~ScriptItem();
+#if _MSC_VER == 1900
+	SignalProxy<void()> __sigScriptFinished__;
+#endif
 };
 
 typedef ref_ptr<ScriptItem> ScriptItemPtr;
diff --git a/src/Base/python/PyItems.cpp b/src/Base/python/PyItems.cpp
index 43407a3e..e9a14eb5 100644
--- a/src/Base/python/PyItems.cpp
+++ b/src/Base/python/PyItems.cpp
@@ -25,6 +25,19 @@ using namespace cnoid;
 // for MSVC++2015 Update3
 CNOID_PYTHON_DEFINE_GET_POINTER(Item)
 CNOID_PYTHON_DEFINE_GET_POINTER(RootItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(MultiPointSetItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(PointSetItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(SceneItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(MultiSeqItem<class MultiSE3Seq>)
+CNOID_PYTHON_DEFINE_GET_POINTER(MultiSeqItem<class MultiAffine3Seq>)
+CNOID_PYTHON_DEFINE_GET_POINTER(MultiSeqItem<class MultiValueSeq>)
+CNOID_PYTHON_DEFINE_GET_POINTER(Vector3SeqItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(ExtCommandItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(FolderItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(AbstractMultiSeqItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(AbstractSeqItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(ScriptItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(AbstractTextItem)
 
 namespace {
 
@@ -320,8 +333,16 @@ void exportPyItems()
     PyItemList<MultiPointSetItem>("MultiPointSetItemList");
 
 #ifdef _MSC_VER
-    register_ptr_to_python<ItemPtr>();
-	register_ptr_to_python<RootItemPtr>();
+#define REGISTER_PTR_TO_PYTHON(CLASS)	do{ \
+	const boost::python::type_info cinfo = boost::python::type_id<CLASS>(); \
+	const boost::python::converter::registration* creg = boost::python::converter::registry::query(cinfo); \
+	if (creg == NULL){ boost::python::register_ptr_to_python<CLASS>(); 	} \
+	else if ((*creg).m_to_python == NULL) { boost::python::register_ptr_to_python<CLASS>(); }	}while (0)
+
+	//register_ptr_to_python<ItemPtr>();
+	//register_ptr_to_python<RootItemPtr>();
+	REGISTER_PTR_TO_PYTHON(ItemPtr);
+	REGISTER_PTR_TO_PYTHON(RootItemPtr);
 #endif
 
 }
diff --git a/src/Base/python/PyQtCore.cpp b/src/Base/python/PyQtCore.cpp
index 7f5b134e..e50d958b 100644
--- a/src/Base/python/PyQtCore.cpp
+++ b/src/Base/python/PyQtCore.cpp
@@ -11,6 +11,7 @@ using namespace boost::python;
 
 // for MSVC++2015 Update3
 CNOID_PYTHON_DEFINE_GET_POINTER(QObject)
+CNOID_PYTHON_DEFINE_GET_POINTER(QTimer)
 
 namespace {
 
diff --git a/src/Base/python/PyQtEx.cpp b/src/Base/python/PyQtEx.cpp
index 374b10c9..00b5ad56 100644
--- a/src/Base/python/PyQtEx.cpp
+++ b/src/Base/python/PyQtEx.cpp
@@ -11,6 +11,8 @@ using namespace boost;
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(Timer)
+
 namespace cnoid {
 
 void exportPyQtExTypes()
diff --git a/src/Base/python/PyQtGui.cpp b/src/Base/python/PyQtGui.cpp
index 6cc3b872..6a713749 100644
--- a/src/Base/python/PyQtGui.cpp
+++ b/src/Base/python/PyQtGui.cpp
@@ -12,6 +12,9 @@ using namespace boost::python;
 
 // for MSVC++2015 Update3
 CNOID_PYTHON_DEFINE_GET_POINTER(QWidget)
+CNOID_PYTHON_DEFINE_GET_POINTER(QToolButton)
+CNOID_PYTHON_DEFINE_GET_POINTER(QMainWindow)
+CNOID_PYTHON_DEFINE_GET_POINTER(QAbstractButton)
 
 namespace {
 
diff --git a/src/Base/python/PySceneTypes.cpp b/src/Base/python/PySceneTypes.cpp
index 875a0efb..fa6ad9b4 100644
--- a/src/Base/python/PySceneTypes.cpp
+++ b/src/Base/python/PySceneTypes.cpp
@@ -10,6 +10,9 @@ using namespace boost;
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(PositionDragger)
+CNOID_PYTHON_DEFINE_GET_POINTER(SceneDragger)
+
 namespace cnoid {
 
 void exportPySceneTypes()
diff --git a/src/Base/python/PyToolBars.cpp b/src/Base/python/PyToolBars.cpp
index 59084a37..24ebbbcb 100644
--- a/src/Base/python/PyToolBars.cpp
+++ b/src/Base/python/PyToolBars.cpp
@@ -14,6 +14,7 @@ using namespace cnoid;
 CNOID_PYTHON_DEFINE_GET_POINTER(QWidget)
 CNOID_PYTHON_DEFINE_GET_POINTER(ToolButton)
 CNOID_PYTHON_DEFINE_GET_POINTER(TimeBar)
+CNOID_PYTHON_DEFINE_GET_POINTER(ToolBar)
 
 namespace {

diff --git a/src/Body/python/PyBodyModule.cpp b/src/Body/python/PyBodyModule.cpp
index 9d084cf3..9496db8b 100644
--- a/src/Body/python/PyBodyModule.cpp
+++ b/src/Body/python/PyBodyModule.cpp
@@ -18,6 +18,9 @@ using namespace cnoid;
 // for MSVC++2015 Update3
 CNOID_PYTHON_DEFINE_GET_POINTER(Link)
 CNOID_PYTHON_DEFINE_GET_POINTER(Body)
+CNOID_PYTHON_DEFINE_GET_POINTER(BodyMotion)
+CNOID_PYTHON_DEFINE_GET_POINTER(JointPath)
+CNOID_PYTHON_DEFINE_GET_POINTER(Device)
 
 namespace
 {
@@ -262,7 +265,9 @@ BOOST_PYTHON_MODULE(Body)
             .def("hasVirtualJointForces", &Body::hasVirtualJointForces)
             .def("setVirtualJointForces", &Body::setVirtualJointForces)
             .def("addCustomizerDirectory", &Body::addCustomizerDirectory).staticmethod("addCustomizerDirectory")
+#ifndef _MSC_VER
             .def(other<BodyMotion::Frame>() >> self)
+#endif
             ;
 
     }
@@ -336,7 +341,9 @@ BOOST_PYTHON_MODULE(Body)
         class_< BodyMotion::Frame >("Frame", no_init)
             .def("frame", &BodyMotion::Frame::frame)
             .def(self << other<Body>())
+#ifndef _MSC_VER
             .def(other<Body>() >> self)
+#endif
             ;
     }
 
@@ -361,8 +368,16 @@ BOOST_PYTHON_MODULE(Body)
     }
 
 #ifdef _MSC_VER
-    register_ptr_to_python<BodyPtr>();
-    register_ptr_to_python<LinkPtr>();
+#define REGISTER_PTR_TO_PYTHON(CLASS)	do{ \
+	const boost::python::type_info cinfo = boost::python::type_id<CLASS>(); \
+	const boost::python::converter::registration* creg = boost::python::converter::registry::query(cinfo); \
+	if (creg == NULL){ boost::python::register_ptr_to_python<CLASS>(); 	} \
+	else if ((*creg).m_to_python == NULL) { boost::python::register_ptr_to_python<CLASS>(); }	}while (0)
+
+//    register_ptr_to_python<BodyPtr>();
+ //   register_ptr_to_python<LinkPtr>();
+	REGISTER_PTR_TO_PYTHON(BodyPtr);
+	REGISTER_PTR_TO_PYTHON(LinkPtr);
 #endif
 
 }

diff --git a/src/BodyPlugin/SimulationScriptItem.h b/src/BodyPlugin/SimulationScriptItem.h
index 0972b5e5..09b8ea1e 100644
--- a/src/BodyPlugin/SimulationScriptItem.h
+++ b/src/BodyPlugin/SimulationScriptItem.h
@@ -34,7 +34,11 @@ public:
     void setExecutionDelay(double t);
 
     virtual bool execute();
-    virtual bool executeAsSimulationScript() = 0;
+#if _MSC_VER == 1900
+	virtual bool executeAsSimulationScript() { return true; };
+#else
+	virtual bool executeAsSimulationScript() = 0;
+#endif
 
 protected:
     virtual ~SimulationScriptItem();
diff --git a/src/BodyPlugin/python/PyBodyItem.cpp b/src/BodyPlugin/python/PyBodyItem.cpp
index 04ebbb50..87a2603d 100644
--- a/src/BodyPlugin/python/PyBodyItem.cpp
+++ b/src/BodyPlugin/python/PyBodyItem.cpp
@@ -9,6 +9,8 @@
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(BodyItem)
+
 namespace {
 
 BodyItemPtr loadBodyItem(const std::string& filename) {
diff --git a/src/BodyPlugin/python/PyItems.cpp b/src/BodyPlugin/python/PyItems.cpp
index 3e069d34..ce2c9153 100644
--- a/src/BodyPlugin/python/PyItems.cpp
+++ b/src/BodyPlugin/python/PyItems.cpp
@@ -9,6 +9,9 @@
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(BodyMotionItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(WorldItem)
+
 namespace {
 
 BodyMotionPtr BodyMotionItem_motion(BodyMotionItem& self) { return self.motion(); }
diff --git a/src/BodyPlugin/python/PySimulationClasses.cpp b/src/BodyPlugin/python/PySimulationClasses.cpp
index ab47f576..78146c1d 100644
--- a/src/BodyPlugin/python/PySimulationClasses.cpp
+++ b/src/BodyPlugin/python/PySimulationClasses.cpp
@@ -18,6 +18,9 @@ using namespace cnoid;
 // for MSVC++2015 Update3
 //CNOID_PYTHON_DEFINE_GET_POINTER(SimulatorItem)
 CNOID_PYTHON_DEFINE_GET_POINTER(SimulationBar)
+CNOID_PYTHON_DEFINE_GET_POINTER(SimpleControllerItem)
+CNOID_PYTHON_DEFINE_GET_POINTER(SimulationBody)
+CNOID_PYTHON_DEFINE_GET_POINTER(SimulationScriptItem)
 
 namespace {
 
diff --git a/src/PoseSeqPlugin/python/PyPoseSeqPlugin.cpp b/src/PoseSeqPlugin/python/PyPoseSeqPlugin.cpp
index 427722eb..2c1dd936 100644
--- a/src/PoseSeqPlugin/python/PyPoseSeqPlugin.cpp
+++ b/src/PoseSeqPlugin/python/PyPoseSeqPlugin.cpp
@@ -8,6 +8,8 @@
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(PoseSeqItem)
+
 BOOST_PYTHON_MODULE(PoseSeqPlugin)
 {
     class_< PoseSeqItem, PoseSeqItemPtr, bases<Item> >("PoseSeqItem");

diff --git a/src/PythonSimScriptPlugin/python/PyPythonSimScriptPlugin.cpp b/src/PythonSimScriptPlugin/python/PyPythonSimScriptPlugin.cpp
index 221b1711..1128352c 100644
--- a/src/PythonSimScriptPlugin/python/PyPythonSimScriptPlugin.cpp
+++ b/src/PythonSimScriptPlugin/python/PyPythonSimScriptPlugin.cpp
@@ -8,6 +8,9 @@
 using namespace boost::python;
 using namespace cnoid;
 
+// for MSVC++2015 Update3
+CNOID_PYTHON_DEFINE_GET_POINTER(PythonSimScriptItem)
+
 BOOST_PYTHON_MODULE(PythonSimScriptPlugin)
 {
     class_< PythonSimScriptItem, PythonSimScriptItemPtr, bases<SimulationScriptItem> >("PythonSimScriptItem")

diff --git a/src/Util/python/PySceneGraph.cpp b/src/Util/python/PySceneGraph.cpp
index bcdb0d35..65a7f7ef 100644
--- a/src/Util/python/PySceneGraph.cpp
+++ b/src/Util/python/PySceneGraph.cpp
@@ -9,6 +9,13 @@
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(SgPosTransform)
+CNOID_PYTHON_DEFINE_GET_POINTER(SgGroup)
+CNOID_PYTHON_DEFINE_GET_POINTER(SgNode)
+CNOID_PYTHON_DEFINE_GET_POINTER(SceneProvider)
+CNOID_PYTHON_DEFINE_GET_POINTER(SgTransform)
+CNOID_PYTHON_DEFINE_GET_POINTER(SgObject)
+
 namespace {
 
 void SgObject_notifyUpdate1(SgObject& self){ self.notifyUpdate(); }
diff --git a/src/Util/python/PyTask.cpp b/src/Util/python/PyTask.cpp
index badf5857..2cffccb8 100644
--- a/src/Util/python/PyTask.cpp
+++ b/src/Util/python/PyTask.cpp
@@ -17,10 +17,148 @@ using namespace boost::python;
 namespace python = boost::python;
 using namespace cnoid;
 
+#if _MSC_VER == 1900
+namespace cnoid {
+
+	class TaskWrap : public Task, public python::wrapper<Task>
+	{
+	public:
+		TaskWrap() { };
+
+		TaskWrap(const std::string& name, const std::string& caption) : Task(name, caption) { };
+
+		TaskWrap(const Task& org, bool doDeepCopy = true) : Task(org, doDeepCopy) { };
+
+		virtual void onMenuRequest(TaskMenu& menu) {
+			bool called = false;
+			{
+				PyGILock lock;
+				try {
+					if (python::override onMenuRequest = this->get_override("onMenuRequest")) {
+						called = true;
+						onMenuRequest(boost::ref(menu));
+					}
+				}
+				catch (python::error_already_set const& ex) {
+					cnoid::handlePythonException();
+				}
+			}
+			if (!called) {
+				Task::onMenuRequest(menu);
+			}
+		}
+
+		void default_onMenuRequest(TaskMenu& menu) {
+			return this->Task::onMenuRequest(menu);
+		}
+
+		virtual void onActivated(AbstractTaskSequencer* sequencer) {
+			bool isOverridden = false;
+			{
+				PyGILock lock;
+				try {
+					if (python::override func = this->get_override("onActivated")) {
+						isOverridden = true;
+						func(boost::ref(sequencer));
+					}
+				}
+				catch (python::error_already_set const& ex) {
+					cnoid::handlePythonException();
+				}
+			}
+			if (!isOverridden) {
+				Task::onActivated(sequencer);
+			}
+		}
+
+		void default_onActivated(AbstractTaskSequencer* sequencer) {
+			return this->Task::onActivated(sequencer);
+		}
+
+		virtual void onDeactivated(AbstractTaskSequencer* sequencer) {
+			bool isOverridden = false;
+			{
+				PyGILock lock;
+				try {
+					if (python::override func = this->get_override("onDeactivated")) {
+						isOverridden = true;
+						func(boost::ref(sequencer));
+					}
+				}
+				catch (python::error_already_set const& ex) {
+					cnoid::handlePythonException();
+				}
+			}
+			if (!isOverridden) {
+				Task::onDeactivated(sequencer);
+			}
+		}
+
+		void default_onDeactivated(AbstractTaskSequencer* sequencer) {
+			return this->Task::onDeactivated(sequencer);
+		}
+
+		virtual void storeState(AbstractTaskSequencer* sequencer, Mapping& archive) {
+			bool isOverridden = false;
+			{
+				PyGILock lock;
+				try {
+					if (python::override storeStateFunc = this->get_override("storeState")) {
+						isOverridden = true;
+						MappingPtr a = &archive;
+						storeStateFunc(boost::ref(sequencer), a);
+					}
+				}
+				catch (python::error_already_set const& ex) {
+					cnoid::handlePythonException();
+				}
+			}
+			if (!isOverridden) {
+				Task::storeState(sequencer, archive);
+			}
+		}
+
+		void default_storeState(AbstractTaskSequencer* sequencer, Mapping& archive) {
+			return this->Task::storeState(sequencer, archive);
+		}
+
+		virtual void restoreState(AbstractTaskSequencer* sequencer, const Mapping& archive) {
+			bool isOverridden = false;
+			{
+				PyGILock lock;
+				try {
+					if (python::override restoreState = this->get_override("restoreState")) {
+						isOverridden = true;
+						MappingPtr a = const_cast<Mapping*>(&archive);
+						restoreState(boost::ref(sequencer), a);
+					}
+				}
+				catch (python::error_already_set const& ex) {
+					cnoid::handlePythonException();
+				}
+			}
+			if (!isOverridden) {
+				Task::restoreState(sequencer, archive);
+			}
+		}
+
+		void default_restoreState(AbstractTaskSequencer* sequencer, const Mapping& archive) {
+			return this->Task::restoreState(sequencer, archive);
+		}
+	};
+
+}
+#endif
+
 // for MSVC++2015 Update3
 CNOID_PYTHON_DEFINE_GET_POINTER(TaskProc)
 CNOID_PYTHON_DEFINE_GET_POINTER(TaskMenu)
 CNOID_PYTHON_DEFINE_GET_POINTER(AbstractTaskSequencer)
+CNOID_PYTHON_DEFINE_GET_POINTER(TaskPhase)
+CNOID_PYTHON_DEFINE_GET_POINTER(TaskCommand)
+CNOID_PYTHON_DEFINE_GET_POINTER(TaskToggleState)
+CNOID_PYTHON_DEFINE_GET_POINTER(TaskPhaseProxy)
+CNOID_PYTHON_DEFINE_GET_POINTER(TaskWrap)
         
 namespace {
 
@@ -313,6 +451,7 @@ void TaskMenu_addMenuSeparator(TaskMenu& self){
     self.addMenuSeparator();
 }
 
+#if _MSC_VER != 1900
 class TaskWrap : public Task, public python::wrapper<Task>
 {
 public :
@@ -434,6 +573,7 @@ public :
         return this->Task::restoreState(sequencer, archive);
     }
 };
+#endif
 
 typedef ref_ptr<TaskWrap> TaskWrapPtr;
 
diff --git a/src/Util/python/PyUtil.h b/src/Util/python/PyUtil.h
index 12ab33f5..028ddb80 100644
--- a/src/Util/python/PyUtil.h
+++ b/src/Util/python/PyUtil.h
@@ -44,7 +44,7 @@ struct pointee< cnoid::ref_ptr<T> >
    The following macro is used to avoid compile errors caused by a bug of VC++ 2015 Update 3
    http://stackoverflow.com/questions/38261530/unresolved-external-symbols-since-visual-studio-2015-update-3-boost-python-link
 */
-#ifdef _MSC_VER
+#if _MSC_VER == 1900
 #define CNOID_PYTHON_DEFINE_GET_POINTER(CLASS) namespace boost { template <> CLASS const volatile * get_pointer<class CLASS const volatile >(class CLASS const volatile *c){ return c; } } 
 #else
 #define CNOID_PYTHON_DEFINE_GET_POINTER(classname)
diff --git a/src/Util/python/PyUtilModule.cpp b/src/Util/python/PyUtilModule.cpp
index a3fb9318..52ef1ad4 100644
--- a/src/Util/python/PyUtilModule.cpp
+++ b/src/Util/python/PyUtilModule.cpp
@@ -10,6 +10,8 @@
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(Referenced)
+
 namespace
 {
 
diff --git a/src/Util/python/PyValueTree.cpp b/src/Util/python/PyValueTree.cpp
index 00fb7d68..d2b89da3 100644
--- a/src/Util/python/PyValueTree.cpp
+++ b/src/Util/python/PyValueTree.cpp
@@ -10,6 +10,10 @@ using namespace boost;
 using namespace boost::python;
 using namespace cnoid;
 
+CNOID_PYTHON_DEFINE_GET_POINTER(Listing)
+CNOID_PYTHON_DEFINE_GET_POINTER(Mapping)
+CNOID_PYTHON_DEFINE_GET_POINTER(ValueNode)
+
 namespace {
 
 MappingPtr ValueNode_toMapping(ValueNode& self){


また、これは必須ではないのですが、Pythonコンソールではフォントの拡大縮小が効きませんので Ctrl+Up とCtrl+Downにフォントの拡大縮小を割り当てます。
diff --git a/src/PythonPlugin/PythonConsoleView.cpp b/src/PythonPlugin/PythonConsoleView.cpp
index 47a2de4c..7e74d9f9 100644
--- a/src/PythonPlugin/PythonConsoleView.cpp
+++ b/src/PythonPlugin/PythonConsoleView.cpp
@@ -579,7 +579,12 @@ void PythonConsoleViewImpl::keyPressEvent(QKeyEvent* event)
             break;
         }
     case Qt::Key_Up:
-        setInputString(getPrevHistoryEntry());
+		if (event->modifiers() == Qt::ControlModifier) {
+			zoomIn();
+		}
+		else {
+			setInputString(getPrevHistoryEntry());
+		}
         done = true;
         break;
         
@@ -588,7 +593,12 @@ void PythonConsoleViewImpl::keyPressEvent(QKeyEvent* event)
             break;
         }
     case Qt::Key_Down:
-        setInputString(getNextHistoryEntry());
+		if (event->modifiers() == Qt::ControlModifier) {
+			zoomOut();
+		}
+		else {
+			setInputString(getNextHistoryEntry());
+		}
         done = true;
         break;
以上でChoreonoidのソースコードの修正は完了です。

Choreonoidのビルド

前述までの修正が完了すれば、あとはオフィシャルサイトにあるビルド方法を実行すればOKです。
Choreonoid.org「ソースコードからのビルドとインストール (Windows編)」の「CMakeによるビルド設定」からはじめればよいかと思います。

資料