Category Archives: Technology

B4X: An experiment for practical use of IoT on the shop floor

Beacons

At OneTwo, we are always searching for ways to make things easier on the workfloor.  For nearly a decade, we introduced barcode scanners everywhere! From architects and accountants, over carpenters and contractors, to farmers and gardeners are now using our small barcode scanners to record times, jobs and used materials.

The last couple of weeks, I’ve been investigating how we could tackle another common issue, but now on the factory shop floor.  Working on a specific step in the development of a product demands the constant focus of the operator so using a barcode scanner to get the instructions is, well, just not practical if you have your hands full.

Time to get to the lab! Provided with heaps of coffee, some unhealthy snacks and an open mind we started putting some ideas together on the whiteboard.  We wanted to give as much feedback to the operator as possible using monitors,  beamer projections at the workstation and personal instructions on phones and tablets.

The key to deliver hyper-contextual content to the users is knowing the location of every chess piece in the game: the workstation, the machine that is going to be build and the operator(s).  The underlying communication technology was going to be Bluetooth Low Energy (BLE). The Raspberry Pi has it and so does almost any phone or tablet. By attaching a cheap BLE Beacon to the machine we could understand the location of all the players.

Using B4X for this project was a no-brainer, as Erels toolbox is just made to build stuff like this! One important link in the chain was missing:  the BLE reader in B4J for the Raspberry Pi.  However, writing some small scripts and calling it using jShell and a couple of timers did the job just fine.

Scripts code:

Two scripts to discover BLE devices around the Raspberry Pi.  Each one runs in its own jShell in B4J. First one scans for devices, second one reads whatever they broadcast.

#!/bin/bash
# Beacon Scan by Alain Bailleul 2017
sudo timeout -s SIGINT 5s hcitool lescan

#!/bin/bash
# Beacon Scan by Alain Bailleul 2017
sudo timeout -s SIGINT 5s hcidump -X > scan.txt

Also, as the Raspberry Pi has to be a BLE beacon itself (so the Android Native app can discover it), I had to write another little script:

#!/bin/bash
# Beacon Scan by Alain Bailleul 2017

sudo hciconfig hci0 leadv 3
sudo hcitool -i hci0 cmd 0x08 0x0008 19 02 01 06 03 03 aa fe 11 16 aa fe 10 00 02 6f 6e 65 2d 74 77 6f 07 $1 $2 $3 00 00 00 00 00 00
sudo hciconfig

IPN=$(ip addr show eth0 | awk ‘/inet / {print $2}’ | cut -d/ -f 1)
IPW=$(ip addr show wlan0 | awk ‘/inet / {print $2}’ | cut -d/ -f 1)
MACN=$(ip link show eth0 | awk ‘/ether/ {print $2}’)
MACW=$(ip link show wlan0 | awk ‘/ether/ {print $2}’)

echo “$MACW;$IPW;$MACN;$IPN;END” > macip.txt

For anything related to presenting the instructions, we could use ABMaterial.

Alright! We’ve got everything we needed to set up a test scenario for a workstation so time to bring out the cool slide:

How it works

Although there are a lot of physical components and different OS’s in play, B4X has all the tools to make them seamlessly talk to each other using one language.  For the native Android part, I wrote my own BLE discovery library based on the altbeacons library. (Note, there is a library available in B4A to discover BLE devices).

For the video demonstration, things you have to keep in mind:

INPUT:

  1. OneTwo box + BLE beacon: represents a machine arriving on the workstation
  2. Raspberry Pi (under the table): represents the workstation
  3. Android Phone: represents an operator/visitor at the workstation

OUTPUT:

  1. On the monitor, for each ‘machine’ some info is presented (e.g. a serial number, to what country it has to be shipped, etc)
  2. On the phone: specific instructions for the operator(s) for this ‘machine’, or a greeting to a visitor.
  3. On the workstation, projected global instructions for the operator(s) for this ‘machine’ with a beamer.

Let’s have a look how all of this plays out:

This turned out to work all very well for a first trial! For real world usage, the project will need some more work (like improving the algorithms to discover the BLE devices, setting thresholds or calculating them without calibration, etc…).  But we are very excited with the possibilities this low-cost solution can already show in such a short time.

Next step will be setting this up on a real workstation on the shop floor in a real factory later this month.

Until next time,

Alwaysbusy

Click here to Donation and get the latest ABMaterial first!

 

 

Advertisements

B4J:Programming LEGO Mindstorms EV3

b4lego

