AravisProject / aravis

A vision library for genicam based cameras
GNU Lesser General Public License v2.1
861 stars 321 forks source link

Problems Using Pleora iPORT CL-GigE #179

Open zackwyatt opened 6 years ago

zackwyatt commented 6 years ago

Hi --

I'm having trouble using Aravis (0.5.12) with a Pleora iPORT CL-GigE Cameralink->GigE Vision framegrabber->gige-converter. (https://www.pleora.com/products/frame-grabbers/iport-cl-gige/)

I hooked up the CL-GigE and am able to see the stream of images in Pleora's eBUS Player over GigE.

The Pleora CL-GigE adapter shows up fine to arv-tool. I can read genicam properties of the Pleora device from aravis.

But: 1) Using arv-tool control to set a non-register value just sets the desired value to 0/null. Using arv-tool to set a register value does set the value. 2) After executing AcquisitionStart, I can't read any buffers from the stream.

I've attached the genicam output genicam_pleora.txt and stream/acquisition logs acquisition_attempt.txt for the buffer errors.

Here's a sequence of arv-tool commands where I try to change the Width from 640 to 600:

$ arv-tool-0.6 control Width
Width = 640 (min:4;max:16376) 

$ arv-tool-0.6 control Width=600
Width = 600 (min:4;max:16376) // says it's updated

$ arv-tool-0.6 control Width
Width = 0 (min:4;max:16376) // but it's not actually updated

$ arv-tool-0.6 control R[0x12500]=0x258
R[0x00012500] = 0x00000258 // set the register

$ arv-tool-0.6 control Width
Width = 600 (min:4;max:16376) // after writing x258 to the register value behind Width, Width changes

With debug on and running arv_device_set_integer_feature_value(arv_camera_get_device(mArvCamera), "Width", 640):

[GcRegisterNode::_set_integer_value] address = 0x12500, value = 0x280
packet_type  = cmd
command      = write-memory-cmd
size         = 8
id           = 65389
00000000 42 01 00 86 00 08 ff 6d 00 01 25 00 00 00 02 80  B......m..%.....

packet_type  = ack
command      = write-memory-ack
size         = 4
id           = 65389
00000000 00 00 00 87 00 04 ff 6d b8 01 00 04              .......m....

And debug logs from arv_device_write_register(arv_camera_get_device(mArvCamera), 0x12500, 640, NULL):

packet_type  = cmd
command      = write-register-cmd
size         = 8
id           = 65390
address      =      75008 (0x00012500)
value        =        640 (0x00000280)
00000000 42 01 00 82 00 08 ff 6e 00 01 25 00 00 00 02 80  B......n..%.....

packet_type  = ack
command      = write-register-ack
size         = 4
id           = 65390
data index   =          1 (0x00000001)
00000000 00 00 00 83 00 04 ff 6e 00 00 00 01              .......n....

You can also see similar setting-to-null behavior with PixelFormat:

$ arv-tool-0.6 control PixelFormat
Pleora Technologies Inc.- (192.168.12.4)
PixelFormat = Mono12

$ arv-tool-0.6 control PixelFormat=Mono10
Pleora Technologies Inc.- (192.168.12.4)
PixelFormat = Mono10

$ arv-tool-0.6 control PixelFormat
Pleora Technologies Inc.- (192.168.12.4)
PixelFormat = (null)

Regarding #2 (the buffer errors): Seems likely it'd be some issue related to the above difficulty setting values. I see a bunch of activity after the AcquisitionStart ... like setting the GevSCPInterfaceIndex and GevSCDA ... which seem fine? I've attached the debug logs afters AcquisitionStart. Only error I see is:

[GvStream::set_socket_filter] source ip = 0xc0a80c04 - port = 20202 - dest ip = 0xc0a80c07 - port 46755
[GvStream::find_frame_data] Start frame 38221
[GvStream::process_packet] Error packet at dt = 0, packet id = 6269 frame id = 38221
packet_type  = (null) (f5bc)
content_type = (null) (0080)
0000 f5 bc 95 4d 80 10 18 7d b7 d6 00 00 01 01 08 0a  ...M...}........
0010 37 da 8b 22 88 23 30 9a                          7..".#0.        
[GvStream::process_packet] Error packet at dt = 0, packet id = 6525 frame id = 38221
packet_type  = (null) (f5bc)
content_type = (null) (0080)
0000 f5 bc 95 4d 80 10 19 7d b6 d6 00 00 01 01 08 0a  ...M...

