-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 51bf870
Showing
25 changed files
with
1,988 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Compiled python modules. | ||
*.pyc | ||
|
||
# Setuptools distribution folder. | ||
/dist/ | ||
|
||
# Python egg metadata, regenerated from source files by setuptools. | ||
/*.egg-info | ||
/*.egg | ||
|
||
# PyCharm artifacts. | ||
.idea/ | ||
|
||
# Build files. | ||
/build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Copyright (c) 2021 Michael Gann | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
include README.md | ||
include LICENSE.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
o3d3xx-python | ||
============= | ||
|
||
A Python 2/3 library for ifm efector O2x5xx 2D sensors | ||
|
||
Features | ||
-------- | ||
* easy XMLRPC interface with integrated session handling | ||
* PCIC V3 client for result data transfer | ||
|
||
Prerequisites | ||
------------- | ||
Usage with Python 2 requires the 'future' package | ||
|
||
Installation | ||
------------ | ||
Install the package with | ||
|
||
$ python setup.py install | ||
|
||
Examples | ||
-------- | ||
For a quick start, go to the `examples` folder and run | ||
|
||
$ python create_application.py 192.168.0.69 | ||
|
||
with your device's IP address to create an example application and | ||
|
||
$ python image_viewer.py 192.168.0.69 | ||
|
||
to view the image data coming from the camera (requires matplotlib) | ||
|
||
Usage | ||
----- | ||
### RPC client | ||
The library provides all XMLRPC objects as mentioned in the camera's XMLRPC | ||
manual. The entry point is the RPC main object which can be created with e.g. | ||
|
||
camera = o3d3xx.Device("192.168.0.69") | ||
|
||
RPC calls can be performed e.g. like this | ||
|
||
version_info = camera.getSWVersion() | ||
|
||
These are the different RPC objects and the possibilities how they can be | ||
acquired: | ||
|
||
* Session object | ||
- `session = camera.requestSession()` | ||
This is different from the regular RPC call which only returns the | ||
session ID. The session ID can be retrieved from `camera.sessionID` | ||
- `session = camera.session` (only valid after a `requestSession()` call) | ||
* EditMode object | ||
- `edit = session.startEdit()` which is equivalent to | ||
- `edit = session.setOperatingMode(1)` (again, this is different from the | ||
pure RPC call) | ||
- `edit = session.edit` (only valid after a `startEdit()` call) | ||
* DeviceConfig object | ||
- `device = edit.device` | ||
* NetworkConfig object | ||
- `network = edit.network` | ||
* ApplicationConfig object | ||
- `application = edit.editApplication(1)` (different from the pure RPC) | ||
- `application = edit.application` (only valid after a `editApplication()` | ||
call) | ||
* ImagerConfig object | ||
- `imagerConfig = application.imagerConfig` | ||
* Spatial filter configuration object | ||
- `spatialFilter = application.spatialFilter` | ||
* Temporal filter configuration object | ||
- `temporalFilter = application.temporalFilter` | ||
|
||
### PCIC client | ||
The library currently provides three basic clients: | ||
|
||
* A simple PCIC V3 client | ||
- Create it with `pcic = o3d3xx.PCICV3Client("192.168.0.69", 50010)` | ||
providing the device's address and PCIC port. | ||
- Send PCIC commands with e.g. `answer = pcic.sendCommand("G?")`. All | ||
asnychronous PCIC messages are discarded while waiting for the answer | ||
to the command. | ||
- Read back the next PCIC for a particular ticket number. This can be used | ||
to read asynchronously sent results (ticket number "0000"): | ||
`answer = pcic.readAnswer("0000")` | ||
- Read back any answer coming from the device: | ||
`ticket, answer = pcic.readNextAnswer()` | ||
* A PCIC client supporting arbitrary formatting | ||
- Define an instance of `o3d3xx.PCICFormat` to describe which data you | ||
want to retrieve | ||
- Most common use case: retrieval of binary data. For example, if you want | ||
to receive amplitude and radial distance images, use the format | ||
`o3d3xx.PCICFormat.blobs("amplitude_image", "distance_image")`. | ||
- Create the client with | ||
`pcic = o3d3xx.FormatClient("192.168.0.69", format)` with `format` being | ||
the `PCICFormat` instance described above. | ||
- When `result = pcic.readNextFrame()` returns for the given example, | ||
`result` is a dictionary containing image arrays for the keys | ||
`amplitude_image` and `distance_image`. | ||
* A PCIC client for asynchronous image retrieval | ||
- Deprecated, please use the `o3d3xx.FormatClient` instead, it uses much | ||
less network bandwidth if you are not interested in all available image | ||
types. | ||
- Create it with `pcic = o3d3xx.ImageClient("192.168.0.69", 50010)`. | ||
- It configures a PCIC connection to receive all image types. | ||
- Read back the next result (a dictionary containing all the images) | ||
with `result = pcic.readNextFrame()` | ||
|
||
### PCIC interface (ifmVisionAssistant) | ||
Following structure in the process interface is required for multiple and | ||
nested records: | ||
|
||
* supported interface structure | ||
- records require a special delimiter at the end like seen in below | ||
example. default delimiters `|` and `*` can be parsed without any | ||
changes in library. | ||
- multiple or nested records between two blob images | ||
- multiple models and ROIs in application which yield cascaded model | ||
records in result. | ||
- blob image(s) at the start or between the result | ||
|
||
|
||
star ; X Image ; models Normalized amplitude image ; stop | ||
| | | ||
ID ; ROIs; Value of SP1 ; Value of SP2 | <-- default delimiter for models | ||
| | | ||
ID ; Process value ; Status * <-- default delimiter for ROIs | ||
|
||
* restrictions | ||
- single blob image at the end of multiple or nested records | ||
- positional swap of delimiters `|` and `*` in process interface | ||
|
||
Contributing | ||
------------ | ||
o2x5xx-python is also available at | ||
[Github](https://github.com/ifm/o3d3xx-python) | ||
|
||
Smoke-Tests | ||
------------ | ||
|
||
1.22.9009 | ||
|
||
O2D5xx | O2I5xx | tested function | comment | ||
-------- | -------- | -------- | -------- | ||
x | x | activate_application | - | ||
x | x | application_list | - | ||
x | x | upload_pcic_output_configuration | - | ||
x | x | retrieve_current_process_interface_configuration | - | ||
x | x | request_current_error_state | - | ||
x | x | request_current_error_state_decoded | - | ||
x | x | gated_software_trigger_on_or_off | - | ||
x | x | request_device_information | - | ||
x | x | return_a_list_of_available_commands | - | ||
o | o | request_last_image_taken | uncompressed images possible? answer is always ! | ||
x | x | request_last_image_taken_decoded | TODO: Decode the split in case of multiple images | ||
x | x | overwrite_data_of_a_string | - | ||
x | x | read_string_from_defined_container | - | ||
x | x | return_the_current_session_id | - | ||
x | x | set_logic_state_of_a_id | - | ||
o | o | request_state_of_a_id | Reading io states without linked element is not working (O3D3xx is working) | ||
x | x | turn_process_interface_output_on_or_off | - | ||
x | x | request_current_decoding_statistics | - | ||
x | x | execute_asynchronous_trigger | - | ||
x | x | execute_synchronous_trigger | - | ||
x | x | set_current_protocol_version | - | ||
x | x | request_current_protocol_version | - | ||
x | x | turn_state_of_view_indicator_on_or_off | - | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import o2x5xx | ||
import sys | ||
import time | ||
|
||
if len(sys.argv) > 1: | ||
address = sys.argv[1] | ||
else: | ||
address = '192.168.0.69' | ||
|
||
# create device | ||
device = o2x5xx.Device(address) | ||
|
||
# open a session and create an application for editing | ||
session = device.requestSession() | ||
session.startEdit() | ||
applicationIndex = session.edit.createApplication() | ||
application = session.edit.editApplication(applicationIndex) | ||
session.edit.stopEditingApplication() | ||
|
||
# configure the application to | ||
# - double exposure | ||
application.imagerConfig.changeType("under5m_moderate") | ||
# - free-run at 10 Hz | ||
application.setParameter("TriggerMode", "1") | ||
application.imagerConfig.setParameter("FrameRate", "10") | ||
# and perform an auto-exposure run to determine | ||
# exposure times | ||
application.imagerConfig.startCalculateExposureTime() | ||
# wait until the auto-exposure process has finished | ||
while application.imagerConfig.getProgressCalculateExposureTime() < 1.0: | ||
time.sleep(1) | ||
# name and save the application and stop editing | ||
application.setParameter("Name", "o2x5xx-python example application") | ||
application.save() | ||
session.edit.stopEditingApplication() | ||
|
||
# set the new application as active and save the change | ||
session.edit.device.setParameter("ActiveApplication", str(applicationIndex)) | ||
session.edit.device.save() | ||
|
||
# finish the session | ||
session.cancelSession() |
Oops, something went wrong.