I was wondering if it would be possible to use B4J to program the Lego Mindstorms EV3 Brick for some time. So, some weeks ago, I finally spend a couple of evenings looking into it. And yes, B4J goes Robotics! It uses a modified LeJOS Firmware.

I upgraded LeJOS to support Java 1.8, which is probably the most technical part of the project.  I cannot provide it here, as it depends on your Java version but if you follow the next steps, you can build your own.  This is done on a Windows PC:


Upgrading the LeJOS Firmware to use Java 1.8

The following procedure will install the java 8 environment compatible with leJOS 9.0 from windows 7. The only extra tool needed is 7ZIP (a free tool) which can generate tar and gz format.  In the following I use a temporary directoyr as F:\temp. Replace it with your own temp directory wherever it appears.

  1. Go to java site http://www.oracle.com/technetwork/java/ … 82511.html
  2. Create an account if you dont have one then Accept Licensee agreement and download ejdk-8-xxxxxxx-linux-arm-sflt-xxxxxxxx.tar.gz or the latest java8 jre for EV3.
  3. Unzip this file in your F:\temp directory. For simpler process you may rename the extracted directory  as ejdk8. Run 7zip as administrator!
  4. Go to directory ejdk8\ejdk1.8.0\bin. Save the file jrecreate.bat. Now right click on jrecreate.bat and select “modify”.  Add one first line to the bat file as SET JAVA_HOME=C:\Progra~2\Java\jdk1.8.xxxx.  this is where java8 is installed on my system. Program~2 stand for Program Files (x86) but is easier to type.
  5. Start a command window: Start->All prog->Accessory->commands.
  6. In this window type in the following commands
    F:
    cd temp
    cd ejdk8\ejdk1.8.0\bin
    jrecreate.bat –dest newjre –profile compact2 –vm clientIt should start creating the new jre files in the directory “newjre” under ejdk8\ejdk1.8.0\bin
    Wait for the final message.
    Close the command window.
  7. With file explorer go to F:\temp\ejdk8\ejdk1.8.0\bin. Copy “newjre” directory back to F:\temp
  8. Rename the “newjre” directory as something expected by LeJOS such as
    ejre-8-b132-linux-arm-sflt
  9. Right click on it. Open with 7ZIP and add to archive. Select tar format. It will create ejre-8-b132-linux-arm-sflt.tar file.
  10. Right click on tar copy then add archive with gzip format. It will create ejre-8-b132-linux-arm-sflt.tar.gz. You have created the JRE file for java8 expected by EV3.
  11. Insert your SD card and format it.
  12. Copy the ejre-8-b132-linux-arm-sflt.tar.gz under the sd card top directory.
  13. Go to C:\Program Files\leJOS EV3
  14. Now remove the SD from PV and insert the card into the EV3 brick then power it. Wait for the end of the install (about 10mn).

If anything goes wrong, format again the SD, empty the F:\temp directory and restart at step 3.  if it persist try another SD card.

Your brick is ready!


Next I wrote a B4J wrapper for the basics like motors, sensors etc. This project is just a hobby and may grow in the future. But I just wanted to share this first video (badly directed so no Oscars here, unless…)

Obviously, I wanted to test out my code, but I had to build a bot first.  Well, I was in for a surprise! It took me over 3 hours to build EV3D4 and I can tell you, I’m not a very patient person so I may have taken some shortcuts in the construction.

What happens in the video:
1. I uploaded the B4J created .jar file to the brick via ssh and I’m ready to start it.
2. After some time, it runs (on the brick shows a disclamer and waits for a key).
3. I disconnect the brick, put it on the ground and press a button on the brick.
4. I programmed the IR sensor so if it sees a wall, it turns away, else it keeps going.

Fun fact is you can use B4J-Bridge.jar on the brick!

This is handy as debugging a Brick is a b*tch. You must have a lot of patience and prepared to restart your brick A LOT. This is not a B4J limitation, just to say how unstable programming a Brick is in general.

Coding is straightforward in B4J (this is all the code I wrote, including turning if it is about to hit a wall):

Sub Process_Globals
   Private StartTimer As Timer
   Public EV3 As ABLegoEV3
   Public LeftMotor As ABLLargeRegulatedMotor
   Public RightMotor As ABLLargeRegulatedMotor
   Public Sensor As ABLIRSensor
   Public sp As ABLSensorMode

   Public control As Int = 0
   Public distance As Int = 255
End Sub