I saw an older issue (https://github.com/AravisProject/aravis/issues/91) about Pleora framegrabber/adapter lacking an AcquisitionFrameRate and breaking ArvViewer. I just intended to set AcquisitionMode to Continuous, call AcquisitionStart, and then grab buffers from the ArvStream with arv_stream_pop_buffer in a loop.


lastly, just in case it's any interest, the debug logs for aravis spit out a lot of "can't append" errors at start-up:

[GvDevice::load_genicam] Zipped xml data
[Zip::new] number of files = 1
[Zip::new] directory position = 0x00009f0a
[Zip::new] directory size = 82
[Zip::new] directory offset = 0x00009eb8
[Zip::new] header size = 0
[Zip::list_files] iport_cl_gige_pt01_cl0ip01_128xg.xml
[GcFeature::set_attribute] Unknown attribute 'ToolTip'
[GcFeature::set_attribute] Unknown attribute 'StandardNameSpace'
[GcFeature::set_attribute] Unknown attribute 'ProductGuid'
[GcFeature::set_attribute] Unknown attribute 'VersionGuid'
[GcFeature::set_attribute] Unknown attribute 'xmlns'
[GcFeature::set_attribute] Unknown attribute 'xmlns:xsi'
[GcFeature::set_attribute] Unknown attribute 'xsi:schemaLocation'
[ArvDomCharacterData::set_data] Value = '
    '
[ArvDomNode::append_child] Can't append '#text' to 'RegisterDescription'
[ArvDomCharacterData::set_data] Value = '
        '
[ArvDomNode::append_child] Can't append '#text' to 'Group'
[Gc::register_feature_node] Register node 'Root' [Category]
[ArvDomCharacterData::set_data] Value = '
            '
[ArvDomNode::append_child] Can't append '#text' to 'Category'
[ArvDomCharacterData::set_data] Value = 'DeviceControl'
[ArvDomCharacterData::set_data] Value = '
            '
[ArvDomNode::append_child] Can't append '#text' to 'Category'
[ArvDomCharacterData::set_data] Value = 'Deprecated'
[ArvDomCharacterData::set_data] Value = '
            '
[ArvDomNode::append_child] Can't append '#text' to 'Category'
[ArvDomCharacterData::set_data] Value = 'ImageFormatControl'
[ArvDomCharacterData::set_data] Value = '
            '
[ArvDomNode::append_child] Can't append '#text' to 'Category'
[ArvDomCharacterData::set_data] Value = 'AcquisitionControl'
EmmanuelP commented 6 years ago

So it looks like it works when a GigEVision register write command is used instead of memory write. Could you try to force the legacy behaviour by modifying _register_workaround_check and make it always return TRUE.

zackwyatt commented 6 years ago

Awesome, that worked. Thank you! Can now set values and reading from ArvStream works fine. (as suggested, specific change was to return TRUE at start of https://github.com/AravisProject/aravis/blob/fc1713fb6b22ae53ee5d6eb66bcc61f290d972c7/src/arvgcport.c#L95-L105)

The Pleora genicam config says it's at 1.1. I gather that the non-register approach should work with this version? Is there something I should flag to Pleora or PR to Aravis?

thanks again for quick help and suggestion.

EmmanuelP commented 6 years ago

Hi Zachary.

Could you check if WriteMem commands are supported please ?

This command should give you the answer:

arv-tool-0.6 control GevSupportedOptionSelector=WriteMem GevSupportedOption
zackwyatt commented 6 years ago

Looks like it is:

$ arv-tool-0.6 control GevSupportedOptionSelector=WriteMem GevSupportedOption
Pleora Technologies Inc.- (192.168.12.4)
GevSupportedOptionSelector = WriteMem
GevSupportedOption = true
roimr commented 6 years ago

Hi, I had the same issue with a Pleora Camera, after doing the changes in (https://github.com/AravisProject/aravis/blob/fc1713fb6b22ae53ee5d6eb66bcc61f290d972c7/src/arvgcport.c#L95-L105) as suggested, I am able to receive images.

However, I am having some issues setting some features value. Specifically, I am trying to modify the Windowing feature (Enum: w128x128, w64x64, w32x32, w1x128), which changes the size of the image. By default Windowing=w128x128 with an image size of 128x128.

I run the following command to set Windowing=w64x64 and retrieve the Width feature to check that it is correct:

$ arv-tool control Width Windowing Windowing=w64x64 Windowing Width New Infrared Technologies Ltd.-Tachyon 16k Camera-117D3FF (192.168.0.167) Width = 128 (min:8;max:128) Windowing = w128x128 Windowing = w64x64 Windowing = w64x64 Width = 128 (min:8;max:64)

As you see Windowing is set correctly, but the Width value should be automatically set to 64 and it is not. See attached the complete log file when debugging output.log. This feature works properly with the Pleora SDK.

If I run again the same command I get the following behavior:

./arv-tool control Width Windowing Windowing=w64x64 Windowing Width New Infrared Technologies Ltd.-Tachyon 16k Camera-117D3FF (192.168.0.167) Width = 64 (min:8;max:128) Windowing = w128x128 Windowing = w64x64 Windowing = w64x64 Width = 64 (min:8;max:64)

EmmanuelP commented 6 years ago

@zackwyatt Please report this issue to pleora. They should not advertise 1.1.0 schema version if they do not support 4 bytes writemem commands.

@roimr Please open another issue for your problem.

zackwyatt commented 5 years ago

Hi Emmanuel --

I've found that if I send the WRITEMEM length-4 buffer data to Pleora adaptor as little-endian, WRITEMEM works fine in my simple cases (setting Width=640). If I send as big-endian, the WRITEMEMs fail.

Here's the normal Aravis behavior (including wireshark capture of command) that sends WRITEMEM of Width=640 with big-endian value of 00 00 02 80. This will result in subsequent calls to Width reporting 0.

aravis_default_bigendian_screen shot 2018-09-06 at 11 32 40 am

And here's the modified Aravis behavior that sends WRITEMEM of Width=640 with little-endian value of 80 02 00 00. Subsequent calls to read the width correctly report 640.

aravis_hacked_littleendian_screen shot 2018-09-06 at 11 35 39 am

The only change I made was to make a little-endian version of buffer and send that to WRITEMEM before calling arv_device_write_memory. I didn't change anything else. https://github.com/AravisProject/aravis/blob/994abcd8910550ec816b321c4cb53039e52b6591/src/arvgcport.c#L181

I've exchanged several emails with Pleora and they say they're meeting the genicam specification with this behavior. Here are the explanations:

To explain the behaviors you see and how our device works: Our device is litte-Endian by design. According to GenICam/GigE Vision standard, Writing/Reading using WriteReg/ReadReg to little-endian device requires flip each 4-byte word. Writing/Reading using WriteMem/ReadMem should pass "as is". The reason is we cannot really do any Endianness converting for the WriteMem since you normally don't know which type of data send out, 16bit interger and 32bit interger are not exactly the same, and string shouldn't be flipped. That's to say, if you use GenICam interface to write/read cmd to the device, the application should already handle the endianness for you according to the standard. However, if you use the raw WriteReg/WriteMem, you need to know the Endianness of your PC and your device. One our device side, we flip the 32bit interger from WriteReg, but do nothing on WriteMem. (We recommend to use WriteReg for 32bit interger and WriteMem for string and anything else) If your PC is little-Endian, writeReg on application side flip the bytes to follow network byte order (Big Endian), our device flip it back, perfect, everything works. If your PC is little-Endian, somehow the Aravis WriteMem flip the bytes for you, now our device receive Big-Endian data and do nothing, you got the wrong byte order.

Without knowing underneath how the Aravis handles WriteReg/WriteMem and which Endianness your PC uses, no one could say the fault is absolutely on Pleora. The only thing I can tell you is, our device and SDK are standard compliant and they are proven to work with all major software. To Sum up, For WriteReg, you need to send Big-Endian data out on the wire while for WriteMem, it should be little Endian.

... I asked for clarification since they previously said I should be sending as Big-endian. And how can I know that I should send little-endian to the device since the pleora adaptor doesn't seem to report anything as little-endian...

The standard did mention "GVCP MUST use network byte order, also known as big-endian", but there are more to it, according to the standard, the data payload of WRITEREG is limited to 32bit interger " The control protocol assumes the registers are 32-bit wide", while READ/WRITEMEM is recommended for "read/write consecutive 8-bit locations from/to the device". I quote directly from the standard, that READMEM is "The application can issue a READMEM message to read consecutive 8-bit locations from the device. This could be useful to read strings, such as the XML description file location, or to read an on-board XML description file.".

If you take everything into account, the standard recommended READ/WRITEREG with 32bit integer, while READ/WRITEMEM with string, this is the reason why WRITEREG needs to flip the bytes to fulfill network byte order, because when you are dealing with 32bit integer, you will run into the endianness issue. However, for string, this is not an issue at all, it can only be big-endian regardless of the machine you are using.

We are little-Endian device by default, however, according to the standard, we need to advertise as big-endian. The device side handle the endianness for you as well as the application side.

I don't know the aravis software, If your machine is little-endian, and you prepare 32bit interger as 0x00000280, and WRITEMEM send it out on the wire as 00 00 02 80, then the WRITEMEM must flip the byte order for you.

I understand the confusion here, we normally don't expect the end customer to use the raw WRITEREG/WRITEMEM, the reason for GenICam interface is to allow the GenICam handle it for you. However, if that's a must, then that's the reason Pleora support comes into play, we are here to help you understand how our device works so you can implement them in your application the way you wantt.

Thoughts?

Sending a 4-byte integer of the correct endianness using WRITEMEM seems impossible since the devices don't specify if they are little/big endian. Maybe I've misread the emails/standard? I wonder if best behavior is to just use WRITEREG in this (4-byte integer) case, even with 1.1.0+ genicam cameras? The pleora SDK only sends WRITEREG for Width=640 -- although they say they send strings with WRITEMEM. You've certainly seen more cameras than me so curious of your thoughts.

also: as I was looking around the arv_gc_port_write code, I was wondering if line 177 of the write register section --value = GUINT32_FROM_BE (value); -- should be GUINT32_TO_BE? Seems like it ends up being same GUINT32_SWAP_LE_BE function ... but for code clarity, it's intentionally going from host order to BE for the register write, yeah?

thanks again!

EmmanuelP commented 3 years ago

Blast from the past...

In the Genicam documentation:

3.1.1 Behavior of products based on schema version 1.1 and newer

Cameras providing XML file based on schema version 1.1 or newer must implement
endianess as follows:
* The <Endianess> tags of all registers have to correspond with the real endianess of the
camera, corresponding with the endianess reported in the DeviceMode bootstrap
register.
* The port's <SwapEndianess> tag must not be used.

The device is little endian, and all the registers are defined as BigEndian. That can not work with the 1.1 genicam schema version. They should claim 1.0.

EmmanuelP commented 3 years ago

also: as I was looking around the arv_gc_port_write code, I was wondering if line 177 of the write register section --value = GUINT32_FROM_BE (value); -- should be GUINT32_TO_BE? Seems like it ends up being same GUINT32_SWAP_LE_BE function ... but for code clarity, it's intentionally going from host order to BE for the register write, yeah?

That is because I don't want to have integers in the API in other order than the host one. So the read/write_register functions take an 32 bit integer in the host endianness, that is converted to/from network (big) endianness when building/reading the control packet sent/received to/from internet. In arv_gc_port_write, there is a conversion from big endian to host endian because the data are passed to this function as memory buffer, and in legacy mode, the register are supposed to always be in big endian. That leads in this case to a double conversion (triple if you count the one happening in the genicam code), but the guint32 passed in the API is in host endianness.

julius-ziegler commented 1 year ago

I am working with a "Sony XCG-CG240" and it has the same issue. The above "fix" was required. The camera advertises to be both Genicam 1.2 and 2.0 compliant (it can be switched between both protocol versions), but it has the problem in both modes.

pageldev commented 1 year ago

Adding the entry { .vendor_selection = "Sony", .model_selection = "XCG_CGSeries"}, to ArvGvLegacyInfos struct in arvgcport.c should fix that. Can we do that?

EmmanuelP commented 1 year ago

The camera advertises to be both Genicam 1.2 and 2.0 compliant (it can be switched between both protocol versions), but it has the problem in both modes.

I guess you are confusing the genicam and gigeVision versions. Genicam schema versions are 1.0 and 1.1.

EmmanuelP commented 1 year ago

Adding the entry { .vendor_selection = "Sony", .model_selection = "XCG_CGSeries"}, to ArvGvLegacyInfos struct in arvgcport.c should fix that. Can we do that?

I have added this entry in commit bb1e25e9ebbbe532075e5487daac66fffca2f45a

Stigaard commented 1 year ago

Hi I am seeing a similar issue with an Teledyne Dalsa GXM640 thermal camera. I have tried adding it to the ArvGvLegacyInfos which does resolve the problem when using { .vendor_selection = "TeledyneDALSA", .model_selection = "ICE"} , I am however getting a bit confused about the model name. arv_camera_get_model_name returns "Calibir GXM640" (taken using arv-camera-test) however arv_gc_register_description_node_get_model_name returns "ICE" (discovered by adding printf to _use_legacy_endianness_mechanism ). What would be the difference between the two calls and should I be worried about using ICE as the model name?

EmmanuelP commented 1 year ago

Hi @Stigaard

I have added some documentation about the legacy endianness mechanism exception list:

https://github.com/AravisProject/aravis/pull/794/files

Stigaard commented 1 year ago

Hi @EmmanuelP , Thank you for the elaboration, I discovered that it is sort of a repost of https://github.com/AravisProject/aravis/issues/490 The Genicam also lists it as ModelName="ICE" VendorName="TeledyneDALSA" Even though that arv_camera_get_model_name is the one providing the "correct" model name for this camera, I am however interpreting it more as Teledyne Dalsa not having customized their xml to this camera than as a bug of aravis. I have patched my "own" Aravis instance with this information, but I cannot judge if it should be "allowed" in mainstream when it does not have the correct model name, I will let you be the judge of that.