Sunday, March 3, 2013

Planned obsoles-C-ence

Here's some notes on how to put an epoch time stamp in your C/C++ program using the preprocessor macros __DATE__ and __TIME__


#include <time.h>



/* put this stuff in your function */


struct tm build_tm;
time_t build_t;

if (strptime(__DATE__, "%b  %d %Y", &build_tm) == NULL)

      return(); /* error! */
if (strptime(__TIME__, "%H:%M:%S", &build_tm) == NULL)
      return(); /* error! */

build_t = strptime(&build_tm);
  
if (build_t == -1)
      return(); /* error! */

return(build_t);

There you go.  Current epoch time is even easier:

#include <stdio.h>


time_t sec;

sec = time (NULL);

Assuming the user doesn't reset their system time just to run your program, you could use those two variables - build date and current date - to make decisions based on the age of the program.

- nzvyyx



Monday, December 24, 2012

The ZF 9 Speed Automatic - part 2

For fun and profit I've coded working simulations of automatic transmissions using in m, c, Simulink, and even Excel spreadsheets.  My latest effort is compiled C/C++ to make a GNU octave .oct file for the ZF nine speed transmission, with INI file initialization via a flex based lexer.  The fact that I'm posting this on Christmas Eve pretty much proves I have no clue how to take a real vacation.  On the other hand I'm sitting on the couch with my kid, and in guy terms that counts as interacting.

The basics are  working at a very basic level - open converter, locked in a gear - and I thought it'd be a good idea to keep some notes.  In particular the gear matrix was more tedious than I'd like... partly because I eschewed my beloved lever analogs in favor of free body analyses... but looking at the body analytic result I am left wondering if the lever analog was obscuring the symmetric gear matrix.  I'll present the result first, and then work up to it from first principles:

  • J is a diagonal matrix representing gear inertiae for the acceleration terms
  • N and f  are gear contact gains and forces 
  • S is gear speed constraints (e.g. tooth count ratios)
  • C is clutch torque application 
  • X is external torque application
  • H represents a "holding" clutch, D represents a "dragging" clutch

The ZF nine speed has four simple planetary gear sets, with a novel concentrically nested arrangement of the first two.  Gear ratio is determined by a combination of six clutches.  Any simple planetary has four "nodes:" a ring gear, sun gear, pinion gears, and the carrier for the pinion gears.  Generic torque to force balance equations can be expressed as:



In matrix form these equations can be expressed as:

The transmission has four gear sets with four nodes each, which would imply a total of sixteen torque:acceleration equations.  The total is reduced by rigid connections between gear components:
  • A1 and A2 and R3 are connected
  • A3 and R4 are connected
  • S3 and S4 are connected

If the converter turbine shaft is included in gear train analysis (which is probably a good idea) there are twelve independent torque:acceleration equations.  Clutches are named by which gears they control.

These equations can be expressed more compactly in matrix form, but to help understanding  I think it's better to take it one step at a time.

Here's the explicit inertia torque terms:
Vehicle inertia adds to output carrier inertia.  Vehicle inertia reflected to the output carrier is:


Here's the explicit gear:gear contact forces:
It may not be immediately obvious, but the speed constraints could be take as simply the transpose of the contact force matrix.