Sub AppStart (Args() As String)
   LeftMotor.Initialize("B")
   RightMotor.Initialize("C")

   LeftMotor.ResetTachoCount
   RightMotor.resetTachoCount
   LeftMotor.rotateTo(0)
   RightMotor.rotateTo(0)
   LeftMotor.Speed = 400
   RightMotor.Speed = 400
   LeftMotor.Acceleration = 800
   RightMotor.Acceleration = 800

   Log("starting sensor")
   Sensor.Initialize("S4")
   sp = Sensor.DistanceMode 

   IntroMessage

   StartTimer.Initialize("StartTimer", 100)
   StartTimer.Enabled = True
   StartMessageLoop
End Sub

Sub StartTimer_Tick
   ' read the sensor
   Dim sample(sp.sampleSize) As Float
   control = Sensor.getRemoteCommand(0)
   sp.fetchSample(sample, 0)
   distance = sample(0)
   Log("Control: " & control & " Distance: " & distance) 

   If distance < 70 Then
     Log("A wall!")
     EV3.Button.LEDPattern(2)

     LeftMotor.rotate2(-180, True) ' start Motor.B rotating backward
     RightMotor.rotate(-180)  ' rotate C farther To make the turn
     If Bit.And(DateTime.Now, 1) <> 0 Then
         LeftMotor.rotate2(-180, True) ' start Motor.B rotating backward
         RightMotor.rotate(180)  ' rotate C farther To make the turn
     Else
         RightMotor.rotate2(-180, True) ' start Motor.B rotating backward
         LeftMotor.rotate(180) ' rotate C farther To make the turn
     End If
  Else
     Log("Let's walk")
     EV3.Button.LEDPattern(1)

     LeftMotor.Speed = 400
     RightMotor.Speed = 400
     LeftMotor.Backward ' my motors are installed inverted on this robot
     RightMotor.Backward
  End If
End Sub

Sub IntroMessage()
   Dim g As ABLGraphicsLCD = EV3.GraphicsLCD
   g.clear
   g.drawString("Bumper Car Demo", 5, 0, 0)
   g.Font = g.Font.SmallFont
   g.drawString("Demonstration of the Behavior", 2, 20, 0)
   g.drawString("subsumption classes. Requires", 2, 30, 0)
   g.drawString("a wheeled vehicle with two", 2, 40, 0)
   g.drawString("independently controlled", 2, 50, 0)
   g.drawString("motors connected to motor", 2, 60, 0)
   g.drawString("ports B and C, and an", 2, 70, 0)
   g.drawString("infrared sensor connected", 2, 80, 0)
   g.drawString("to port 4.", 2, 90, 0)

   ' Quit GUI button:
   g.Font = g.Font.SmallFont
   Dim y_quit As Int = 100
   Dim width_quit As Int = 45
   Dim height_quit As Int = width_quit/2
   Dim arc_diam As Int = 6
   g.drawString("QUIT", 9, y_quit+7, 0)
   g.drawLine(0, y_quit,  45, y_quit) ' top line
   g.drawLine(0, y_quit,  0, y_quit+height_quit-arc_diam/2) ' left line
   g.drawLine(width_quit, y_quit,  width_quit, y_quit+height_quit/2) ' right line
   g.drawLine(0+arc_diam/2, y_quit+height_quit,  width_quit-10, y_quit+height_quit) ' bottom line
   g.drawLine(width_quit-10, y_quit+height_quit, width_quit, y_quit+height_quit/2) ' diagonal
   g.drawArc(0, y_quit+height_quit-arc_diam, arc_diam, arc_diam, 180, 90)

   ' Enter GUI button:
   g.fillRect(width_quit+10, y_quit, height_quit, height_quit)
   g.drawString2("GO", width_quit+15, y_quit+7, 0,True)

   EV3.Button.WaitForAnyPress
   If (EV3.Button.ESCAPE.isDown()) Then
     ExitApplication2(0)
   End If
   g.clear
End Sub

As I said, this is just for fun. No idea how far this will go.  You can download the source code for the B4J library from my Github.

Cheers,

Alwaysbusy


B4J: ABTelegram bots library

Bots are the next hot thing in 2016! So in my spare-spare time I’ve been working on a wrapper for the Telegram API v2.0. It has a rather unconventional API but I’m reworking it to make it very easy to write bots in B4J.

Bots could be very useful as yet another way to ‘talk’ with IoT devices. You can control LEDs, temperatures, ask for stats etc right from within the Telegram Chat App (which runs on about every kind of platform, being the desktop, a browser, iOS, Android, etc…). Or you can, like I did to test the wrapper, write a little game:

ABTelegram

Note: this library is in very early stages so the wrapper is not available for download yet. Full source code of the game will also be available when released.

