garaemon.net: 脳汁でコードを書く

menu

top

softwares

2010-09-01-01-20-09 rosinstall

rosinstall

今日は意外と要望があるかもしれないと思って, rosinstallについて書きます.

rosinstallとはROS とよばれるロボットミドルウェアの環境構築において, はじめに 利用するスクリプトです. 参考

ROSは, aptでのインストールもサポートしていますが, 個人的にはソースコードから buildするのを好んで使っています.

このページ によると, 例えば以下のような例があげられていますが,

$ rosinstall ~/ros http://ros.org/rosinstalls/cturtle_ros.rosinstall 

この*.rosinstallというファイルは自分で書いても良いので, 自分なりのrosinstallファイルを 書くことをおすすめします(ROS初心者は意外とこれに気づいていないかも).

たとえば, 以下のようなgaraemon.rosinstallを用意してみます.

$ cat garaemon.rosinstall
- svn:
    uri: https://code.ros.org/svn/ros/stacks/ros/tags/cturtle
    local-name: ros
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/arm_navigation/tags/cturtle
    local-name: stacks/arm_navigation
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/camera_drivers/tags/cturtle
    local-name: stacks/camera_drivers
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/collision_environment/tags/cturtle
    local-name: stacks/collision_environment
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/common/tags/cturtle
    local-name: stacks/common
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/common_msgs/tags/cturtle
    local-name: stacks/common_msgs
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/diagnostics/tags/cturtle
    local-name: stacks/diagnostics
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/driver_common/tags/cturtle
    local-name: stacks/driver_common
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/executive_python/tags/cturtle
    local-name: stacks/executive_python
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/executive_smach/tags/cturtle
    local-name: stacks/executive_smach
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/geometry/tags/cturtle
    local-name: stacks/geometry
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/graph_mapping/tags/cturtle
    local-name: stacks/graph_mapping
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/image_common/tags/cturtle
    local-name: stacks/image_common
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/image_pipeline/tags/cturtle
    local-name: stacks/image_pipeline
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/image_transport_plugins/tags/cturtle
    local-name: stacks/image_transport_plugins
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/imu_drivers/tags/cturtle
    local-name: stacks/imu_drivers
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/joystick_drivers/tags/cturtle
    local-name: stacks/joystick_drivers
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/joystick_drivers_tutorials/tags/cturtle
    local-name: stacks/joystick_drivers_tutorials
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/kinematics/tags/cturtle
    local-name: stacks/kinematics
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/laser_drivers/tags/cturtle
    local-name: stacks/laser_drivers
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/laser_pipeline/tags/cturtle
    local-name: stacks/laser_pipeline
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/motion_planners/tags/cturtle
    local-name: stacks/motion_planners
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/motion_planning_common/tags/cturtle
    local-name: stacks/motion_planning_common
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/motion_planning_environment/tags/cturtle
    local-name: stacks/motion_planning_environment
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/motion_planning_visualization/tags/cturtle
    local-name: stacks/motion_planning_visualization
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/navigation/tags/cturtle
    local-name: stacks/navigation
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/object_manipulation/tags/cturtle
    local-name: stacks/object_manipulation
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/people/tags/cturtle
    local-name: stacks/people
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/physics_ode/tags/cturtle
    local-name: stacks/physics_ode
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/point_cloud_perception/tags/cturtle
    local-name: stacks/point_cloud_perception
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_apps/tags/cturtle
    local-name: stacks/pr2_apps
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_arm_navigation/tags/cturtle
    local-name: stacks/pr2_arm_navigation
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_arm_navigation_apps/tags/cturtle
    local-name: stacks/pr2_arm_navigation_apps
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_arm_navigation_tests/tags/cturtle
    local-name: stacks/pr2_arm_navigation_tests
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_calibration/tags/cturtle
    local-name: stacks/pr2_calibration
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_cockpit/tags/cturtle
    local-name: stacks/pr2_cockpit
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_common/tags/cturtle
    local-name: stacks/pr2_common
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_common_actions/tags/cturtle
    local-name: stacks/pr2_common_actions
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_controllers/tags/cturtle
    local-name: stacks/pr2_controllers
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_doors/tags/cturtle
    local-name: stacks/pr2_doors
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_ethercat_drivers/tags/cturtle
    local-name: stacks/pr2_ethercat_drivers
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_gui/tags/cturtle
    local-name: stacks/pr2_gui
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_kinematics/tags/cturtle
    local-name: stacks/pr2_kinematics
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_kinematics_with_constraints/tags/cturtle
    local-name: stacks/pr2_kinematics_with_constraints
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_mechanism/tags/cturtle
    local-name: stacks/pr2_mechanism
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_navigation/tags/cturtle
    local-name: stacks/pr2_navigation
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_navigation_apps/tags/cturtle
    local-name: stacks/pr2_navigation_apps
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_object_manipulation/tags/cturtle
    local-name: stacks/pr2_object_manipulation
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_plugs/tags/cturtle
    local-name: stacks/pr2_plugs
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_power_drivers/tags/cturtle
    local-name: stacks/pr2_power_drivers
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_robot/tags/cturtle
    local-name: stacks/pr2_robot
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_self_test/tags/cturtle
    local-name: stacks/pr2_self_test
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_simulator/tags/cturtle
    local-name: stacks/pr2_simulator
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_tabletop_manipulation_apps/tags/cturtle
    local-name: stacks/pr2_tabletop_manipulation_apps
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/pr2_web_apps/tags/cturtle
    local-name: stacks/pr2_web_apps
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/robot_calibration/tags/cturtle
    local-name: stacks/robot_calibration
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/robot_model/tags/cturtle
    local-name: stacks/robot_model
