Robotic Workcell

April 13, 2007

Life has been quite hectic lately but I am shooting for a second release of SIMPACK. I have spent time fixing bugs and adding a new package – robotics. This video shows a robotic workcell simulation I am working on.

3D Engine Animation

November 1, 2006

I stumbled upon this video while reading auto blogs. Very cool and educational. I have seen it before but couldn’t get a copy. I am keeping a link here just for my reference.

Source Code Now Available

September 18, 2006

It was decided in the very beginning that this is an open source project since I benefited so much from other open source code. However, it still takes me considerable time to clean up the source before I can open it up. I started to use CVS to do version control, and then later found out SVN is now a more popular method. Like many other open source projects, I chose SourceForge to host it. I picked BSD license because it is less restricted. The result is far from perfect, but I finally managed to let it go. If you are interested in anything you see in this blog, check out the source code!

Box stacking in a bowl

September 16, 2006

Demonstrates collision between convex and concave geometries.

Single Valvetrain Simulation

September 14, 2006

At first glance, this is a very simple mechanism. Put a convex-convex contact joint between the cam and tappet and a spring force to restore the tappet to the original position. However, this leads to a complete overhaul of my collision detection scheme. The problem is between the valve seat and valve. I want a more realistic concave-convex type collision between them. How to handle a concave geometry? I have treaded the territory of signed distance map before and accumulated enough frustration. In addition, it does not fit my fundamental work on the feature-based geometry. Convex decomposition? Some geometry is inherently concave, such as the inside of a cylinder wall. Moreover, I am reluctant to invest even more time on the uncharted sea of collision detection. I need something simple and effective.

My solution is to have three types of geometry:

  1. Convex – a convex polytope or a convex surface patch that is not limited to a polyhedron.
  2. Complex – a triangle soup. A concept that is easy for me to grasp when I studied RAPID.
  3. Composite – a thing that is composed of convex and complex.

There is no primitive geometry such as box, sphere, or cylinder. Everything is built from triangle meshes. A non-polyhedron convex opens the floodgate to bugs roaming around my code. I spent a lot of time debugging but I think there is still some dormant bugs which I have not uncovered. There is no automatic schemes for convex decomposition. The user is responsible for identifying the convex parts in a composite. If it is very difficult to identify a part in a composite, that part deserves to be called complex. These geometries are supported by three colliders:

  1. ConvexConvexCollider – the fundamental element in the hierarchy that uses DEEP. Free edges cause me the most trouble.
  2. ComplexConvexCollider – the triangle soup is culled by an AABB tree. A single triangle and a convex collision is handled by ConvexConvexCollider.
  3. CompositeCompositeCollider – peels down the hierarchy to employ ConvexConvexCollider and ComplexConvexCollider.

Complex and complex collision is not allowed since I don’t know how to determine the penetration depth between two colliding objects when they are represented by two triangle soups. I am aware that ODE trimesh manages to do just that but it is not very reliable.

The model geometry is taken from ADAMS Engine, but the spring geometry is constructed by java code from j3d.org. Obviously, there is more to accurately model a spring than just to assign the spring stiffness. I didn’t include the spring details in the model and it seems lack of accuracy. But that work is left for the future improvement.

HalfEdge.pair

August 12, 2006

To my startling I paid no attention to HalfEdge.pair when I decided that a triangle mesh should be generalized to a polytope instead of a polyhedron. HalfEdge.pair could be null and should be checked when traversing all the edges emitted from a vertex.

BoxStack Milestone

June 29, 2006

I set my goal back in January 2005 to implement my own BoxStack. Finally, 1.5 years later, I declare a milestone for this project. The initial idea was somewhat unrealistic. The current implementation employs Java3D for graphics, GJK for collision detection, DEEP for estimating penetration depth.

Embeded Google Video

June 26, 2006

Google video now directly provides html to embed a video. Here is my cranktrain simulation video.

Java Web Start for Cranktrain Simulation

June 26, 2006

I have put out a Java web start version of cranktrain simulation for a while. The tricky thing about Java web start is loading a data file. After reading all the available document on the web (which is very little), I learned that ClassLoader is necessary to invoke files in the JAR file.

ClassLoader cl;  crankShape = Trimesh.loadObj(cl.getResource("images/crank.obj"));

I used Java3D ObjLoader class to load the OBJ files. However, I am still confounded about how to directly read a text file in a web start app. The combustion force file was stripped from the current web start version of the crank model until I figured out a way to do it.

Make Movies

June 6, 2006

Step 1:

Do screen grab at every frame and encode the captured image to JPEG format. The solution could come from Java 3D but using Robot seems to be a more stable method (from I read from different forums).

     try {
       //setLocationRelativeTo(null);
       Rectangle win = getBounds();
       Robot robot = new Robot(getGraphicsConfiguration().getDevice());
       BufferedImage image =
         robot.createScreenCapture(new Rectangle(win.x, win.y,
                                                 win.width, win.height));
       FileOutputStream out = new FileOutputStream("image" + jpgCount + ".jpg");
       JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
       JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image);
       param.setQuality(0.9f, false);
       encoder.setJPEGEncodeParam(param);
       encoder.encode(image);
       out.close();
     } catch(AWTException e) {
       e.printStackTrace();
     } catch(IOException e) {
       System.err.println("I/O exception!");
     }
     jpgCount++;

Step 2:

Stitch the still images into a movie using ffmpeg:

or

Bit rate is probably the main factor for quality. Choose wisely. The default bit rate of 200 yields low quality result.