Some sample code to show you how easy it is to write a bot in B4J (this is not the game code, just some tests):

Code to initialize the library:

Sub Process_Globals
   Dim ABT As ABTelegram
End Sub

Sub AppStart (Args() As String)
   Dim b As MyBot
   b.Initialize
   ABT.RegisterLongPollingBot(b.Bot)

   StartMessageLoop
End Sub

Code for the Bot:

'Class module
Sub Class_Globals
Dim ABT As ABTelegram
Public Bot As ABTLongPollingBot
Private botToken As String = &quot;207189xxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy&quot;
Private botUserName As String = &quot;zzzzzzzzzBot&quot;
'Private callbackCounter As Int
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
Bot.Initialize(&quot;Bot&quot;, Me, botToken, botUserName)
Dim upds As List = Bot.botgetUpdates
For i = 0 To upds.Size - 1
Dim upd As ABTUpdate = upds.Get(i)
Log(&quot;Go update: &quot; &amp; upd.UpdateId)
Next
End Sub

Sub Bot_UpdateReceived(update As ABTUpdate)
Log(&quot;Got an update&quot;)
If update.hasMessage Then
Dim msg As ABTMessage = update.GetMessage
Log(&quot;Message: &quot; &amp; msg.Text)

'        Dim userPhotos As ABTUserProfilePhotos = Bot.BotGetUserProfilePhotos(msg.Chat.id)
'        Log(&quot;photos: &quot; &amp; userPhotos.TotalCount)
'        Dim Photos As List = userPhotos.Photos
'        For i = 0 To Photos.Size - 1
'            Dim photoSizes As ABTPhotoSizes = Photos.Get(i)
'            For j = 0 To photoSizes.Sizes.Size - 1
'                Dim photoSize As ABTPhotoSize = photoSizes.Sizes.Get(j)
'                Dim photoFile As ABTFile = Bot.BotGetFile(photoSize.FileId)
'                Log(photoFile.FilePath)
'
'                Dim job1 As HttpJob
'                job1.Initialize(&quot;Job&quot; &amp; j, Me)
'                job1.Tag = photoFile.FilePath.Replace(&quot;photo/&quot;, &quot;&quot;)
'
'                Dim url As String = &quot;https://api.telegram.org/file/bot&quot; &amp; botToken &amp; &quot;/&quot; &amp; photoFile.FilePath
'                   job1.Download(url)
'               Next
'        Next

'        callbackCounter = callbackCounter + 1
'        Bot.BotSendMessageAsync(callbackCounter, msg.ChatId, &quot;Alweer hallo &quot; &amp; msg.Chat.FirstName)

Bot.BotSendMessage(msg.ChatId, &quot;Using an Emoji &quot; &amp; &quot;:grinning: in the message!&quot;) ' see    https://github.com/vdurmont/emoji-java for a list of emojis

'        Bot.BotSendPhoto(True, msg.ChatId, File.DirApp &amp; &quot;/&quot; &amp; &quot;telegram.png&quot;)

'        callbackCounter = callbackCounter + 1
'        Bot.BotSendDocumentAsync(callbackCounter, True, msg.ChatId, File.DirApp &amp; &quot;/&quot; &amp; &quot;mydocument.pdf&quot;, &quot;mydocument.pdf&quot;)

'        Bot.BotSendDocument(True, msg.ChatId, File.DirApp &amp; &quot;/&quot; &amp; &quot;mydocument.pdf&quot;, &quot;mydocument.pdf&quot;)

Bot.BotSendAudio(True, msg.ChatId, File.DirApp &amp; &quot;/&quot; &amp; &quot;myaudio.mp3&quot;)

'        Bot.BotSendVideo(True, msg.ChatId, File.DirApp &amp; &quot;/&quot; &amp; &quot;myvideo.mp4&quot;)

'        Bot.BotSendSticker(True, msg.ChatId, File.DirApp &amp; &quot;/&quot; &amp; &quot;mysticker.webp&quot;)

'        Bot.BotSendContact(msg.ChatId, &quot;+32496000000&quot;, &quot;Alain&quot;)

'        Bot.BotSendChatAction(msg.ChatId, ABT.CHATACTIONTYPE_TYPING)

'        Bot.BotSendLocation(msg.ChatId, 50.8492, 2.8779)

'        Bot.BotSendVenue(msg.ChatId, 50.8492, 2.8779, &quot;my venue&quot;, &quot;Grote markt 1&quot;)