- svn:
    uri: https://code.ros.org/svn/ros/stacks/ros_realtime/tags/cturtle
    local-name: stacks/ros_realtime
- svn:
    uri: https://code.ros.org/svn/ros/stacks/ros_tutorials/tags/cturtle
    local-name: stacks/ros_tutorials
- svn:
    uri: https://code.ros.org/svn/ros/stacks/roslisp_support/tags/cturtle
    local-name: stacks/roslisp_support
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/simulator_gazebo/tags/cturtle
    local-name: stacks/simulator_gazebo
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/simulator_stage/tags/cturtle
    local-name: stacks/simulator_stage
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/slam_gmapping/tags/cturtle
    local-name: stacks/slam_gmapping
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/slam_karto/tags/cturtle
    local-name: stacks/slam_karto
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/sound_drivers/tags/cturtle
    local-name: stacks/sound_drivers
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/sql_database/tags/cturtle
    local-name: stacks/sql_database
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/tabletop_object_perception/tags/cturtle
    local-name: stacks/tabletop_object_perception
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/trajectory_filters/tags/cturtle
    local-name: stacks/trajectory_filters
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/vision_opencv/tags/cturtle
    local-name: stacks/vision_opencv
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/visualization/tags/cturtle
    local-name: stacks/visualization
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/visualization_common/tags/cturtle
    local-name: stacks/visualization_common
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/tags/cturtle
    local-name: stacks/visualization_tutorials
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/vslam/tags/cturtle
    local-name: stacks/vslam
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/web_interface/tags/cturtle
    local-name: stacks/web_interface
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/wg_common/tags/cturtle
    local-name: stacks/wg_common
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/wg_hardware_test/tags/cturtle
    local-name: stacks/wg_hardware_test
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/wg_pr2_apps/tags/cturtle
    local-name: stacks/wg_pr2_apps
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/wifi_drivers/tags/cturtle
    local-name: stacks/wifi_drivers
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/vision_opencv/trunk
    local-name: stacks/vision_opencv
- svn:
    uri: https://code.ros.org/svn/ros-pkg/branches/trunk_cturtle/stacks/camera_drivers_experimental
    local-name: stacks/camera_drivers_experimental
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/texas_drivers/tags/latest
    local-name: stacks/texas_drivers
- svn:
    uri: https://code.ros.org/svn/ros-pkg/stacks/navigation_experimental/tags/cturtle
    local-name: stacks/navigation_experimental
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/stacks/topological_navigation/tags/cturtle
    local-name: stacks/topological_navigation
- svn:
    uri: https://code.ros.org/svn/wg-ros-pkg/branches/trunk_cturtle
    local-name: wg-ros-pkg-unreleased
- svn:
    uri: https://code.ros.org/svn/ros-pkg/branches/trunk_cturtle
    local-name: ros-pkg-unreleased
- svn:
    uri: https://code.ros.org/svn/ros/stacks/ros_experimental/trunk
    local-name: ros-experimental-trunk
- svn:
    uri: https://cmu-ros-pkg.svn.sourceforge.net/svnroot/cmu-ros-pkg/trunk
    local-name: cmu-ros-pkg
- svn:
    uri: https://code.ros.org/svn/ros/stacks/ros_tutorials/trunk
    local-name: ros_tutorials
- svn:
    uri: https://code.ros.org/svn/ros-pkg/branches/trunk_cturtle/stacks/ros_pkg_tutorials
    local-name: ros_pkg_tutorials
- svn:
    uri: https://ua-ros-pkg.googlecode.com/svn/trunk/arrg
    local-name: ua-ros-pkg
- svn:
    uri: https://bosch-ros-pkg.svn.sourceforge.net/svnroot/bosch-ros-pkg/trunk
    local-name: bosch-ros-pkg
- svn:
    uri: https://prairiedog.googlecode.com/svn/trunk
    local-name: prairiedog-ros-pkg
- svn:
    uri: https://sail-ros-pkg.svn.sourceforge.net/svnroot/sail-ros-pkg/trunk
    local-name: sail-ros-pkg
- svn:
    uri: https://tum-ros-pkg.svn.sourceforge.net/svnroot/tum-ros-pkg
    local-name: tum-ros-pkg
- svn:
    uri: http://brown-ros-pkg.googlecode.com/svn/tags/brown-ros-pkg
    local-name: brown-ros-pkg
