Dynamic Languages and Java/Case Study

From JVMLanguages

Table of contents

Introduction

    The fully automated factory of the future employs only one man and a dog.
    The dog is there to make sure the man doesn't touch anything, and the man is there to feed the dog.
      -- Unknown 

In much the same way that the software industry has been trending towards dynamicism, the manufacturing industry has been pushing towards automation. Factory robots continue to replace human workers since they are more precise, more reliable and, in most cases, less expensive. Thanks to increased integration of computer systems, distribution of both supplies and finished products are tracked more accurately than ever before. The majority of this book has been spent exploring the paradigm of multi-language software development and pushing that idea to the bleeding edge of the industry. In this chapter, however, we will be using these techniques to explore the drive towards automation in manufacturing and forecasting what may be possible in the future. Let's begin by picturing a world where manufacturing plants can be completely automated and finished products can be fabricated entirely from commodity off-the-shelf components or recycled materials and shipped to customers without any human interaction.

Automation due to an increased use of computers is now ubiquitous, but automation in manufacturing is of particular interest. Once machines are capable of creating sufficiently complex components, they open up the possibility of creating other machines that fulfill a similar purpose -- in other words, self-replication. Von Neumann, the father of the modern digital computer, was obsessed with this idea. He envisioned oceans swarming with robots that were capable of consuming natural resources that could be used to construct copies of themselves. Along with replicating like a virus, they would also fulfill some other purpose -- perhaps foraging for valuable minerals, or cleaning up an oil spill. This other purpose could then occur at an exponential rate for the cost of building only a single robot. Amateur solar explorers also love this idea, as it could provide a cost-effective way of mining asteroids or teraforming planets. However, creating a single machine able to replicate itself has proven to be a difficult problem. A better idea may be to create an army of specialized robots each capable of performing a single task, but also capable of collaborating to collectively replicate the entire army. In theory, these robots could collectively manufacture and assemble customized tools to accomplish any task. At this point you could simply put them in a sufficiently large room with a steady supply of unprocessed resources and call them a manufacturing plant.

Let's consider what some Use Cases of this automated factory may be.

  • Users will dispose of their garbage and unwanted items in a kiosk, which will pay them cash in exchange for the raw materials and will send the items to a centralized recycling center.
  • The unwanted items will travel through a series of machines where the various compounds will be recovered, sorted, and stored.
  • The raw materials can be processed in a chemical plant in order to extract basic elements and recombine them to synthesize any required molecules or compounds.
  • Orders for new products are then placed via a shopping cart website and the desired items are fabricated from raw materials, assembled, packaged, and shipped directly to the customer.
  • Materials at each stage of the manufacturing process are given a monetary value using an internal auctioning process. Corporations will be allowed to submit agent programs which can interact with this auctioning system and bid for materials or solicit bids on their behalf.

To demonstrate many of the language integration concepts that I am proposing, and to prove the viability of a multi-language approach to development, in the rest of this book I will be developing the software to control just such an automated factory. This will require creating a complex system made up of a dozen components that extend all the way from low-level hardware interfaces up to high-level artificial intelligence components. These components will each be implemented in a different programming language and using a different technique to integrate them with Java.

Each component of the Manufacturing Plant will be implemented in the language that I feel is best suited for this task.

  • Java for the framework
  • Domain-Specific language for Chemical Processing
  • E for the auction system
  • C++ for controlling manufacturing equipment
  • JSTL for the web site (or PHP w/ JSR-223?)
  • Perl for Shipping (FedEx/UPS)
  • Scheme for the Packing System
  • Ruby for the Transportation System
  • Python for the Storage System

Building a Framework

The core architecture of our manufacturing plant consists of a number of independent worker machines that each carry out a discrete set of tasks, and collaborate together to fill an order. Each subsystem needs to be somewhat isolated from the others, but needs to communicate with the broker via a standard interface. This is what allows us to implement each component in a different programming language. To do this we will let frameworks like BSF manage the language translations and mappings that are required.

We obviously need some concept of a "task", which is a request for a specific action to be performed. Synthesizing a chemical compound, spot welding two aluminum bars together, and painting an assembled bike cherry-red are all examples of tasks. We'll also need "workers" to execute our tasks. In this case, a chemical plant, a welding robot, and a spray painter are the workers. Tasks can have dependencies on the output of other tasks, so they have a composite relationship and can be viewed as a tree.

Since we're implementing a simulator and not the actual driver applications that would run a physical manufacturing plant, we'll also need some model to represent what would otherwise exist in the real world. We'll introduce an additional concept called a "model" that is essentially a data structure describing a three-dimensional object, similar to one you might load into a CAD application. When a task is executed, it generates a model, and these are fed into the parent tasks as part of an input structure. The model returned by executing the root task in the task tree is the final object that can be shipped off to the user.