Bot.BotSendVoice(True, msg.ChatId, File.DirApp &amp; &quot;/&quot; &amp; &quot;telegram.ogg&quot;)

'        Dim keyb As ABTReplyKeyboard
'        Dim rows As List
'        rows.Initialize
'        Dim tmpRow As ABTInlineKeyboardRow
'        tmpRow.Initialize
'        tmpRow.AddButton(&quot;test button&quot;, &quot;http://one-two.com&quot;, &quot;&quot;, &quot;&quot;)
'        rows.Add(tmpRow)
'        keyb.InitializeAsInlineKeyboardMarkup(rows)
'        Bot.BotEditMessageTextEx(msg.ChatId, msg.MessageId, 0, &quot;Extended test&quot;, ABT.PARSEMODE_HTML, False, keyb)

Dim rkeyb As ABTReplyKeyboard
rkeyb.InitializeAsForceReplyKeyboard(False)
Bot.BotSendMessageEx(msg.ChatId, &quot;some test: reply please&quot;, ABT.PARSEMODE_HTML, False, False, 0, rkeyb)

'        Dim rkeyb2 As ABTReplyKeyboard
'        Dim rows2 As List
'        rows2.Initialize
'        For i = 1 To 100
'            Dim tmpRow2 As ABTKeyboardRow
'            tmpRow2.Initialize
'            tmpRow2.AddButton(&quot;Press me&quot;)
'            rows2.Add(tmpRow2)
'        Next
'        rkeyb2.InitializeAsReplyKeyboardMarkup(rows2,False, False, False)
'        Bot.BotSendMessageEx(msg.ChatId, &quot;some test: press the button&quot;, ABT.PARSEMODE_HTML, False, False, 0, rkeyb2)

'        Dim rkeyb3 As ABTReplyKeyboard
'        Dim rows3 As List
'        rows3.Initialize
'        Dim tmpRow3 As ABTInlineKeyboardRow
'        tmpRow3.Initialize
'        tmpRow3.AddButton(&quot;Show image&quot;, &quot;&quot;, &quot;showimage&quot;, &quot;&quot;)
'        rows3.Add(tmpRow3)
'
'        rkeyb3.InitializeAsInlineKeyboardMarkup(rows3)
'        Bot.BotSendMessageEx(msg.ChatId, &quot;some test: press the button&quot;, ABT.PARSEMODE_HTML, False, False, 0, rkeyb3)
End If
If update.hasCallbackQuery Then
Dim cquery As ABTCallbackQuery = update.GetCallbackQuery
Log(&quot;CallbackQuery: &quot; &amp; cquery.data)
Select Case cquery.Data
Case &quot;showimage&quot;
Dim msg As ABTMessage = cquery.Message

Bot.BotSendPhotoEx(True, msg.ChatId , File.DirApp &amp; &quot;/&quot; &amp; &quot;myphoto.jpg&quot;, &quot;A new photo of darth vader!&quot;,False, 0, Null )
Bot.BotSendLocation(msg.ChatId, 50.8492, 2.8779)
Bot.BotEditMessageText(msg.ChatId, msg.MessageId, &quot;&quot;, &quot;Shown&quot;)
End Select
End If
If update.hasInlineQuery Then
Dim ciquery As ABTInlineQuery = update.GetInlineQuery
Log(&quot;InlineQuery: &quot; &amp; ciquery.Query)
If ciquery.Query = &quot;loc&quot; Then
Dim lstResults As List
lstResults.Initialize
Dim myanswer As ABTInlineQueryResult
myanswer.InitializeAsLocation(&quot;1&quot;, 50.8492, 2.8779, &quot;Your location&quot;)
lstResults.Add(myanswer)
Bot.BotAnswerInlineQuery(ciquery.Id, lstResults)
End If
End If
If update.hasChosenInlineResult Then
Dim ccresult As ABTChosenInlineResult = update.GetChosenInlineResult
Log(&quot;ChosenInlineResult: &quot; &amp; ccresult.Query)
End If
End Sub

Sub Bot_AsyncSendReceived(methodType As String, callbackId As String, success As Boolean, asyncObject As ABTObject)
Log(&quot;Async method: &quot; &amp; callbackId &amp; &quot; &quot; &amp; methodType &amp; &quot; &quot; &amp; success)
If success And asyncObject &amp;lt;&amp;gt; Null Then
If asyncObject.objectType=&quot;ABTMessage&quot; Then
Dim message As ABTMessage = asyncObject
Log(&quot;Async callback: &quot; &amp; message.MessageId)
End If
End If
End Sub

