Raspberry pi camera servers
(→Keeper) |
(→common camera server) |
||
(8 intermediate revisions by one user not shown) | |||
Line 3: | Line 3: | ||
This configuration guide is for the raspberry pi cameras and for the single camera server. | This configuration guide is for the raspberry pi cameras and for the single camera server. | ||
+ | |||
+ | == Prerequisites == | ||
+ | |||
+ | It is assumed that mobotware is compiled for (or on) raspberry, and installed to /usr/local/smr, e.g. from the mobotware directory like this: | ||
+ | |||
+ | cd mobotware | ||
+ | make | ||
+ | sudo make install | ||
+ | |||
+ | Make takes a long time (one hour or so). | ||
+ | |||
+ | The make install installs the needed files into /usr/local/smr.local and links to this from /usr/local/smr. But do not put anything into /etc/rc.local. | ||
+ | |||
== Files needed == | == Files needed == | ||
Line 31: | Line 44: | ||
# | # | ||
exit 0 | exit 0 | ||
+ | |||
+ | This starts a script placed in /home/local named startKeeper as the user local. | ||
+ | This is to run as much as possible without root privileges. | ||
+ | |||
+ | Copy the start script to /home/local (beeing the user ''local'': | ||
+ | |||
+ | cd | ||
+ | cp mobotware/build/config/gogo/picam/startKeeper . | ||
+ | chmod +x startKeeper | ||
+ | |||
+ | Make a live directory where the configuration files for keeper and camera server resides, and copy the ini-files: | ||
+ | |||
+ | mkdir live | ||
+ | cd live | ||
+ | cp mobotware/build/config/gogo/picam/*.ini . | ||
+ | |||
+ | Theaukeeper.ini file looks something like this | ||
+ | |||
+ | # open server - port and path | ||
+ | server port=24926 | ||
+ | server imagepath="/var/log/keeper" | ||
+ | server datapath="/var/log/keeper" | ||
+ | module load=var | ||
+ | # cam | ||
+ | module load="if" alias=cam | ||
+ | cam connect=localhost:24920 | ||
+ | camonconnect cmd="cam push t=3 cmd='var allcopy'" | ||
+ | var global.requiredclients=1 | ||
+ | var global.keep.cam=1 | ||
+ | var global.caminifile="/home/local/live/ucamserver.ini" | ||
+ | # start rules | ||
+ | module load="aurule.so.0" | ||
+ | rule log=false | ||
+ | rule load="/usr/local/smr/bin/aursconf/keepcam.rule" | ||
+ | rule resume | ||
+ | |||
+ | The keeper uses a rule to monitor and restart the cameraserver, this is assumed to be placed in /usr/local/smr/bin/aursconf, so copy the rules there (they may be there already, so probably not needed) | ||
+ | |||
+ | sudo cp *.rule /usr/local/smr/bin/aursconf/ | ||
+ | |||
+ | The rule used for the camera server looks like this: | ||
+ | |||
+ | <?xml version="1.0" ?> | ||
+ | <rule name="keepcam" if="defined('cam.connected')"> | ||
+ | <description> | ||
+ | * This rule is trying to keep cam server running, when the | ||
+ | number of clients is more than required in global.requiredclients and | ||
+ | the variable global.keep.cam is true. | ||
+ | * This rule starts when the cam interface module is available (and | ||
+ | has created the variable cam.connected). | ||
+ | * When number of clients falls below the number of required, then | ||
+ | the server is closed (if it was started by the keeper). | ||
+ | * If the cam server is running already then the keeper will monitor the running | ||
+ | instance and restart it if it crashes. The server is crashed if no "alive" signal | ||
+ | is received within 3 seconds (value in alive rule below) | ||
+ | </description> | ||
+ | <init> | ||
+ | # define global status variables | ||
+ | global.alive.cam = false | ||
+ | global.alive.camStarted = false | ||
+ | allow = 7 # allow time is allowed time to be dead | ||
+ | if (not defined('global.keep.cam')) | ||
+ | global.keep.cam=false | ||
+ | deadCnt = allow + 1 | ||
+ | <rule name="alive" if="cam.connected[1] and | ||
+ | cam.hostalive and | ||
+ | not global.alive.cam"> | ||
+ | global.alive.cam = true | ||
+ | print("cam is alive after " deadCnt " secs to start") | ||
+ | deadCnt = 0 | ||
+ | allow = 3 # seen alive to dead detect | ||
+ | </rule> | ||
+ | <rule name="deadCnt" if="not cam.connected[1] or not cam.hostalive"> | ||
+ | # if (deadCnt < 0.51) | ||
+ | # print("cam seems to be dying " deadCnt " : cam.connected=" cam.connected[1] ", cam.alive=" cam.hostalive) | ||
+ | deadCnt = deadCnt + rulestate.sampletime | ||
+ | </rule> | ||
+ | <rule name="noclient" if="cam.connected[1] and | ||
+ | global.requiredclients > core.clients and | ||
+ | global.alive.camStarted"> | ||
+ | global.alive.camStarted = false | ||
+ | print("Closing cam server - as there is no clients left on port " core.port) | ||
+ | core.send("cam quit") | ||
+ | </rule> | ||
+ | <rule name="dead" if="deadCnt >= allow and global.alive.cam"> | ||
+ | print("cam assumed dead after " deadCnt " secs with no responce") | ||
+ | print(" - cam status: cam.connected=" cam.connected[1] ", cam.alive=" cam.hostalive) | ||
+ | global.alive.cam = false | ||
+ | global.alive.camStarted = false | ||
+ | </rule> | ||
+ | <rule name="start" if="core.clients >= global.requiredclients and | ||
+ | not global.alive.cam and | ||
+ | not global.alive.camStarted and | ||
+ | global.keep.cam"> | ||
+ | <init> | ||
+ | inistr=" " | ||
+ | startstr=" " | ||
+ | </init> | ||
+ | deadCnt = 0 | ||
+ | if (defined("global.caminifile")) | ||
+ | inistr = "--script " global.caminifile | ||
+ | global.alive.camStarted = true | ||
+ | allow = 30 # allow for start-up time | ||
+ | # startstr = 'su -c "nice --adjustment=5 /usr/local/smr/bin/startserver ucamserver ' inistr '" local' | ||
+ | startstr = 'nice --adjustment=5 /usr/local/smr/bin/startserver ucamserver ' inistr | ||
+ | core.send("bash " startstr) | ||
+ | </rule> | ||
+ | </init> | ||
+ | # keep monitoring rule active | ||
+ | wait() : false | ||
+ | </rule> | ||
+ | |||
+ | It is a XML formatted rule script, as defined for the aurule.so.0 plugin. | ||
+ | |||
+ | === Camera server on Raspberry camera === | ||
+ | |||
+ | In the live directory is the camera configuration file, it looks something like this: | ||
+ | |||
+ | local@rpi7:~/mobotware/build/config/gogo/picam $ cat ucamserver.ini | ||
+ | #!/bin/bash | ||
+ | # camera server scriptfile | ||
+ | server imagepath="." | ||
+ | server datapath="." | ||
+ | server replayPath="foo" | ||
+ | # server port=24920 | ||
+ | # | ||
+ | module load=var | ||
+ | module load=odopose | ||
+ | module load=aurule.so.0 | ||
+ | module load=aupoly.so.0 | ||
+ | # camera parameters | ||
+ | camset device=6 focallength=532 posx=0.45 posy=0.03 posz=0.65 rotphi=0 rotkappa=-1.57 # east -90 deg | ||
+ | camset device=7 focallength=532 posx=0.45 posy=0.00 posz=0.65 rotphi=0 rotkappa=0 | ||
+ | camset device=8 focallength=532 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=-0.785 | ||
+ | camset device=9 focallength=532 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=0.785 | ||
+ | camset device=10 focallength=532 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=1.57 | ||
+ | # raspberry pi camera | ||
+ | module load=aupicam.so.0 | ||
+ | # use the one fit for this pi-cam | ||
+ | # will then use the corresponding image-pool number | ||
+ | # then much easier when collecting images | ||
+ | var picam.camDeviceNum=6 | ||
+ | ; var picam.camDeviceNum=7 | ||
+ | ; var picam.camDeviceNum=8 | ||
+ | ; var picam.camDeviceNum=9 | ||
+ | ; var picam.camDeviceNum=10 | ||
+ | var picam.framerate=2 | ||
+ | var picam.resolution="768 1024" | ||
+ | var picam.white=7 | ||
+ | var picam.exposuremode=1 | ||
+ | var picam.meter=0 | ||
+ | var picam.pyramidlevels=3 | ||
+ | picam open | ||
+ | # end of script | ||
+ | |||
+ | |||
+ | The ''camset'' commands configure the raspberry camera with different numbers, this is to ease the transfer of images to the combining camera server. | ||
+ | |||
+ | Near the end is the camera number for this raspberry camera defined - the others are commented out. | ||
+ | |||
+ | NB! it seems like a frame rate of 1 (var picam.framerate=1) will not work, so keep it at 2 or higher. | ||
+ | |||
+ | == common camera server == | ||
+ | |||
+ | A camera server to combine all the images may be needed - at least for logging of images and odometry. | ||
+ | |||
+ | The camera server configuration file could look like this: | ||
+ | |||
+ | local@rpi7:~/mobotware/build/config/gogo $ cat ucamserver.ini | ||
+ | #!/bin/bash | ||
+ | server imagepath="." | ||
+ | server datapath="." | ||
+ | server replayPath="log_cam" | ||
+ | server port=24920 | ||
+ | # | ||
+ | module load=var | ||
+ | # | ||
+ | module load=odoPose | ||
+ | odopose log | ||
+ | module load=mappose | ||
+ | mappose log | ||
+ | module load=utmpose | ||
+ | utmpose log | ||
+ | ;mapPose replay | ||
+ | module load=ucamif.so.0 | ||
+ | camdata add=img | ||
+ | camdata add=gmk | ||
+ | camdata add=path | ||
+ | camdata add=cam | ||
+ | ; | ||
+ | # autostart cameraserver on raspberry pi cameras | ||
+ | module load=if alias=cam6keep | ||
+ | module load=if alias=cam7keep | ||
+ | module load=if alias=cam8keep | ||
+ | module load=if alias=cam9keep | ||
+ | module load=if alias=cam10keep | ||
+ | cam6keep connect=rpi6.local:24926 | ||
+ | cam7keep connect=rpi7.local:24926 | ||
+ | cam8keep connect=rpi8.local:24926 | ||
+ | cam9keep connect=rpi9.local:24926 | ||
+ | cam10keep connect=rpi10.local:24926 | ||
+ | ; ; | ||
+ | # connect to get images | ||
+ | module load=if alias=cam6 | ||
+ | module load=if alias=cam7 | ||
+ | module load=if alias=cam8 | ||
+ | module load=if alias=cam9 | ||
+ | module load=if alias=cam10 | ||
+ | ; # | ||
+ | camset device=6 focallength=455 posx=0.45 posy=0.03 posz=0.65 rotphi=0 rotkappa=0.8 | ||
+ | camset device=7 focallength=455 posx=0.45 posy=0.00 posz=0.65 rotphi=0 rotkappa=0 | ||
+ | camset device=8 focallength=455 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=-0.8 | ||
+ | camset device=9 focallength=455 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=-1.57 | ||
+ | camset device=10 focallength=455 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=1.57 | ||
+ | ; ; | ||
+ | # load images scaled 2 levels down cam 6 is img=6+2 = 8 | ||
+ | # to get small overview images | ||
+ | cam6onconnect cmd="cam6 poolpush img=8 cmd='poolget all toimg=26 fmt=rgb'" | ||
+ | cam7onconnect cmd="cam7 poolpush img=9 cmd='poolget all toimg=27 fmt=rgb'" | ||
+ | cam8onconnect cmd="cam8 poolpush img=10 cmd='poolget all toimg=28 fmt=rgb'" | ||
+ | cam9onconnect cmd="cam9 poolpush img=11 cmd='poolget all toimg=29 fmt=rgb'" | ||
+ | cam10onconnect cmd="cam10 poolpush img=12 cmd='poolget all toimg=30 fmt=rgb'" | ||
+ | ; ; | ||
+ | cam6 connect=rpi6.local:24920 | ||
+ | cam7 connect=rpi7.local:24920 | ||
+ | cam8 connect=rpi8.local:24920 | ||
+ | cam9 connect=rpi9.local:24920 | ||
+ | cam10 connect=rpi10.local:24920 | ||
+ | ; | ||
+ | poolset img=26 log | ||
+ | poolset img=27 log | ||
+ | poolset img=28 log | ||
+ | poolset img=29 log | ||
+ | poolset img=30 log | ||
+ | ; | ||
+ | |||
+ | This configuration file connects to 5 camera boards. | ||
+ | |||
+ | This gets an image from each of the raspberry pi cameras and load them to image numbers 26 to 30 in RGB format. |
Latest revision as of 18:29, 5 May 2016
This is notes from installation multi-raspberry pi camera (3 or 5 raspberry pi, each with a camera). The camera images is then collected in one single camera server.
This configuration guide is for the raspberry pi cameras and for the single camera server.
Contents |
[edit] Prerequisites
It is assumed that mobotware is compiled for (or on) raspberry, and installed to /usr/local/smr, e.g. from the mobotware directory like this:
cd mobotware make sudo make install
Make takes a long time (one hour or so).
The make install installs the needed files into /usr/local/smr.local and links to this from /usr/local/smr. But do not put anything into /etc/rc.local.
[edit] Files needed
In mobotware a configuration example is in mobotware/build/config/gogo and mobotware/build/config/gogo/picam.
ls mobotware/build/config/gogo picam rhdconfig.xml ucamserver.ini ls mobotware/build/config/gogo/picam aukeeper.ini connectrhd.rule keepcam.rule keeplaser.rule keepnav.rule rc.local startKeeper ucamserver.ini
In mobotware/build/config/gogo/picam is the configuration files for the raspberry pi camera, the mobotware/build/config/gogo/ucamserver.ini is the configuration file for the single image collecting camera server (mostly for image recording).
[edit] Raspberry pi camera
The raspberry pi cameras in this example is named rpi6, rpi7, ... rpi10 as their hostname (in /etc/hostname).
[edit] Keeper
The keeper is a server that starts the cameraserver when needed (and restarts it if it crashes or gets stuck in other ways).
The Keeper should be started at reboot using the /etc/rc.local, like this line almostat the end of rc.local:
# rc.local ... # start keeper su -c "/home/local/startKeeper" local # exit 0
This starts a script placed in /home/local named startKeeper as the user local. This is to run as much as possible without root privileges.
Copy the start script to /home/local (beeing the user local:
cd cp mobotware/build/config/gogo/picam/startKeeper . chmod +x startKeeper
Make a live directory where the configuration files for keeper and camera server resides, and copy the ini-files:
mkdir live cd live cp mobotware/build/config/gogo/picam/*.ini .
Theaukeeper.ini file looks something like this
# open server - port and path server port=24926 server imagepath="/var/log/keeper" server datapath="/var/log/keeper" module load=var # cam module load="if" alias=cam cam connect=localhost:24920 camonconnect cmd="cam push t=3 cmd='var allcopy'" var global.requiredclients=1 var global.keep.cam=1 var global.caminifile="/home/local/live/ucamserver.ini" # start rules module load="aurule.so.0" rule log=false rule load="/usr/local/smr/bin/aursconf/keepcam.rule" rule resume
The keeper uses a rule to monitor and restart the cameraserver, this is assumed to be placed in /usr/local/smr/bin/aursconf, so copy the rules there (they may be there already, so probably not needed)
sudo cp *.rule /usr/local/smr/bin/aursconf/
The rule used for the camera server looks like this:
<?xml version="1.0" ?> <rule name="keepcam" if="defined('cam.connected')"> <description> * This rule is trying to keep cam server running, when the number of clients is more than required in global.requiredclients and the variable global.keep.cam is true. * This rule starts when the cam interface module is available (and has created the variable cam.connected). * When number of clients falls below the number of required, then the server is closed (if it was started by the keeper). * If the cam server is running already then the keeper will monitor the running instance and restart it if it crashes. The server is crashed if no "alive" signal is received within 3 seconds (value in alive rule below) </description> <init> # define global status variables global.alive.cam = false global.alive.camStarted = false allow = 7 # allow time is allowed time to be dead if (not defined('global.keep.cam')) global.keep.cam=false deadCnt = allow + 1 <rule name="alive" if="cam.connected[1] and cam.hostalive and not global.alive.cam"> global.alive.cam = true print("cam is alive after " deadCnt " secs to start") deadCnt = 0 allow = 3 # seen alive to dead detect </rule> <rule name="deadCnt" if="not cam.connected[1] or not cam.hostalive"> # if (deadCnt < 0.51) # print("cam seems to be dying " deadCnt " : cam.connected=" cam.connected[1] ", cam.alive=" cam.hostalive) deadCnt = deadCnt + rulestate.sampletime </rule> <rule name="noclient" if="cam.connected[1] and global.requiredclients > core.clients and global.alive.camStarted"> global.alive.camStarted = false print("Closing cam server - as there is no clients left on port " core.port) core.send("cam quit") </rule> <rule name="dead" if="deadCnt >= allow and global.alive.cam"> print("cam assumed dead after " deadCnt " secs with no responce") print(" - cam status: cam.connected=" cam.connected[1] ", cam.alive=" cam.hostalive) global.alive.cam = false global.alive.camStarted = false </rule> <rule name="start" if="core.clients >= global.requiredclients and not global.alive.cam and not global.alive.camStarted and global.keep.cam"> <init> inistr=" " startstr=" " </init> deadCnt = 0 if (defined("global.caminifile")) inistr = "--script " global.caminifile global.alive.camStarted = true allow = 30 # allow for start-up time # startstr = 'su -c "nice --adjustment=5 /usr/local/smr/bin/startserver ucamserver ' inistr '" local' startstr = 'nice --adjustment=5 /usr/local/smr/bin/startserver ucamserver ' inistr core.send("bash " startstr) </rule> </init> # keep monitoring rule active wait() : false </rule>
It is a XML formatted rule script, as defined for the aurule.so.0 plugin.
[edit] Camera server on Raspberry camera
In the live directory is the camera configuration file, it looks something like this:
local@rpi7:~/mobotware/build/config/gogo/picam $ cat ucamserver.ini #!/bin/bash # camera server scriptfile server imagepath="." server datapath="." server replayPath="foo" # server port=24920 # module load=var module load=odopose module load=aurule.so.0 module load=aupoly.so.0 # camera parameters camset device=6 focallength=532 posx=0.45 posy=0.03 posz=0.65 rotphi=0 rotkappa=-1.57 # east -90 deg camset device=7 focallength=532 posx=0.45 posy=0.00 posz=0.65 rotphi=0 rotkappa=0 camset device=8 focallength=532 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=-0.785 camset device=9 focallength=532 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=0.785 camset device=10 focallength=532 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=1.57 # raspberry pi camera module load=aupicam.so.0 # use the one fit for this pi-cam # will then use the corresponding image-pool number # then much easier when collecting images var picam.camDeviceNum=6 ; var picam.camDeviceNum=7 ; var picam.camDeviceNum=8 ; var picam.camDeviceNum=9 ; var picam.camDeviceNum=10 var picam.framerate=2 var picam.resolution="768 1024" var picam.white=7 var picam.exposuremode=1 var picam.meter=0 var picam.pyramidlevels=3 picam open # end of script
The camset commands configure the raspberry camera with different numbers, this is to ease the transfer of images to the combining camera server.
Near the end is the camera number for this raspberry camera defined - the others are commented out.
NB! it seems like a frame rate of 1 (var picam.framerate=1) will not work, so keep it at 2 or higher.
[edit] common camera server
A camera server to combine all the images may be needed - at least for logging of images and odometry.
The camera server configuration file could look like this:
local@rpi7:~/mobotware/build/config/gogo $ cat ucamserver.ini #!/bin/bash server imagepath="." server datapath="." server replayPath="log_cam" server port=24920 # module load=var # module load=odoPose odopose log module load=mappose mappose log module load=utmpose utmpose log ;mapPose replay module load=ucamif.so.0 camdata add=img camdata add=gmk camdata add=path camdata add=cam ; # autostart cameraserver on raspberry pi cameras module load=if alias=cam6keep module load=if alias=cam7keep module load=if alias=cam8keep module load=if alias=cam9keep module load=if alias=cam10keep cam6keep connect=rpi6.local:24926 cam7keep connect=rpi7.local:24926 cam8keep connect=rpi8.local:24926 cam9keep connect=rpi9.local:24926 cam10keep connect=rpi10.local:24926 ; ; # connect to get images module load=if alias=cam6 module load=if alias=cam7 module load=if alias=cam8 module load=if alias=cam9 module load=if alias=cam10 ; # camset device=6 focallength=455 posx=0.45 posy=0.03 posz=0.65 rotphi=0 rotkappa=0.8 camset device=7 focallength=455 posx=0.45 posy=0.00 posz=0.65 rotphi=0 rotkappa=0 camset device=8 focallength=455 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=-0.8 camset device=9 focallength=455 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=-1.57 camset device=10 focallength=455 posX=0.45 posY=-0.03 posZ=0.65 rotPhi=0 rotkappa=1.57 ; ; # load images scaled 2 levels down cam 6 is img=6+2 = 8 # to get small overview images cam6onconnect cmd="cam6 poolpush img=8 cmd='poolget all toimg=26 fmt=rgb'" cam7onconnect cmd="cam7 poolpush img=9 cmd='poolget all toimg=27 fmt=rgb'" cam8onconnect cmd="cam8 poolpush img=10 cmd='poolget all toimg=28 fmt=rgb'" cam9onconnect cmd="cam9 poolpush img=11 cmd='poolget all toimg=29 fmt=rgb'" cam10onconnect cmd="cam10 poolpush img=12 cmd='poolget all toimg=30 fmt=rgb'" ; ; cam6 connect=rpi6.local:24920 cam7 connect=rpi7.local:24920 cam8 connect=rpi8.local:24920 cam9 connect=rpi9.local:24920 cam10 connect=rpi10.local:24920 ; poolset img=26 log poolset img=27 log poolset img=28 log poolset img=29 log poolset img=30 log ;
This configuration file connects to 5 camera boards.
This gets an image from each of the raspberry pi cameras and load them to image numbers 26 to 30 in RGB format.