- svn:
    uri: http://alufr-ros-pkg.googlecode.com/svn/trunk/
    local-name: alufr-ros-pkg
- svn:
    uri: http://cu-ros-pkg.googlecode.com/svn/trunk
    local-name: cu-ros-pkg
- svn:
    uri: http://gt-ros-pkg.googlecode.com/svn/trunk
    local-name: gt-ros-pkg
- git:
    uri: http://robotics.ccny.cuny.edu/git/ccny-ros-pkg.git/
    local-name: ccny-ros-pkg
- svn:
    uri: http://svn.mech.kuleuven.be/repos/orocos/trunk/kul-ros-pkg
    local-name: kul-ros-pkg
- svn: 
    uri: http://utexas-art-ros-pkg.googlecode.com/svn/trunk/stacks/
    local-name: utexas-art-ros-pkg
- svn:
    uri: https://usc-ros-pkg.svn.sourceforge.net/svnroot/usc-ros-pkg/trunk
    local-name: usc-ros-pkg
- svn:
    uri: https://wu-ros-pkg.svn.sourceforge.net/svnroot/wu-ros-pkg/stacks
    local-name: wu-ros-pkg
- git:
    uri: http://github.com/IHeartRobotics/iheart-ros-pkg.git
    local-name: ihart-ros-pkg
- svn:
    uri: https://jsk-ros-pkg.svn.sourceforge.net/svnroot/jsk-ros-pkg/trunk
    local-name: jsk-ros-pkg

フォーマットはYAMLで, 分かりやすいと思います. 前半部分はcturtle_pr2all.rosinstallからの コピーです.

このファイルはhttp://garaemon.net/garaemon.rosinstall に置いてあるので, 以下のようにして rosinstallを呼び出します. (もちろんweb上におかなくてもOK)

$ rosinstall ~/ros http://garaemon.net/garaemon.rosinstall

ROSは非常によく出来ているので(特にツールチェインの充実がうれしい), ロボットを研究とかで 触っている人は, 試してみる価値があるかと思います.

個人的に気に入ってるのはrospyとpclです.

また, rosinstallで注意したほうがいいのは, 同じ名前のpackage, stackがあるとあれれな ことになります.

また, ここに上げたrosinstallは一部のレポジトリしかカバーできていませんが, いろいろな ところのrosレポジトリを入れておいて, つねにアンテナを張っておくと結構楽しいです.

jsk-rosemacs and emacs-settings

rosをemacs上で開発するには, rosemacs というemacs lispがあってこれを使うのが良いです. (とてもよく出来ている).

しかし, もしもあなたがrosemacsのキーバインドを覚えられないほど怠惰なら,jsk-rosemacs を 使ってみてはどうでしょうか?

jsk-rosemacsを使うと, anything.el で, rosのパッケージにアクセスできます.

インストールは, 拙作ながら, emacs-settingsを使うと便利です. anythingとかを 勝手にいれてくれます.

$ git clone git://github.com/garaemon/emacs-settings.git
$ cd emacs-settings
$ ./emacs-settings setup >> ~/.emacs
$ ./emacs-settings install jsk-rosemacs

あとは, anythingのsourceの設定をします. 僕はこんな感じです