Sub JobDone (Job As HttpJob)
Log(&quot;JobName = &quot; &amp; Job.JobName &amp; &quot;, Success = &quot; &amp; Job.Success)
If Job.Success = True Then
Dim fSave As OutputStream = File.OpenOutput(File.DirApp, Job.tag, False)
File.Copy2(Job.GetInputStream, fSave)
fSave.Close
Else
Log(&quot;Error: &quot; &amp; Job.ErrorMessage)
End If
Job.Release
End Sub

Alwaysbusy

Click here to Donation if you like my work

 


B4R (Basic4Arduino) is coming!

Excellent news from Erel (CEO of Anywhere Software).  The excellent B4X suite will support yet another platform: Arduino!  Next to support for all desktop platforms, webapps, Raspberry Pi, Android and iOS this new addition is another great step from Anywhere Software towards the most simple framework to make IoT applications.

Unlike the other platforms which generate Java, B4R will generate native C.  Users will be able to write their own libraries or use inline C for specific functionalities.  More on this later, but make sure you check out the video!

 

 


Xojo: Sketching with Real-time Contrast Preserving Decolorization and Potrace

Sketcher

Always looking for some ways to learn the computer to ‘see’, I came accross two very interesting algorithms: ‘Real-time Contrast Preserving Decolorization’ by Cewu Lu, Li Xu and Jiaya Jia. And Potrace by Peter Selinger

Decolorization – the process to transform a color image to a grayscale one – is a basic tool in digital printing, stylized black-and-white photography, and in many single channel image processing applications. RTCPD is aiming at maximally preserving the original color contrast alleviate a strict order constraint for color mapping based on human vision system.

An example can be seen here:
RTCPD

The second algorithm Potrace(TM) is a tool for tracing a bitmap, which means, transforming a bitmap into a smooth, scalable image.

Example:
potrace

Playing around with both algorithms, I came up with the idea to use them for a project I had in mind for some time: Sketching pictures on my wall using a Pico projector.

First I had to implement both algorithms in Xojo. The result of RTCPR can be found in the attached source code in the RTCPRGB2Gray() method:

Private Sub RTCPRGB2Gray(pic as Picture)
  dim imcols as Integer = pic.Width
  dim imrows as Integer = pic.Height
  dim sRGB as RGBSurface = pic.RGBSurface

  dim Mat(-1,-1) as ABDoubleVector
  redim Mat(imrows-1,imcols-1)
  dim c as Color
  for y as Integer = 0 to  imrows - 1
    for x as Integer = 0 to imcols - 1
      c = sRGB.Pixel(x,y)
      mat(y,x) = new ABDoubleVector(c.Blue, c.Green, c.Red) ' switch to BRG
    next
  next

  dim s as Double = 64.0 / sqrt(imcols*imrows)
  dim cols as Integer = (s * imcols) + 0.5
  dim rows as Integer = (s * imrows) + 0.5

  dim sigma as Double = 0.05
  dim W() as ABDoubleVector = wei()

  dim P() as ABDoubleVector
  dim det() as Double

  dim pos0() as ABDoublePoint
  dim pos1() as ABDoublePoint
  for i as Integer = 0 to cols - 1
    for j as Integer = 0 to rows - 1
      dim x as Integer = (i+0.5) * imcols/cols
      dim y as Integer = (j+0.5) * imrows/rows
      pos0.Append new ABDoublePoint(x,y)
      pos1.Append new ABDoublePoint(x,y)
    next
  next

  pos1.Shuffle

  for i as Integer = 0 to pos0.Ubound
    dim c0 as ABDoubleVector = mat(pos0(i).y, pos0(i).x)
    dim c1 as ABDoubleVector = mat(pos1(i).y, pos1(i).x)

    add c0,c1, P, det
  next

  cols = cols / 2
  rows = rows / 2

  for i as Integer = 0 to cols - 2
    for j as integer = 0 to rows - 1
      dim x0 as integer = (i + 0.5) * imcols / cols
      dim x1 as integer = (i + 1.5) * imcols / cols
      dim y as integer = (j + 0.5) * imrows / rows

      dim c0 as ABDoubleVector = mat(y, x0)
      dim c1 as ABDoubleVector = mat(y, x1)

      add(c0, c1, P, det)
    next
  next

  for i as integer = 0 to cols - 1
    for j as Integer = 0 to rows - 2
      dim x as integer = (i + 0.5) * imcols / cols
      dim y0 as integer = (j + 0.5) * imrows / rows
      dim y1 as integer = (j + 1.5) * imrows / rows

      dim c0 as ABDoubleVector = mat(y0, x)
      dim c1 as ABDoubleVector = mat(y1, x)

      add(c0, c1, P, det)
    next
  next

  dim maxES as Double = -99999999999
  dim bw as Integer
  for i as integer = 0 to w.Ubound
    dim es as Double
    for j as integer = 0 to p.Ubound
      dim l as Double = P(j).x * W(i).x + P(j).y * W(i).y + P(j).z * W(i).z
      dim detM as Double = det(j)

      dim a as double = (L + detM) / sigma
      dim b as double = (L - detM) / sigma

      es = es + log(exp(-a * a) + exp(-b * b))
    next
    es = es / (p.Ubound+1)
    if eS &gt; maxEs then
      maxEs = Es
      bw = i
    end if
  next

  dim result(-1,-1) as Double
  redim result(imrows-1,imcols-1)

  for y as Integer = 0 to  imrows - 1
    for x as Integer = 0 to imcols - 1
      result(y,x) = mat(y,x).z*W(bw).x + mat(y,x).y*w(bw).y+0
      result(y,x) = mat(y,x).x*W(bw).z + result(y,x)*1+0
      sRGB.Pixel(x,y) = rgb(result(y,x),result(y,x),result(y,x))
    next
  next

  bw = 0
