ModalAI Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login
    1. Home
    2. Alex Kushleyev
    3. Posts
    • Profile
    • Following 0
    • Followers 11
    • Topics 0
    • Posts 1882
    • Best 101
    • Controversial 1
    • Groups 1

    Posts made by Alex Kushleyev

    • RE: Minimizing voxl-camera-server CPU usage in SDK1.6

      @Rowan-Dempster , yeah that is going to be a problem.. I don't think we have a 32 bit version of libgbm.so for VOXL2. This library is used for allocating the ION buffers.

      The next thing to try would be to remove the buffer allocation part from the 32-bit build. Actually receiving and reading the buffer does not involve libgbm. the client just gets a FD, which needs to be mmap'ed and used. (this would remove ability to allocate new ION buffers, which you actually don't need on the client side).

      I just commented out the following from the library CMakeLists:

      #list(APPEND LIBS_TO_LINK gbm)
      #list(APPEND all_src_files src/buffers/gbm.cpp)
      

      and here are the errors:

      /usr/bin/aarch64-linux-gnu-ld: CMakeFiles/modal_pipe.dir/src/buffers.cpp.o: in function `mpa_ion_buf_pool_alloc_bufs':
      buffers.cpp:(.text+0x10c): undefined reference to `allocate_one_buffer(mpa_ion_buf_t*, int, int, unsigned int, unsigned int)'
      /usr/bin/aarch64-linux-gnu-ld: buffers.cpp:(.text+0x184): undefined reference to `init_buffer_allocator()'
      /usr/bin/aarch64-linux-gnu-ld: CMakeFiles/modal_pipe.dir/src/buffers.cpp.o: in function `mpa_ion_buf_pool_delete_bufs':
      buffers.cpp:(.text+0x24c): undefined reference to `delete_one_buffer(mpa_ion_buf_t*)'
      /usr/bin/aarch64-linux-gnu-ld: buffers.cpp:(.text+0x2a0): undefined reference to `shutdown_buffer_allocator()'
      

      You could try replacing those functions with a fatal print statement "not implemented". Maybe that would work?

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: Robust way of setting static IP

      @jonathankampia ,

      Here is something i tried, you can try as well. You are right, there is a background service that may be taking over, I think i found how to disable it:

      systemctl disable QCMAP_ConnectionManagerd
      systemctl disable qti_pppd
      systemctl disable qtid
      
      rm /lib/systemd/system/multi-user.target.wants/QCMAP_ConnectionManagerd.service
      rm /lib/systemd/system/multi-user.target.wants/qti_pppd.service
      rm /lib/systemd/system/multi-user.target.wants/qtid.service
      
      #edit: instead of disabling the above 3 services and removing the entries from `multi-user.target.wants`, it seems you can do the following:
      systemctl mask QCMAP_ConnectionManagerd
      systemctl mask qti_pppd
      systemctl mask qtid
      
      # you may want to disable dhcpcd as well, but i dont think that is strictly necessary:
      systemctl disable dhcpcd
      

      Now, set up static connection:

      #create a new network interface file
      vi /etc/systemd/network/10-eth0.network
      
      [Match]
      Name=eth0
      
      [Network]
      Address=192.168.xx.xx/24
      Gateway=192.168.xx.1
      DNS=8.8.8.8 1.1.1.1
      

      enable networkd

      systemctl enable systemd-networkd
      

      Then reboot voxl2...

      I think if dhcpcd is enabled, it may first take over the interface, but then networkd takes it back.. For example, here is the log from networkd when dhcpcd is enabled:

      ...
      Dec 10 06:01:00 m0054 systemd-networkd[1126]: dummy0: Gained carrier
      Dec 10 06:01:00 m0054 systemd-networkd[1126]: dummy0: Gained IPv6LL
      Dec 10 06:01:11 m0054 systemd-networkd[1126]: eth0: Gained carrier
      Dec 10 06:02:13 m0054 systemd-networkd[1126]: eth0: Gained IPv6LL
      Dec 10 06:02:13 m0054 systemd-networkd[1126]: eth0: Configured
      Dec 10 06:02:13 m0054 systemd-networkd[1126]: docker0: Link UP
      Dec 10 06:02:21 m0054 systemd-networkd[1126]: eth0: Lost carrier
      Dec 10 06:02:36 m0054 systemd-networkd[1126]: eth0: Gained carrier
      Dec 10 06:02:38 m0054 systemd-networkd[1126]: eth0: Gained IPv6LL
      Dec 10 06:02:38 m0054 systemd-networkd[1126]: eth0: Configured
      

      and the log with dhcpcd disabled:

      ...
      Dec 10 06:02:13 m0054 systemd-networkd[1126]: bond0: Link is not managed by us
      Dec 10 06:02:13 m0054 systemd-networkd[1126]: sit0: Link is not managed by us
      Dec 10 06:02:14 m0054 systemd-networkd[1126]: eth0: Link UP
      Dec 10 06:02:38 m0054 systemd-networkd[1126]: eth0: Gained carrier
      Dec 10 06:09:56 m0054 systemd-networkd[1126]: eth0: Gained IPv6LL
      Dec 10 06:09:56 m0054 systemd-networkd[1126]: eth0: Configured
      Dec 10 06:09:56 m0054 systemd-networkd[1126]: docker0: Link UP
      

      Can you try and see if that solves your issue?

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev
    • RE: Minimizing voxl-camera-server CPU usage in SDK1.6

      @Rowan-Dempster, the errors above seem like print formatting issues, but i understand that there could be some others. If you want to try to resolve those and see if there are any more significant errors, I can help.

      We do not plan to update QVIO to use ion pipes, mainly because QVIO only supports a single camera input, so the savings from going to ION buffers for a single camera is going to be very small. The majority of savings came from the buffer caching policy, which I pointed out in the previous email. Another reason is that we are now focusing on Open Vins, which does support multiple cameras.

      We do plan to fix the buffer caching policy so to remove this extra cpu usage for the appropriate MISP outputs. The work is ongoing in the branch i mentioned above.

      Are you running multiple instances of QVIO, one for each camera?

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: External pwm ESC questions

      @mkriesel , a few tips..

      • I suspect FETtec ESC is using a pretty accurate xtal or accurate RC oscillator, so you should not need to calibrate the ESC
      • You can check the current calibration by using QGC to control the individual motors to see at which command they start up and make sure that is very close to the same (typically around 1000us or a bit more)
      • Additionally, you can spin up each motor with propeller at certain % power, lets say 20% or 30% and using an optical tachometer (RPM meter) to measure the speed of each motor
      • Those are some sanity checks you can do without being able to calibrate and without having any ESC telemetry.

      Regarding the ESC PWM range, the procedure is documented for VOXL2 IO board : https://docs.modalai.com/voxl2-io-user-guide/#how-to-perform-esc-calibration -- please go over that and make sure you did it correctly.
      Alex

      posted in ESCs
      Alex KushleyevA
      Alex Kushleyev
    • RE: Flir Boson+ Application v4.2 install file not available anymore - does anyone have it please?

      @saegsali , yes you are correct. Unfortunately, the USB port J3 is not populated on M0201 - I believe the decision was made to omit this connector due to some mechanical constraints, I am not sure.

      A couple of things to consider:

      • if you purchase this connector (BM06B-SRSS-TBT), you can solder it on and plug a USB connection in to it. I have not tried it, but I will. I don't see why it would not work, it should be powered from the USB port.
      • if you have any other adapter (from FLIR, etc) which provides a USB port, the function should be the same and you could just plug that into the Boson and use it for the sensor configuration.
      • we are developing a tool for communicating with Boson directly from VOXL2, but it is not yet to the point of performing full configuration. So you should try to use the GUI for the initial setup. Perhaps with the correct connection the GUI version 4.6 should work, otherwise there may be an issue with the GUI itself.

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev
    • RE: Python Programmatic GStreamer Access for Hardware Encoded Acceleration and Low Latency

      Hi @joseph-vale , i tested the python script from FLIR help site (Radiometry.py). I just had to modify it to use the correct USB and Video devices. The script ran find, but since my Boson does not support radiometric output, the reported temperature was like 70 degrees colder than it should be (reporting -50C at room temperature). Are you able to get correct temperatures with your device using this script?

      As i mentioned before, there is a way of getting the image data from voxl-camera-server into python. I think it would be interesting to try running the same exact conversion and annotation code from the FLIR example. This would allow you to first check the temperatures using a USB connection and then check them using the VOXL2 pipeline.

      I am going to set up an example that that uses pympa (python wrapper for MPA) to get the 16bit data from Boson and plot + convert it to temperature using the reference code.

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev
    • RE: Python Programmatic GStreamer Access for Hardware Encoded Acceleration and Low Latency

      @joseph-vale ,

      to enable voxl-streamer and voxl-camera-server on startup, just use the following commands:

      • systemctl enable voxl-camera-server
      • systemctl enable voxl-streamer

      Regarding your question about thermal radiometric readings, i am not sure - can you please elaborate? The default post-AGC 8-bit mode sends a monochrome processed image. The pixel value is related to the temperature, but the image itself does not provide the mapping from pixel value to temperature. Also, not all Boson units support outputting radiometric data.

      I don't have much experience with this aspect (and I don't think we have any Bosons with radiometric output capability). Looking at some FLIR help, it seems that you have to use the 16 bit output (well it's actually 14 bit) and turn on linear T output and then the conversion from RAW pixel value (16 bit) to degrees is simple : https://flir.custhelp.com/app/answers/detail/a_id/3387/~/flir-oem---boson-video-and-image-capture-using-opencv-16-bit-y16

      If this is the case, then here is how this could be tested (high level steps - don't worry if you don't know how to implement them at this point) :

      • set up Boson to correct configuration (output RAW14, linear T, etc) using the FLIR SDK (using USB)
      • configure VOXL2 to use boson driver that accepts 14 bit data (not 8-bit, which is default)
      • voxl-camera-server will publish RAW16 unmodified images to an mpa pipe
      • a client application can receive the RAW16 frame and apply the temperature conversion and publish the image that reflects certain temperature -> color mapping. Then this image can be used by voxl-streamer to be encoded with h264 / h265.

      I have not actually tried that script (at the bottom of that help article) -- i wonder what would happen if i use it with a Boson that does not support radiometric output. Do you know?

      I can help set this up if i can test it using non-radiometric Boson. It seems the conversion is straightforward, I could potentially add the support for this directly into voxl-camera-server.

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev
    • RE: Minimizing voxl-camera-server CPU usage in SDK1.6

      @Rowan-Dempster ,

      Yes, QVIO only runs as a 32-bit app due to the nature of the library from Qualcomm.

      I tried to build the voxl-image-repub application for 32 bit and got the following error:

      /usr/bin/arm-linux-gnueabi-ld: CMakeFiles/voxl-image-repub.dir/voxl-image-repub.cpp.o: in function `main':
      voxl-image-repub.cpp:(.text.startup+0x228): undefined reference to `pipe_client_set_ion_buf_helper_cb'
      

      So it seems like the 32-bit version of libmodal-pipe does not support sending ION buffers.

      I just checked with the team - even though we have not tested the ION buffer sharing in 32-bit environment, it should work. You could try to build libmodal-pipe library and enable ION support : https://gitlab.com/voxl-public/voxl-sdk/core-libs/libmodal-pipe/-/blob/master/build.sh?ref_type=heads#L76 .

      Then you would need to install that new library into your docker container where you are building your app, as well as deploy to VOXL2.

      BTW in order to build the tools in voxl-mpa-tools i needed to disable -Werror and comment out a few targets like voxl-convert-image and voxl-inspect-cam-ascii due to lack of 32-bit version of opencv.

      So.. if you really wanted the QVIO app to use the shared ION buffers, you would have to go that route..

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: M0201 gimbal passthrough pinout

      @Zachary-Lowell-0 and @smiley ,

      I just updated the docs to include more info on this https://docs.modalai.com/M0153/#misc-connector-pinout

      Also verified that i could ping a i2c device connected to M0201 J4 and M0201 itself is connected to VOXL2 J7 via M0181 (there are other options how to connect M0201 to VOXL).

      IMU -> [JST GH cable] -> (M0201 J4) .... (M0201 J2) -> [MIPI COAX cable] -> (M0181 J1) .... (M0181) -> (VOXL2 J7)

      voxl2:/$ i2cdetect -r -y 4
           0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
      00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
      10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
      20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
      30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
      40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
      50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
      60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
      70: -- -- -- -- -- -- -- --
      

      (able to ping an i2c IMU board connected to /dev/i2c-4).

      Please let me know if you have any additional questions.

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev
    • RE: Flir Boson+ Application v4.2 install file not available anymore - does anyone have it please?

      @simiken1234 , Can you please clarify what exactly did not work in 4.6.6?

      I have not tried it yet.

      Let me check regarding 4.2, we may not be able to distribute it.

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev
    • RE: Minimizing voxl-camera-server CPU usage in SDK1.6

      @Rowan-Dempster , sounds good, let me know how the testing goes.

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: EIS functionality

      @SKA ,

      Does this happen right away after you start voxl-camera-server ?

      What raw "preview" resolution / fps are you requesting in camera server config?

      Also, can you post output of dmesg (everything after you start voxl-camera-server)

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: EIS functionality

      @SKA , that result / buffer error (i think) is showing up because the camera pipeline selects incorrect camera mode / resolution, perhaps you missed one of the steps in EIS instructions, either using the correct camera drivers or updating the override txt file.

      Also, the latest docs for EIS are here, the old .md file is probably outdated : https://docs.modalai.com/camera-video/electronic-image-stabilization/

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: Minimizing voxl-camera-server CPU usage in SDK1.6

      Hi @Rowan-Dempster ,

      Please take a look at this example (you can build and run it too) : https://gitlab.com/voxl-public/voxl-sdk/utilities/voxl-mpa-tools/-/blob/add-new-image-tools/tools/voxl-image-repub.cpp

      This app can accept a regular image (RAW8 or YUV) and either re-publish it unchanged or crop and publish the result. Sometimes this is useful for quickly cropping an image that is fed into a different application that expects a smaller image or different aspect ratio.

      The app shows how to subscribe and handle ion buffer streams.

      Usage:

      voxl2:/$ voxl-image-repub                          
      ERROR: Pipe name not specified
      
          
          Re-publish cropped camera frames (RAW8 or YUV)
          
          Options are:
          -x, --crop-offset-x    crop offset in horizontal dimension
          -y, --crop-offset-y    crop offset in vertical dimension
          -w, --crop-size-x      crop size in horizontal dimension (width)
          -h, --crop-size-y      crop size in vertical dimension (height)
          -o, --output-name      output pipe name
          -u, --usage            print this help message
          
          The cropped image will be centered if the crop offsets are not provided. 
          
          typical usage:
          /# voxl-image-repub tracking --crop-size-x 256 --crop-size-y 256
          /# voxl-image-repub tracking --crop-size-x 256 --crop-size-y 256 --crop-offset-x 128 --crop-offset-y 128
      

      example re-publishing ion buffer image as regular image (which you can view in voxl-portal ) :

      voxl-image-repub tracking_front_misp_norm_ion -o test
      

      (you can see which ion pipes are available by running voxl-list-pipes | grep _ion)

      Please note that without the previous fix that i posted above, the client process that receives and uncached ION buffer will incur extra CPU load while accessing this buffer. For example, the same voxl-image-repub client uses 1.7% cpu while republishing the normalized image (cached ion buffer), while using 7.3% cpu republishing an image from an uncached ION buffer. (cpu usage % using one of the smaller cores).

      Please try and let me know if you have any questions.

      I know this cached / uncached buffering may be a bit confusing, but i will document this a bit more to help explain it a little better.

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: EIS functionality

      @SKA, you should be able to update libmodal-pipe to latest package in the dev package repository : http://voxl-packages.modalai.com/dists/qrb5165/dev/binary-arm64//

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: Using an RTK GPS with the VOXL2

      @alan123 , yes, the 12-pin connector on VOXL2 (J19) was designed such that the first 6 pins are compatible with a lot of existing GPS recevier modules. Please double check the pins and you should use a 12-pin connector to plug into VOXL2 (may need to re-pin your cable).

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev
    • RE: tracking down pipe switching to images of traccking front camera

      Hi @mark ,

      Thank you for the update. We will keep investigating the underlying issue that was a result of that questionable camera.

      Meanwhile, if you think that the camera is defective and has no damage, you can fill out an RMA request and send it back for an exchange. I cant really comment on what could be causing this on the camera itself (it would be interesting to try it), but the camera is not serviceable by the user.

      https://www.modalai.com/pages/rma

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: Minimizing voxl-camera-server CPU usage in SDK1.6

      Hi @Rowan-Dempster ,

      I started a new branch where I will be working on some performance optimizations in the camera server.

      https://gitlab.com/voxl-public/voxl-sdk/services/voxl-camera-server/-/tree/perf-optimizations

      In my initial testing, setting cpu to perf and when running one or two instances of the following:

      voxl-inspect-cam tracking_front_misp_norm tracking_down_misp_norm
      

      i was seeing:

      1 instance (2 inspected streams) : 42% CPU (of one core)
      2 instances (4 inspected streams): 58% CPU (of one core)
      

      with the changes i just committed, i am seeing:

      1 instance: 31% cpu
      2 instances : 36% cpu
      

      If you would like you can test camera server from this branch and see if you can reproduce the results.

      notes:

      • the internal buffers were switched from uncached to cached and proper buffer management was added to ensure that data written by GPU is properly accessed by CPU
      • with these changes, if you use the _encoded stream from the tracking camera, it will work, but in dmesg you will see messages related to qbuf cache ops failed -- this is still under investigation and will be fixed soon.

      Meanwhile, I will work on an a simple example that shows the usage of ION buffers, I will try to share it a bit later today.

      Alex

      posted in Video and Image Sensors
      Alex KushleyevA
      Alex Kushleyev
    • RE: Using Ardupilot with Flight Core v2+VOXL Mini 4-in-1 ESC : Min/Max PWM Mismatch and motors keep spinning after disarm

      tagging @Eric-Katzfey for Ardupiot -related question..

      Some answers:
      3-1: VOXL ESC supports PWM input via aux pads (as you probably already know, but just noting it here) : https://docs.modalai.com/voxl-mini-esc-datasheet/#pwm-inputs--outputs. The range of the commands are 1000us=0% duty cycle, 2000us = 100% duty cycle (linear mapping). There is no calibration needed or supported (the MCU clock is pretty accurate).

      3-2: Recommended PWM frequency (up to 1/(2000us) = 500hz as long as pulses have some off time between them), one-shot is supported.

      3-3: i don't think that we have tested the mini ESC with Ardupilot in PWM mode, but the ESC should work very similarly to a standard ESC in PWM control mode

      3-4: there is no way to set the zero-throttle PWM value in the ESC params, however here is my recommendation:

      • in order to stop the motor and keep it off, send pulse 950us
      • in order to start the motor, send pulse 1050us and operate in range 1050-2000us.
      • the turn off point is 1000us with some hysteresis, but you don't want to operate close to that point and risk motors shutting off in flight.

      Also, we do not support Dshot input for VOXL ESCs. Spin direction reversal is not supported with the PWM commands.

      UART protocol is recommended because you don't run into the PWM-related range issues and you also get telemetry back from the ESCs (and much higher command rate is supported).

      Alex

      posted in ESCs
      Alex KushleyevA
      Alex Kushleyev
    • RE: Python Programmatic GStreamer Access for Hardware Encoded Acceleration and Low Latency

      @joseph-vale ,

      You did not provide the actual error that you are seeing, however I could try to guess what it is (even if not, the details below should probably help you anyway). The default build of voxl-opencv package does not have python3 support. So if you are using gstreamer with opencv in python and that is the error, you should install the voxl-opencv package that I built with python3 support

      • https://storage.googleapis.com/modalai_public/temp/voxl-opencv_4.5.5-3_arm64.deb
      • source : https://gitlab.com/voxl-public/voxl-sdk/third-party/voxl-opencv/-/tree/add-python3-bindings

      Below, i will assume that you want to grab images from Boson part of the Hadron, however similar approach should apply to the RGB camera in Hadron.

      First you should test ability to grab images without python. You may need to replace your camera # depending on what camera id your Boson is.

      IMPORTANT: make sure that voxl-camear-server is not running while you are trying to use gstreamer.

      systemctl stop voxl-camera-server
      

      Tip: you can actually stream video using X forwarding with ssh. This should stream live Boson feed from voxl2 to your linux machine:

      ssh -Y username@<voxl-ip>
      gst-launch-1.0 qtiqmmfsrc camera=0 ! "video/x-raw,width=640,height=512,framerate=30/1" ! videoconvert ! autovideosink
      

      display image directly in terminal as ascii:

      gst-launch-1.0 qtiqmmfsrc camera=0 ! "video/x-raw,width=640,height=512,framerate=30/1" ! autovideoconvert ! aasink
      

      and then finally, a python script that grabs h264 video from qtiqmmfsrc, decodes it and returns frames to python:

      import time
      import cv2
      
      #get RGB (BGR?) directly
      #stream='gst-launch-1.0 qtiqmmfsrc camera=0 ! video/x-raw, width=640,height=512,framerate=30/1 ! autovideoconvert ! appsink'
      
      #get h264 -> decode -> BGR
      stream='gst-launch-1.0 qtiqmmfsrc camera=0 ! video/x-h264,format=NV12,profile=high,width=640,height=512,framerate=30/1 ! h264parse ! qtivdec ! qtivtransform ! video/x-raw,format=BGR,width=640,height=512 ! autovideoconvert ! appsink'
      
      print(stream)
      vcap = cv2.VideoCapture(stream,cv2.CAP_GSTREAMER)
      
      frame_cntr = 0
      while(1):
          ret, frame = vcap.read()
          if ret:
              frame_cntr += 1
              print('got frame %d with dims ' % frame_cntr, frame.shape)
      

      Hopefully, that works for you.

      Final recommendation - if you use qtiqmmfsrc this way, the Boson data is processed in the Qualcomm ISP and unless your have a special tuning file for Boson, the processed output will have degraded quality. Boson, by default, outputs post AGC 8-bit image which is already processed and does not need to be further processed by the ISP. I am not sure whether you can get RAW8 data from qtiqmmfsrc (unmodified data from Boson).

      We handle the above issue in voxl-camera-server by working with the RAW8 directly. We also recently started experimenting with 14bit pre-AGC data from Boson, which would need some processing before it is usable (if you are interested in that, i can share some more information).

      Finally, if you would like to use voxl-camera-server, which is what we recommend and support, there is also a way to get encoded h264/h265 data into python (using our experimental pympa (python MPA bindings)). That is a topic for a discussion in another post, if you are interested..

      Alex

      posted in Ask your questions right here!
      Alex KushleyevA
      Alex Kushleyev