The clutch torque application matrix is:
In the case of the clutch torque (if you're keeping track of the meaning of the matrix rows), it is fairly obvious the speed constraints associated with clutch torque actions are simply the transpose of the torque matrix.
The actions of holding clutches should be moved to the acceleration/gear contact force matrix.  Dragging clutches (or controlled slip clutches) remain with the externally applied torques.  

Last, the externally applied torque matrix, which is fairly boring:
That's all you need for gear analyses.  For input torque I added an open converter using simple K factor and torque ratio lookups, and for output torque I used estimated road load torque (reflected to the output carrier through the axle).  Add water, compile with mkoctfile, debug, debug some more and eventually I had a simple torque converter/transaxle simulation that runs 100 faster than real time!


- nzvyyx



Sunday, August 26, 2012

Linux - associating TeX files with TexMaker

I write a lot of scripts to reduce data from .mdf files into .tex files and then into a .pdf report, formatted for ASME standards.  
If I really trust my processes, I call pdflatex to generate the .pdf.  That's rare.  Almost all the time I'm adding something to the report or developing a new analysis, so, being paranoid, I look at the .tex output TexMaker first.  TexMaker is a free & GPL'd cross platform TeX tool that will compile your .pdf with a button click.

Ubuntu didn't have an option to associate .tex files with TexMaker, which means double clicking a .tex file launched my default text editor instead... not what I wanted.  Here's how to get the association working:

1.  create a texmaker launcher by creating the file /usr/share/applications/texmaker.desktop:

[Desktop Entry]
Encoding=UTF-8
Categories=Office;Programming;
Comment=LaTeX development environment
Comment[fr]=Environnement de développement LaTeX
Comment[pl]=Åšrodowisko edutorskie LaTeXa
Exec=texmaker %U
GenericName=LaTeX Editor
GenericName[fr]=Editeur LaTeX
GenericName[pl]=Edytor LaTeXa
Icon=texmaker
MimeType=text/x-tex;
Name=Texmaker
Terminal=false
Type=Application

2.  add texmaker as a gui-clickable option by editing the file /home/<you>/.local/share/applications/mimeapps.list:
text/x-tex=texmaker.desktop;shotwell.desktop;totem.desktop;

3.  then, via nautilus (my usual gui file manager), associate texmaker with .tex files. 
Right click... Open With... Other Application:

Worked for me, hope it'll work for you too.

- nzvyyx




Friday, July 27, 2012

The ZF 9 Speed Automatic - part 1

Last March Honda announced they'd venture into the new ZF nine speed automatic.  
One nice thing about gears is that you can make a decent estimate of the ratios simply by measuring how big they, relative to each other.  All you need is a good cross-section or cutaway view, a plot digitizer, and some patience.

ZF will give you the ratios and a stick diagram in the .pdf link above, but I've always preferred lever analogies.  Here's what I came up with:











- nzvyyx

Sunday, July 22, 2012

Notes on Connecting to SQLite from Base

 SQLite has some advantages over MySQL (which I had been using).
  • SQLite database files are byte-for-byte identical regardless of operating system
  • the "amalgamation file" makes it easy to embed SQLite into another program.  This becomes a big deal when you swap computers.
  • it is inherently more distributed, because it creates local files on demand
If you're a single user (like me) then I'd add:  
  • it doesn't require a user name or password.  
That's probably an unacceptable risk in an enterprise environment, but I'm just one guy.  SQLite also uses some unique language and for data combination it is less powerful than some of the other big name SQLs.  My prediction is you'll end up using it to simply serve data to other applications, which will in turn manipulate or visualize the results.  Philosophically that's similar to other *nix programs so some people might say it's a good thing.

I connected SQLite to LibreOffice's database application under Ubuntu with an open database connector (ODBC), which calls drivers.  Setting the connection up is done in the opposite order:  drivers, then connector, then Base application.

1.  Get the drivers:

sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc

2.  Get the connector.  
You might already have it; check for it:

dpkg -l | grep unixodbc 

If it doesn't show up, you can install it:

sudo apt-get install unixodbc

After the install, run it as root to add an SQLite driver.

sudo ODBCConfig

Select the Drivers tab (I've already added the drivers... your tab might be empty):


Click the Add button and fill in the information.  Your result should look something like this:


Next, I quit the connector to re-open it as a normal user.  My theory was I wanted to add my specific database file for normal, non-root use and I'd do that as a normal user.  

At this point an actual SQLite database file is required.  It can be empty, but it has to exist.  If you don't have one, here's how to make a simple one so you can practice filling out the next forms.  Open a terminal and start SQLite:

sqlite3 dummy.db

From the SQLite prompt, create a table:

sqlite> create table dummy (id primary key);
sqlite> .quit


That drops an SQLite database file called "dummy.db" in your current directory.  ODBC and Base will be able to work with it.  My database file was called "OpenItems."

Start the connector again as a normal user (no "sudo"):

ODBCConfig


On the User DSN tab, click the Add button to add your database file.  Again, your window might be blank at this point; I've already added mine:


From the Add, fill out the database information:


If you got this far, you've pretty much conquered the connection!  Congratulations.

3.  Point LibreOffice Base at the data connection  (almost done now!)

Select an ODBC database:


Click Next >> and Browse to find the connection you just created in ODBCConfig:


Hit OK, then Next >> again to get to the connection test.  SQLite doesn't require a user name or password, so just click Test Connection.  If everything worked you'll see some good news:


From there on out, it's as if you had created the database inside LibreOffice.  
Click Next >> and decide on database registration etc, and in a couple of windows you should see a the Base interface using your SQLite database.  But using Base is another story - you're connected, so this story is done.  Congratulations!

- nzvyyx



Sunday, May 27, 2012

femm in Ubuntu under Wine

Years ago I stumbled across femm, "finite element method magnetics" by David Meeker.  It's a sweet little magnetics solver with good looking results visualization, but alas, at the time it was only available for Windows.  I used it on my work machine - when I worked for companies that would let me do work, that is.   When I made the personal switch to Linux, I had to bid femm a fond farewell from my personal machine.


I have few regrets about my decision to use Ubuntu Linux.  The lack of femm was on that short list.  Fortunately, Dr Meeker & company have continued to work on their program over the years, and I find now that femm runs under Wine, the windows compatibility translation layer for POSIX-compatible operating systems.  Wine, you say?  Ok...


The internet bristles with "I hate Wine" types of comments.  Perhaps that is to be expected...

  • the tinfoil-hatted Linux fanboys love to hate on Winblow$ stuff
  • the Windows crowd loves to sneer at us Linux freetards
  • Wine is a half-breed orphan seeking for the absent love of an adoptive parent
Personally, as long as it's free and open source I'm fine with it.  Heck I'd probably stop dis'ing   Windows if they'd just write specs; it was the constant churn, triggered by the Windows 7 "up" grade, that really ticked me off.


If you plan to do computer stuff for many years, a proprietary OS with no specification is simply a bad idea.  Specs assure you that you'll be able to read your own files later on.  Today, POSIX is the only standard I know of.  The good news is you can sign up with the Open Group and actually read those standards.  Not nerdy enough to worry about specs?  I understand, and honestly most people should be like you...  but if you're not smart enough to recognize the need for specs, then you should not be in charge of the I.T. department.


Enough ranting for now.  Here's a screen grab of femm-wine-ubuntu in action.  The triangle fill function is erratic but flux density shows up well enough for me without it.   



- nzvyyx

Sunday, November 6, 2011

Connecting MySQL to GNU Octave in Ubuntu

In my little world, this is, officially, A Very Big Deal (tm).  
MySQL features a rich API.  GNU Octave has a database package. 
Unfortunately I don't know API from DPI, and Octave's db package pretty much doesn't work for anybody (including me), according to my google results.


So I wrote my own.. it was:

  1. my first foray in .oct file creation, C++, and APIs
  2. successful!  thanks largely to the extensive help available all over the internet

Regardless, I'm disproportionately pleased with myself.  


Note you'll need both octave and MySQL header files, and my goal was to get a .oct that could retrieve data FROM the database, which is different than stuffing data TO the database.


The code below takes in four strings, queries MySQL, and if the query was successful, returns a cell variable to octave.

/*
 * SQL2m.cpp
 *
 *  Created on: Nov 5, 2011
 *      Author: nzvyyx
 */


#include "/usr/include/mysql/mysql.h"
#include "octave/oct.h"
#include "octave/Cell.h"
#include <string>
using namespace std;


#define NUM_INPUTS_REQUIRED (4) // 0 is file name, 1: user name, 2: password, 3: database name, 4: SQL query


#define  NoError 0
#define  Error_NoInputs (NoError + 1)
#define  Error_SQL_QueryError (Error_NoInputs + 1)
#define  Error_UnexpectedTermination (Error_SQL_QueryError + 1)
#define  Error_UserNameNotAString (Error_UnexpectedTermination + 1)
#define  Error_UserPasswordNotAString (Error_UserNameNotAString + 1)
#define  Error_DatabaseNotAString (Error_UserPasswordNotAString + 1)
#define  Error_SQL_Query_NotAString (Error_DatabaseNotAString + 1)
#define  Error_NoOutputs (Error_SQL_Query_NotAString + 1)
#define  Error_SQL_CnxnFailed (Error_NoOutputs + 1)


#define  *ErrorMsgs[] = {
    ">> SUCCESS <<",
    "not enough inputs, expected (name, password, db_name, SQL_query)",
    "SQL query error",
    "unexpected program exit",
    "non-character user name",
    "non-character user password",
    "non-character database name",
    "non-character SQL query",
    "no output assigned",
    "SQL failed to connect",
    NULL
};


char *server = "localhost";
char *username = NULL;
char *password = NULL;
char *database = NULL;
char *SQL_query = NULL;
string str;
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long long totalrows, numfields;
int _n;
octave_idx_type _row, _col;
octave_value_list  retval;


DEFUN_DLD (SQL2m, args, nargout,
        "[SQL_result] = SQL2m(database, user_name, user_password, SQL_query)")
{
  if (nargout < 1)
  {
    retval(0) = ErrorMsgs[Error_NoOutputs];
    return retval;
  }
  if (args.length() < NUM_INPUTS_REQUIRED)
  {
    retval(0) = ErrorMsgs[Error_NoInputs];
    return retval;
  }
  for (_n = 0; _n < NUM_INPUTS_REQUIRED; _n++)
  {
    if (!(args(_n).is_string()))
    {
      retval(0) = ErrorMsgs[Error_UserNameNotAString + _n];
      return retval;
    }
  }


  str = args(0).string_value();
  username = new char[str.size() + 1];
  strcpy(username, str.c_str());
  str = args(1).string_value();
  password = new char[str.size() + 1];
  strcpy(password, str.c_str());
  str = args(2).string_value();
  database = new char[str.size() + 1];
  strcpy(database, str.c_str());
  str = args(3).string_value();
  SQL_query = new char[str.size() + 1];
  strcpy(SQL_query, str.c_str());


  conn = mysql_init(NULL);


  if (NULL == mysql_real_connect(conn, server,
      username, password, database, 0, NULL, 0))
  {
    retval(0) = ErrorMsgs[Error_SQL_CnxnFailed];
    return retval;
  }


  if (0 != mysql_query(conn, SQL_query))
  {
    retval(0) = ErrorMsgs[Error_SQL_QueryError];
    return retval;
  }


  res = mysql_store_result(conn);


  totalrows = mysql_num_rows(res);
  numfields = mysql_num_fields(res);
  Cell DATA(totalrows, numfields);


  _row = 0;
  while (row = mysql_fetch_row(res))
  {
    for (_col = 0; _col < numfields; _col++)
    {
      DATA(_row, _col) = octave_value(row[_col]);
    }
    _row++;
  }


  mysql_free_result(res);
  mysql_close(conn);


  return octave_value(DATA);
}

Here's a simple octave .m file to build the .oct file  & test for  results.
You'll need to a MySQL running, and the dummy placeholders for user name, password, etc need functional values from you.
% BuildAndTestSQL2m.m
clear all; clc; 

% build required MySQL API:
% $ sudo apt-get install libmysqlclient-dev
%
% directories given by command line:
% $ mysql_config --cflags
% and
% $ mysql_config --libs
mkoctfile  -I/usr/include/mysql  -L/usr/lib/mysql -lmysqlclient  SQL2m.cpp 

disp("change this script to specify your username, password, database name and SQL query !")
username = 'user';   
password = 'password';
dbname = 'dbname';
SQL_query = 'select field1, field2 from table';

[status, output] = system('rm SQL2m_tests.txt');
diary SQL2m_tests.txt
help SQL2m
% test with combinations of insufficient argument counts
SQL2m()
results = SQL2m()
results = SQL2m(username)
results = SQL2m(username, password)
results = SQL2m(username, password, dbname)

% this should return a cell array - success!
results = SQL2m(username, password, dbname, SQL_query)
diary off