End Sub

Potrace is a complete framework to trace an image and converting it to Xojo did take some time. While writing it, I also made some changes to it to optimize the result. One of it was doing my own thresholding using the surrounding pixels to smoothen the edge detection.

Snippet:

  dim v, v1, v2, v3, v4, v5, v6, v7, v8 as Integer
  dim ex,ey, weight, weighttotal, total as Double

  'SISThreshold2 alain
  for y = 1 to H - 2
    for x = 1 to W - 2
      v = sDebugPicRGB.Pixel(x, y).red
      v1 = sDebugPicRGB.Pixel(x+1, y).red
      v2 = sDebugPicRGB.Pixel(x-1, y).red
      v3 = sDebugPicRGB.Pixel(x, y+1).red
      v4 = sDebugPicRGB.Pixel(x, y-1).red
      v5 = sDebugPicRGB.Pixel(x+1, y-1).red
      v6 = sDebugPicRGB.Pixel(x-1, y-1).red
      v7 = sDebugPicRGB.Pixel(x+1, y+1).red
      v8 = sDebugPicRGB.Pixel(x-1, y+1).red
      ex = (v1+v2+v5+v6)/4
      ey = (v3+v4+v7+v8)/4
      if ex &gt; ey then
        weight = ex
      else
        weight = ey
      end if
      weighttotal = weighttotal + weight
      total = total + weight * (v)
    next
  next

  dim  Threshold as Integer = 128

  if weighttotal &lt;&gt; 0 then
    Threshold = total/weighttotal
  end if

  dim ret as Boolean = (sDebugPicRGB.Pixel(0, 0).Red &gt;= Threshold)

  for y = 0 to H
    for x = 0 to W
      c = sDebugPicRGB.Pixel(x, y)
      if c.red &gt;= Threshold then
        Matrix(x+1, y + 1) =true
      else
        Matrix(x+1, y + 1) = false
      end if
    next
  next 

  for x = 0 to MatrixW
    Matrix(x,0) = true
    Matrix(x, MatrixH) = true
  next
  for y = 0 to MatrixH
    Matrix(0,y) = true
    Matrix(MatrixW, y) = true
  next

This gave me all the tools to start tracing an image. But for my project I wanted to have a sort of ‘sketchy’ feeling. For this I needed a couple of things because I wanted the drawing and painting to be done gradually. I had to build it with delays, repetition, randomization and color fading. I wanted to start from a picture and create something like this:
jobs

DrawImage() does all that. It first draws the beziers with some little random mistakes in grey. A gradual painting is then used to fill in the polygons. Finaly it repeats the process with the correct lines in white.

You may notice that a lot of code is redundant, but this is intended because I needed to have enough delays to mimic a more natural feeling.

Here is a demo video showing the result of this project on my wall. It takes about ten seconds before it starts drawing as I had to grab my camera :-). Five different images are drawn.

The project with full source code can be downloaded here

Greetz!

Alwaysbusy

Click here to Donation if you like my work


Xojo: Release 2014R3 with iOS support

Xojo with iOS support
We are spoiled this Christmas! Xojo has released a new update of their cross-platform development tool, and this time it includes a new one: iOS.