Since we have a somewhat static pool of workers but a dynamic queue of tasks, we'll want some kind of broker process to manage the task queue and track which worker is executing each task. The broker is also responsible for tracking task dependencies and ensuring that a tasks children are executed before it is, and that the worker is given the models that result from this execution.

Adding Multi-Language Support

Now that we have a core architecture, we'll need some way of configuring which workers will be available and how the broker will assign tasks to them. There are a number of ways that we could configure this. We could hardcode the rules and workers into our code. We could also create our own file format and use this file to drive the configuration process. We could have each worker live in a separate process and use a directory service to hook them together.

However, in this case the workers will be implemented in more than one programming language. It would also be nice to avoid having Java glue code for each component. Because of this, we'll use Jelly as a very high-level language to configure our Task Broker and to instantiate and integrate the various workers for each subsystem. In addition to acting as an extremely powerful configuration tool, Jelly also has native support for BSF, which gives us the ability to transparently slip code written in another languages into our Jelly configuration file.

   <broker xmlns:bsf="jelly:bsf">
     <worker-list xmlns:bsf="jelly:bsf">
       <worker id="painter"
         <bsf:script engine="org.jruby.javasupport.bsf.JRubyEngine">
         </bsf:script>
       </worker>
     </worker-list>
   </broker>

Transportation System

The transporation system controls the conveyor belts and forklifts that carry materials between the machines.

I will implement this system in Ruby.

Storage System

The storage system stores and maintains an inventory of the raw materials, and I will write it in Python.

Packaging System

The packaging system is essentially one recursive algorithm for packing arbitrarily shaped objects into a rectangular box. I will implement this algorithm in Scheme.

Connecting a CNC Device to our Manufacturing Plant

There are now a few key components of our manufacturing system in place. Now it's time to replace one of the simulated components with a real machine made of metal and gears. In particular, we're going to attach two fabrication devices: a lathe and a mill. A lathe is a device that spins a solid material along one axis and uses cutting tools in the other two axes to shape a part that is radially-symmetrical. A mill is a device that simply moves a cutting tool in three dimensions and simply cuts out the desired shape. We're going to want what are called Command 'N Control (CNC) devices, which just means that they can be controlled by a computer or some other programmable device.

I've taken the liberty of purchasing two CNC devices from ACME, Inc. They arrived along with driver software in the form of a compiled shared library and C++ header files. Now it's up to you to integrate this library with our existing Java components.

You'll probably want to use SWIG to generate the Java wrapper for you. To do this, you'll need to create a cnc.i file to use as input to SWIG.

   %module cnc

   %{
   #include "Tuple.h"
   #include "CNCMachine.h"
   #include "Mill.h"
   #include "Lathe.h"
   %}

   %include "Tuple.h"
   %include "CNCMachine.h"
   %include "Mill.h"
   %include "Lathe.h"
     

Now it's time to generate our Java wrappers:

   $ swig -c++ -java -package com.oreilly.javalangint.cnc.api cnc.i
   $ g++ -shared -olibcnc.so *.cxx
   $ javac com/oreilly/javalangint/cnc/api/*.java

If everything went well, you should now have a Java version of the C++ API in the com.oreilly.javalangint.cnc.api package as well as a libcnc.so shared library that needs to be loaded by Java in order to resolve the API's native methods.

Now, let's write some Java code to test out this API.

   $ javac com/oreilly/javalangint/cnc/*.java
   $ java -Djava.library.path=. com.oreilly.javalangint.cnc.Client

Our Client class should now be able to access every part of the CNC machines' public APIs.

Planning

Since the manufacturing system is autonomous, it should be able to turn any specification for a product from raw materials into a finished product. This will involve the use of any number of machines including mills and lathes, presses and molds, assembly, and painting. The key to this process is planning, which will be implemented by a series of rules implemented in Jess.

Auction

In addition to users recycling their unwanted items and requesting new products, obtaining corporate clients will important to make this manufacturing plant viable. To implement this, an API will be provided so that corporations can implement "bidding agents", which can make offers to buy or sell materials at various stages in the manufactoring process. These agents will be implemented in E so that it is impossible for clients to obtain an unfair advantage or to negatively impact the safety or efficiency of the plant.

Chemical Processing

The manufacturing plant must also be able to simulate and control a chemical processing system, that is able to break down and synthesize chemicals for use as raw materials. Raw materials need to be broken down into their constituent elements and recombined to form other types of molecules. To allow this, I will create a simple metalanguage based on chemical equations which specify what reactions will take place and under what conditions (temperature, pressure, etc.). This language will be used in two ways: to plan a sequence of chemical reactions that will form a desired molecule (to use rule-based terminology, backward-chaining), and to simulate a set of chemical reactions to determine the rate that it is produced and any by-products (forward-chaining).

Shipping Manufactured Products

Once we've manufactured our products, we'll need some way to get them to the customers. To do this, we'll use the existing Perl modules that integrate with shipping companies such as FedEx and UPS.

Web Interface