(require 'anything)
(require 'anything-config)
(require 'anything-rospack)
(setq anything-sources
      (list anything-c-source-buffers
            anything-c-rospack-source
            anything-c-source-file-name-history
            anything-c-source-imenu
            anything-c-source-recentf
            ;;anything-c-source-man-pages
            ;;anything-c-source-info-pages
            anything-c-source-calculation-result
            anything-c-source-kill-ring
            ;;anything-c-source-bookmarks
            ;;anything-c-source-locate))
            ))

(global-set-key "\C-xb" 'anything)
(global-set-key "\M-y" 'anything-show-kill-ring)
(anything-iswitchb-setup)

(define-key anything-map (kbd "C-p") 'anything-previous-line)
(define-key anything-map (kbd "C-n") 'anything-next-line)
(define-key anything-map (kbd "C-v") 'anything-next-source)
(define-key anything-map (kbd "M-v") 'anything-previous-source)
(global-set-key "\C-xp" (lambda () (interactive) (other-window -1)))

emacs-settingsを使うと, この設定でよければ以下でもってこれます.

$ ./emacs-settings add http://garaemon.net/emacs-settings-repo/garaemon.el
$ ./emacs-settings install garaemon-anything-setting

実行するとこんな感じです. ./images/20100901-anything-rospack.png

2010-08-21-01-35-26 sbclコードリーディング(3)

infoまわり (cont.)

前回 からのつづきでsb-int:infoをみていきます.

struct type-info (src/compiler/globaldb.lisp)

これは, class-infoに所有されてる構造体です. 定義は以下のような感じ.

(defstruct (type-info
            #-no-ansi-print-object
            (:print-object (lambda (x s)
                             (print-unreadable-object (x s)
                               (format s
                                       "~S ~S, Number = ~W"
                                       (class-info-name (type-info-class x))
                                       (type-info-name x)
                                       (type-info-number x)))))
            (:copier nil))
  ;; the name of this type
  (name (missing-arg) :type keyword)
  ;; this type's class
  (class (missing-arg) :type class-info)
  ;; a number that uniquely identifies this type (and implicitly its class)
  (number (missing-arg) :type type-number)
  ;; a type specifier which info of this type must satisfy
  (type nil :type t)
  ;; a function called when there is no information of this type
  (default (lambda () (error "type not defined yet")) :type function)
  ;; called by (SETF INFO) before calling SET-INFO-VALUE
  (validate-function nil :type (or function null)))

まぁあんまよくわかりませんね. なんか保持してるんでしょう(ぇ. ちなみに, *info-types*にはtype-infoの全てのリストが保持されています.

* SB-C::*INFO-TYPES*
#(#<:FUNCTION :KIND, Number = 0> #<:FUNCTION :TYPE, Number = 1>
  #<:FUNCTION :ASSUMED-TYPE, Number = 2> #<:FUNCTION :WHERE-FROM, Number = 3>
  #<:FUNCTION :INLINE-EXPANSION-DESIGNATOR, Number = 4>
  #<:FUNCTION :INLINEP, Number = 5> #<:FUNCTION :SOURCE-TRANSFORM, Number = 6>
  #<:FUNCTION :MACRO-FUNCTION, Number = 7>
  #<:FUNCTION :COMPILER-MACRO-FUNCTION, Number = 8>
  #<:FUNCTION :IR1-CONVERT, Number = 9> #<:FUNCTION :INFO, Number = 10>
  #<:FUNCTION :DEFINITION, Number = 11>
  #<:FUNCTION :STRUCTURE-ACCESSOR, Number = 12> #<:VARIABLE :KIND, Number = 13>
  #<:VARIABLE :ALWAYS-BOUND, Number = 14> #<:VARIABLE :TYPE, Number = 15>
  #<:VARIABLE :WHERE-FROM, Number = 16>
  #<:VARIABLE :XC-CONSTANT-VALUE, Number = 17>
  #<:VARIABLE :MACRO-EXPANSION, Number = 18>
  #<:VARIABLE :ALIEN-INFO, Number = 19>
  #<:VARIABLE :DOCUMENTATION, Number = 20> #<:TYPE :KIND, Number = 21>
  #<:TYPE :EXPANDER, Number = 22> #<:TYPE :DOCUMENTATION, Number = 23>
  #<:TYPE :TRANSLATOR, Number = 24> #<:TYPE :BUILTIN, Number = 25>
  #<:TYPE :COMPILER-LAYOUT, Number = 26> #<:TYPE :LAMBDA-LIST, Number = 27>
  #<:TYPE :SOURCE-LOCATION, Number = 28> #<:TYPED-STRUCTURE :INFO, Number = 29>
  #<:TYPED-STRUCTURE :DOCUMENTATION, Number = 30>
  #<:DECLARATION :RECOGNIZED, Number = 31>
  #<:DECLARATION :HANDLER, Number = 32> #<:ALIEN-TYPE :KIND, Number = 33>
  #<:ALIEN-TYPE :TRANSLATOR, Number = 34>
  #<:ALIEN-TYPE :DEFINITION, Number = 35> #<:ALIEN-TYPE :STRUCT, Number = 36>
  #<:ALIEN-TYPE :UNION, Number = 37> #<:ALIEN-TYPE :ENUM, Number = 38>
  #<:SETF :INVERSE, Number = 39> #<:SETF :DOCUMENTATION, Number = 40>
  #<:SETF :EXPANDER, Number = 41> #<:RANDOM-DOCUMENTATION :STUFF, Number = 42>
  #<:SOURCE-LOCATION :VARIABLE, Number = 43>
  #<:SOURCE-LOCATION :CONSTANT, Number = 44>
  #<:SOURCE-LOCATION :TYPED-STRUCTURE, Number = 45>
  #<:SOURCE-LOCATION :SYMBOL-MACRO, Number = 46> NIL NIL NIL NIL NIL NIL NIL
  NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)

class-infoとtype-info

ここでclass-infoとtype-infoについて簡単にまとめて図にしてみます.

anything-rospack

function find-type-info (src/compiler/globaldb.lisp)

前回 , find-type-infoはtype-info-or-loseから呼ばれていました.

定義は

(defun find-type-info (name class)
  (declare (type keyword name) (type class-info class))
  (dolist (type (class-info-types class) nil)
    (when (eq (type-info-name type) name)
      (return type))))

ここまでくると大体想像はついてましたが, class-infoのtypesから, nameにマッチする type-infoを探してくるようです.

やっぱこういう処理はdolistとreturnで書くのが速いのかなあ.

function get-info-value (src/compiler/globaldb.lisp)

ようやくget-info-valueにまで来ました. これは, sb-int:infoから直接呼ばれています.

定義.

;;; Return the value of NAME / TYPE from the first environment where
;;; has it defined, or return the default if none does. We used to
;;; do a lot of complicated caching here, but that was removed for
;;; thread-safety reasons.
(defun get-info-value (name0 type &optional (env-list nil env-list-p))
  (declare (type type-number type))
  ;; sanity check: If we have screwed up initialization somehow, then
  ;; *INFO-TYPES* could still be uninitialized at the time we try to
  ;; get an info value, and then we'd be out of luck. (This happened,
  ;; and was confusing to debug, when rewriting EVAL-WHEN in
  ;; sbcl-0.pre7.x.)
  (aver (aref *info-types* type))
  (let ((name (uncross name0)))
    (flet ((lookup (env-list)
             (let ((hash nil))
               (dolist (env env-list
                        (multiple-value-bind (val winp)
                            (funcall (type-info-default
                                      (svref *info-types* type))
                                      name)
                          (values val winp)))
                 (macrolet ((frob (lookup)
                              `(progn
                                 (setq hash (globaldb-sxhashoid name))
                                 (multiple-value-bind (value winp)
                                     (,lookup env name hash type)
                                   (when winp (return (values value t)))))))
                   (etypecase env
                     (volatile-info-env (frob volatile-info-lookup))
                     (compact-info-env (frob compact-info-lookup))))))))
      (if env-list-p
          (lookup env-list)
          (lookup *info-environment*)))))

なんかけっこう重い.

aver(src/code/ealry-extentions.lisp)はassertみたいなものです. uncross(src/code/uncross.lisp)はまぁidentityと思ってOK.

globaldb-sxhashoidはsxhash の最適化版らしいです.

最後からみていくと,

(if env-list-p
  (lookup env-list)
 (lookup *info-environment*))

結局fletされてるlookupを呼ぶ, と.

lookupの定義は, dolistでenv-listを順にみていって, envの型に応じて, volatile-info-lookupかcompact-info-lookupか切り替えてます.

うーん, よくわからないですが, env-listの中からname / typeがみつかればそれを返し, みつからなかったら*info-types*からデフォルトを返すといったところでしょうか.

compact-info-envもvolatile-info-envもhashtableをもっていることに留意しておけば なんとなく推定できますね. つまり, このテーブルから引いてくると. (setf info)もこのテーブルに適切に値を入れるものであると 推定できます (あっているかはわからない).

(defstruct (compact-info-env (:include info-env)
                             #-sb-xc-host (:pure :substructure)
                             (:copier nil))
  (table (missing-arg) :type simple-vector)
  (index (missing-arg) :type (simple-array compact-info-entries-index (*)))
  (entries (missing-arg) :type simple-vector)
  (entries-info (missing-arg) :type (simple-array compact-info-entry (*))))

(defstruct (volatile-info-env (:include info-env)
                              (:copier nil))
  (table (missing-arg) :type simple-vector)
  (count 0 :type index)
  (threshold 0 :type index))

2010-08-19-02-16-05 sbclコードリーディング(2)

infoまわり

sb-int:infoというのがsbclでは関数の定義されてる環境テーブルになっているようです. 今回はそこをみていきます. 前回

function sb-int:info (src/compiler/globaldb.lisp)

定義を見てみましょう.

(defun info (class type name &optional (env-list nil env-list-p))
  (let ((info (type-info-or-lose class type)))
    (if env-list-p
        (get-info-value name (type-info-number info) env-list)
        (get-info-value name (type-info-number info)))))

実際の使われ方は,

(eq (info :variable :kind name) :macro)

とかのようです.

ためしに呼んでみます.

> (sb-int:info :variable :kind 'aa)

:UNKNOWN
NIL
> (sb-int:info :variable :kind 'listp)

:UNKNOWN
NIL
> (sb-int:info :function :kind 'listp)

:FUNCTION
T

なんとなくイメージはつかめますね.

function type-info-or-lose (src/compiler/globaldb.lisp)

ソースは色々けずると以下のような感じです.

(defun type-info-or-lose (class type)
  (prog1
      (or (find-type-info type (class-info-or-lose class))
          (error "~S is not a defined info type." type))))

さらに飛ばされます.

function class-info-or-lose (src/compiler/globaldb.lisp)

定義は以下のような感じ. *info-classes*というハッシュテーブルを引いてますね. そしてclassが シンボルであったら, plistを使ってメモ化してますね.

(defun class-info-or-lose (class)
  (declare (type keyword class))
  (prog1
      (flet ((lookup (class)
               (or (gethash class *info-classes*)
                   (error "~S is not a defined info class." class))))
        (if (symbolp class)
            (or (get class 'class-info-or-lose-cache)
                (setf (get class 'class-info-or-lose-cache)
                      (lookup class)))
            (lookup class)))))

実際に呼んでみましょう.

> (SB-C::CLASS-INFO-OR-LOSE :variable)

#<SB-C::CLASS-INFO :VARIABLE>
> (SB-C::CLASS-INFO-OR-LOSE :function)

#<SB-C::CLASS-INFO :FUNCTION>
> (SB-C::CLASS-INFO-OR-LOSE :hoge)

debugger invoked on a SIMPLE-ERROR in thread #<THREAD "initial thread" RUNNING
                                               {A9F59D1}>:
  :HOGE is not a defined info class.

*info-classes*とはなんでしょうか?

> (maphash #'(lambda (key value) 
    (format t "key -> ~A, value -> ~A~%" key value)) 
   sb-c::*info-classes*)
key -> ALIEN-TYPE, value -> #<CLASS-INFO :ALIEN-TYPE>
key -> DECLARATION, value -> #<CLASS-INFO :DECLARATION>
key -> FUNCTION, value -> #<CLASS-INFO :FUNCTION>
key -> RANDOM-DOCUMENTATION, value -> #<CLASS-INFO :RANDOM-DOCUMENTATION>
key -> SETF, value -> #<CLASS-INFO :SETF>
key -> SOURCE-LOCATION, value -> #<CLASS-INFO :SOURCE-LOCATION>
key -> TYPE, value -> #<CLASS-INFO :TYPE>
key -> TYPED-STRUCTURE, value -> #<CLASS-INFO :TYPED-STRUCTURE>
key -> VARIABLE, value -> #<CLASS-INFO :VARIABLE>

全部で9種類あるようです. randam-documentationってなんだろう…

struct class-info (src/compiler/globaldb.lisp)

class-infoは, classの名前とtype-infoのリストを持つようです.

(defstruct (class-info
            (:constructor make-class-info (name))
            #-no-ansi-print-object
            (:print-object (lambda (x s)
                             (print-unreadable-object (x s :type t)
                               (prin1 (class-info-name x) s))))
            (:copier nil))
  ;; name of this class
  (name nil :type keyword :read-only t)
  ;; list of Type-Info structures for each type in this class
  (types () :type list))

眠いので今日はここまで.

2010-08-19-02-02-00 Walker's alias methodをつかったParticle Filter

particle filter

最近研究で画像処理てきなことなどをしているわけですが, そこでかなり適当ですがParticle FilterをC++で 実装したので, 自分用のメモとして載せておきます.

実際研究で作ってるプログラムはもちっとこみいってますが, Particle Filterについてはここ を見てください. 復元抽出にWalker's alias methodをつかってます. これについてはこちら を参考に.

実装はC++で, すべてヘッダに書いてます(ぇ. バグとかあったら教えてもらえると嬉しいです. ちなみにC++素人です.

#include <vector>
#include <boost/function.hpp>
#include <boost/random.hpp>
#include <boost/math/distributions/normal.hpp>
#include <ctime>
#include <iostream>

namespace PF
{
    // see http://ja.wikipedia.org/wiki/Boost
    double SampleNormal (double mean, double sigma)
    {
        using namespace boost;
        static mt19937 rng(static_cast<unsigned> (std::time(0)));

        normal_distribution<double> norm_dist(mean, sqrt(sigma));

        variate_generator<mt19937&, normal_distribution<double> >
            normal_sampler(rng, norm_dist);

        return normal_sampler();
    }

    class Particle
    {
    protected:
        double _weight;
        double _orig_likelihood;
        std::vector<double> _state;

    public:

        Particle() {};
        Particle(const int dim): _weight(0.0), _state(dim, 0.0) {};
        // copy constructor
        Particle(const Particle& orig):
            _weight(orig._weight), _orig_likelihood(orig._orig_likelihood)
            {
                _state = std::vector<double>(orig.getState().size());
                for (size_t i = 0; i < orig.getState().size(); i++)
                    _state[i] = orig.getStateValue(i);
            };

        virtual ~Particle() {};

        virtual inline const std::vector<double>& getState() const
            {
                return _state;
            };

        /* does not overwrite _orig_likelihood */
        virtual inline void updateWeight(const double weight)
            {
                _weight = weight;
            };

        /* overwrite _orig_likelihood */
        virtual inline void setWeight(const double weight)
            {
                _weight = weight;
                _orig_likelihood = weight;
            };

        virtual inline double getWeight() const { return _weight; };
        virtual inline double getStateValue(const size_t i) const
            {
                return _state[i];
            };

        virtual inline void setStateValue(const size_t i, const double val)
            {
                _state[i] = val;
            };

        virtual inline double getOriginalLikelihood() const
            {
                return _orig_likelihood;
            };

        virtual void sample(const std::vector<double>& mean,
                            const std::vector<double>& cov)
            {
                for ( size_t j = 0; j < _state.size(); j++ )
                    _state[j] += SampleNormal(mean[j], cov[j]);
            };

        virtual inline void zero()
            {
                for ( size_t j = 0; j < _state.size(); j++ )
                    _state[j] = 0.0;
            };

    };

    std::ostream& operator << (std::ostream& s, const Particle &p)
    {
        s << p.getState()[0] << ", " << p.getState()[1] << ", "
          << p.getState()[2] << ", " << p.getState()[3] << ", "
          << p.getState()[4] << ", " << p.getState()[5];
        return s;
    }

    typedef enum
    {
        UPDATE_MEAN, UPDATE_MAX
    } UpdateParticleFilterMethod;

    class SimpleParticleFilter
    {
        // using gaussian for noising
    protected:
        boost::function<double (std::vector<double>)> _func;
        int _dim;
        int _particle_num;
        std::vector<double> _initial_noise_covariance;
        std::vector<double> _initial_noise_mean;
        std::vector<double> _step_noise_covariance;
        UpdateParticleFilterMethod _update_method;
        std::vector<Particle> _particles;
        Particle _representive_state;

        void normalizeWeight()
            {
                // calc weight summaction
                double sum = 0.0;
                for ( int i = 0; i < _particle_num; i++ )
                    sum += _particles[i].getWeight();
                // too small weight summation, re-initialize particles
                if ( sum <= 1e-5 )
                    initParticles();
                else
                    for ( int i = 0; i < _particle_num; i++ )
                        _particles[i].updateWeight(_particles[i].getWeight() / sum);
            };
    public:
        SimpleParticleFilter(int dim, int particle_num,
                             std::vector<double> initial_noise_mean,
                             std::vector<double> initial_noise_covariance,
                             std::vector<double> step_noise_covariance,
                             boost::function<double (std::vector<double>)> func,
                             UpdateParticleFilterMethod method = UPDATE_MEAN):
            _func(func), _dim(dim), _particle_num(particle_num),
            _initial_noise_covariance(initial_noise_covariance),
            _initial_noise_mean(initial_noise_mean),
            _step_noise_covariance(step_noise_covariance),
            _update_method(method)
            {
                _representive_state = Particle(dim);
                initParticles();
            };
        virtual inline Particle getResult(){ return _representive_state; };
        virtual ~SimpleParticleFilter() { };

        /* sampling with replacement based on Walker's alias method

           @article{355749,
           author = {Walker, Alastair J.},
           title = {An Efficient Method for Generating Discrete
           Random Variables with General Distributions},
           journal = {ACM Trans. Math. Softw.},
           volume = {3},
           number = {3},
           year = {1977},
           issn = {0098-3500},
           pages = {253--256},
           doi = {http://doi.acm.org/10.1145/355744.355749},
           publisher = {ACM},
           address = {New York, NY, USA},
           }

           implementation reference is:
           http://tolstoy.newcastle.edu.au/R/devel/05/06/1403.html
        */
        virtual void genAliasTable(std::vector<int> &a, std::vector<double> &q)
            {
                /* generate an alias table, a and q */
                std::vector<int> HL(_particle_num);
                std::vector<int>::iterator H = HL.begin();
                std::vector<int>::iterator L = HL.end() - 1;
                for ( int i = 0; i < _particle_num; i++ )
                    q[i] = _particles[i].getWeight() * _particle_num;
                for ( int i = 0; i < _particle_num; i++ )
                    a[i] = i;
                // setup H and L
                for ( int i = 0; i < _particle_num; i++ )
                    if ( q[i] >= 1.0 )
                        *H++ = i;
                    else
                        *L-- = i;
                while ( H != HL.begin() && L != HL.end() - 1 )
                {
                    int j = *(L + 1);
                    int k = *(H - 1);
                    a[j] = k;
                    q[k] += q[j] - 1;
                    L++;
                    if ( q[k] < 1.0 )
                    {
                        *L-- = k;
                        --H;
                    }
                }
            }

        virtual inline int sampleWithReplacement(const std::vector<int>& a,
                                                 const std::vector<double>& q)
            {
                using namespace boost;
                static mt19937 gen( static_cast<unsigned long>(time(0)));
                uniform_real<> dst(0.0, 1.0);
                variate_generator<mt19937&, uniform_real<> > rand(gen, dst);
                double rU = rand() * _particle_num;
                int k = (int)rU;
                rU -= k;    /* rU - [rU] */
                if ( rU < q[k] )
                    return k;
                else
                    return a[k];
            };

        void resample()            
            {
                std::vector<int> a(_particle_num);
                std::vector<double> q(_particle_num);
                genAliasTable(a, q);

                const static std::vector<double> zero_mean(_dim, 0.0);
                // escape the original list of particles
                std::vector<Particle> orig_particles = _particles;

                _particles.clear();
                for ( int i = 0; i < _particle_num; i++ )
                {
                    int target_particle_index = sampleWithReplacement(a, q);
                    Particle p = orig_particles[target_particle_index];
                    // add noise using gaussian
                    p.sample(zero_mean, _step_noise_covariance);
                    _particles.push_back(p);
                }
            };

        void weight()
            {
                // call _func for each particles
                for ( int i = 0; i < _particle_num; i++ )
                {
                    double likelihood = _func(_particles[i].getState());
                    _particles[i].setWeight(likelihood);
                }
                normalizeWeight();
            };
        void update_mean()
            {
                //fill by zero
                _representive_state.zero();

                // update
                for ( int i = 0; i < _particle_num; i++)
                {
                    Particle p = _particles[i];
                    for ( int j = 0; j < _dim; j++ )
                    {
                        double a = p.getStateValue(j) * p.getWeight();
                        double b = _representive_state.getStateValue(j);
                        _representive_state.setStateValue(j, a + b);
                    }
                }
            };

        void update_max()
            {
                int max_index = 0;
                double max_weight = 0.0;
                for ( int i = 0; i < _particle_num; i++)
                {
                    Particle p = _particles[i];
                    if ( p.getWeight() > max_weight )
                    {
                        max_weight = p.getWeight();
                        max_index = i;
                    }
                }
                _representive_state = _particles[max_index];
            };

        void update()
            {
                // update
                switch(_update_method)
                {
                case UPDATE_MEAN:
                    update_mean();
                    break;
                case UPDATE_MAX:
                    update_max();
                    break;
                default:
                    break;
                }
            };

        void initParticles()    // finish
            {
                std::cout << "initParticles" << std::endl;
                _particles = std::vector<Particle>(_particle_num, _dim);
                // sampling...
                for ( int i = 0; i < _particle_num; i++ )
                {
                    Particle p(_dim);
                    // w = 1 / N;
                    p.setWeight(1.0 / _particle_num);
                    p.zero();
                    p.sample(_initial_noise_mean, _initial_noise_covariance);
                    _particles[i] = p; // update
                }
            };
        inline std::vector<Particle> getParticles() { return _particles; };
    };
}

2010-08-03-01-36-19 sbclコードリーディング(1)

夏だからsbclのソースコードを読もう

夏なのでsbclのコードでも読んでみようかと思います. 主にコンパイラ周りを. オイラに読み解けるのか…?

どっかにwikiみたいなの置いたほうが良いかなー

macro defun (src/code/defboot.lisp)

(defun add (a b)
  (+ a b))

というところからスタートしてみたいと思います.

* (macroexpand '(defun add (a b) (+ a b)))

(PROGN
 (EVAL-WHEN (:COMPILE-TOPLEVEL) (SB-C:%COMPILER-DEFUN 'ADD 'NIL T))
 (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE)
   (SB-IMPL::%DEFUN 'ADD
                    (SB-INT:NAMED-LAMBDA ADD
                        (A B)
                      (BLOCK ADD (+ A B)))
                    NIL 'NIL (SB-C:SOURCE-LOCATION))))

らしいので, とりあえずSB-IMPL::%DEFUNをみてみます

function SB-IMPL::%DEFUN (src/code/defboot.lisp)

定義は

(defun %defun (name def doc inline-lambda source-location)
  (declare (type function def))
  (declare (type (or null simple-string) doc))
  (aver (legal-fun-name-p name)) ; should've been checked by DEFMACRO DEFUN
  (sb!c:%compiler-defun name inline-lambda nil)
  (when (fboundp name)
    (/show0 "redefining NAME in %DEFUN")
    (style-warn 'sb!kernel::redefinition-with-defun :name name
                :old (fdefinition name) :new def
                :new-location source-location))
  (setf (sb!xc:fdefinition name) def)

  (sb!c::note-name-defined name :function)

  (when doc
    (setf (%fun-doc def) doc))

  name)

適時!は-に読み替えます.

結局,

(sb-c:%compiler-defun 'add (SB-INT:NAMED-LAMBDA ADD
                        (A B)
                      (BLOCK ADD (+ A B))) nil)

が呼ばれるのかな.

function SB-C:%COMPILER-DEFUN (src/compiler/ir1tran-lambda.lisp)

IR1はthe first intermediate representationのことらしい.

定義

(defun %compiler-defun (name lambda-with-lexenv compile-toplevel)
  (let ((defined-fun nil)) ; will be set below if we're in the compiler
    (when compile-toplevel
      (setf defined-fun (get-defined-fun name))
      (when (boundp '*lexenv*)
        (remhash name *free-funs*)
        (aver (fasl-output-p *compile-object*))
        (if (member name *fun-names-in-this-file* :test #'equal)
            (warn 'duplicate-definition :name name)
            (push name *fun-names-in-this-file*))))

    (become-defined-fun-name name)

    (cond (lambda-with-lexenv
           (setf (info :function :inline-expansion-designator name)
                 lambda-with-lexenv)
           (when defined-fun
             (setf (defined-fun-inline-expansion defined-fun)
                   lambda-with-lexenv)))
          (t
           (clear-info :function :inline-expansion-designator name)))

    ;; old CMU CL comment:
    ;;   If there is a type from a previous definition, blast it,
    ;;   since it is obsolete.
    (when (and defined-fun
               (eq (leaf-where-from defined-fun) :defined))
      (setf (leaf-type defined-fun)
            ;; FIXME: If this is a block compilation thing, shouldn't
            ;; we be setting the type to the full derived type for the
            ;; definition, instead of this most general function type?
            (specifier-type 'function))))

  (values))

結局,

(SB-KERNEL:BECOME-DEFINED-FUN-NAME 'add)
(setf (sb-int:info :function :inline-expansion-designator 'add)
                 (SB-INT:NAMED-LAMBDA ADD
                        (A B)
                      (BLOCK ADD (+ A B))))

が実行されるのかな?

Author: garaemon

Date: 2010-09-01 02:11:17 JST

HTML generated by org-mode 7.01h in emacs 23