I think congratulations is in order to the Xojo dev team! The wait has been long and there are a lot of eager programmers wanting to explore the world of mobile development. There are some changes in the framework that will it make somewhat harder for hardcore developers (me included) who have already huge business logic libs. But I’m sure the Xojo community will come up with some tricks to make the transition faster.

Already some members are trying to set-up some kind of central place to cover some missing controls/functionalities with Declares. I hope they share the source code, so we can all learn from it!

Here is what the wizards of Xojo have to say:

Xojo, Inc.:
Latest release allows users to create high-quality, native iOS applications in the same way they develop desktop and web apps today.

Xojo users can now build iOS apps in the same way desktop and web applications are created. Users can drag and drop to create the user interface and use one straight-forward programming language to implement the functionality of their app. Xojo makes it significantly faster and easier to create native iOS apps than any other tool. Many iOS business apps rely on a web-based server application that provides business logic and database access. Xojo is the only development tool that provides the ability to create both a native iOS client application and a native server application from a single language and tool. Users experience true multi-platform development with Xojo, creating their app on one platform and delivering a completely native product to users on another platform.

Geoff Perlman (Xojo Founder and CEO):
“Xojo 2014 Release 3 represents a huge leap forward for us as we are now have a mobile development platform. Adding iOS to Xojo has been the top feature request from our users and we are pleased to deliver. By expanding their Xojo applications from the desktop and web to iOS, our developers are now able to broaden their target audience to a whole new range of prospects.”

This latest release adds 160 improvements and over 20 new features. In addition to the new iOS framework, this release also adds improvements to the web framework and includes new classes that make creating international applications easier. Further, web applications can now respond to requests from search engines such as Google, making their content searchable on the web.

Xojo 2014 Release 3 feature highlights include:

  • New iOS framework.
  • New Text data type and supporting methods for improved text handling.
  • New Auto data type for storing any type or object.
  • New Xojo.Core classes that make creating international applications easier.
  • SSLSockets now support newer security protocols like TLS v1.1 and v1.2, and now defaults to TLS v1 instead of SSLv3.
  • For Web applications, a new HandleURL event allows processing requests for URLs that previously could not be served. This feature also gives you the ability to respond to requests from Google and other search engines.


So as of now, we programmers, have two new development tools added to our repertoire: Xojo iOS and B4i (see previous article). Both with their advantages and drawbacks. As a Windows programmer it is nice for me to be able to develop iOS apps on my own platform with B4i. At the time of this writing, Xojo iOS is Mac only. But who knows, maybe there is some secret Santa out there that will put a Mac mini under my tree (hint!).

But this a personal view of course. My code lib for android (B4A) is also vast and the conversion for my mobile apps is probably going to go smoother when I stay in the same language and OS. So in the end, it’s up to you to make a choice (or use both)! After all, it’s almost Christmas, so you all deserve a treat…

Happy programming!

Alwaysbusy


B4i: Official release at special introductory price!

B4I logo
Great news from Anywhere Software! B4i (a development tool for native iOS applications) is released today.

I had good hopes we would have an early Christmas this year from Erel, but it looks like he has outdone himself (again!).

From its beta release only a couple of weeks ago, B4i looked very stable and already feature rich. Knowing how the B4A (Basic4Android) community quickly has grown very solid, with many contributors creating all kind of great libraries, I have no doubt B4i will be any different. Congratulations Erel with another state-of-the-art development tool!

But let’s give the master himself the stand now (from the official site):

Erel: B4i follows the same concepts of B4A and B4J and provides a simple yet powerful rapid application development tool for iOS applications.

Requirements

– Apple developer account (costs $99 per year).
– An iOS device running iOS 7+.

The compilation process requires a Mac computer. You can either use a local Mac computer or use our Hosted Mac Builder service (currently costs $25 per year).

Documentation

– Tutorials: http://www.basic4ppc.com/android/forum/forums/ios-tutorials.63/
You should start with the following three tutorials:
Creating a certificate and provisioning profile
Installing B4i-Bridge and debugging first app
Developers who use a local Mac: Local Mac Builder Installation

– Formal documentation: http://www.basic4ppc.com/b4i/documentation.html

Purchase

B4i can be purchased from the Anywhere Software Store for just $59!
B4i includes two years of free upgrades.

Hosted Mac Builder

The builder service allows you to develop iOS applications without a Mac computer.
All of the development steps can be done with the builder service except of the final step which is uploading the application to Apple App Store. This step requires a Mac or a service such as MacInCloud.
Note that the builder is currently limited to projects of up to 15mb.

Looking forward to play with this!


%d bloggers like this: