# Lecture 21 - Anthropomorphic Programming

## Public Service Annoucements

1. Exam: 9.00, August 8
2. I now have back my document creation tools. Assignments will start to be more uptodate.

# Calibration

## Constant Jerk

Third order curve for position, second order for velocity, linear acceleration. We usually go one better, and try to minimize jerk over the whole journey.

## Minimize Jerk

Acceleration/Deceleration is continuous

The result is a fourth order curve in position, third order in velocity, which is what you try to achieve when you drive.

## Is it Worth Having an Explicit Function?

#### Benefits

1. You can calculate position explicitly without having to do numerical integration.
• Euler integration is unstable because of accumulating error.
2. You can calculate the parameters of a function with less measurement. How?
• Start at x = t = 0, which assumes that you get the same function regrardless of position on the track and time of day.
• Check deceleration inverse of acceleration?
• &c.

The idea is that the person who programmed acceleration/deceleration into the train was lazy, so there's probably one basic function used over and over again

#### Drawbacks

1. You need to check that the functional form you have is the right one, or a right-enough one.
2. For practical purposes small look-up tables may be perfectly adequate.

## Finding Parameters for an Explicit Function

We are trying x(t) as a fourth order polynomial in t.

• The command to change speed occurs at t1. At t1
• x(t1) = x1,
• v(t1) = v1, and
• a(t1) = 0.
• The velocity change it complete at the unknown time t2. At t2
• x(t2) is unknown,
• v(t2) = v2, and
• a(t2) = 0.

It is easiest to express the polynomial in terms of y = ( t-t1 )/(t2 - t1). Why?

Then write

• x(t) = (A/24) y^4 + (B/6) y^3 + (C/2) y^2 + D y + E
• v(t) = [ (A/6) y^3 + (B/2) y^2 +C y + D ] / (t2 - t1)
• a(t) = [ (A/2) y^2 + B y + C ] / (t2 - t1)^2

and use the equations above to solve for the five parameters in terms of t1. Then, you need only measure t1 to know the relevant kinematic functions.

We discussed how to measure t1 in the second step.

### Testing the Measured Values

You test the measured values by

• driving the train around the track,
• predicting when it will arrive at a sensor,
• measuring when it actually arrives at the sensor, and
• calculating the disagreement.

When you have the disagreement which is, by definition non-zero, but which may be measured as zero, you have to decide the cause:

• random error,
• incorrect measurement,
• incorrect parameter estimation,
• incorrect implementation of a correct function, or
• incorrect function.

Have fun.

# Anthropomorphic Programming

We all, even most programmers (!), have effective intuitions about human relations

• We use them to `understand' pets, which means attributing to them
• goals
• knowledge
• capability
• emotions
• Why not programs?
• apply them to intertask relationships

• Understand them by thinking about them as if they have capabilities and goals.
• When you are developing something like the train application you are defining roles and relationships

Why do servers need attendant tasks?

• What happens if a server calls AwaitEvent?

## 1. Proprietor with a Notifier

Proprietor `owns' a service, which usually means a resource.

• Think of the owner at the counter of an old-fashioned store
• `store' means where things are stored;
• it's in the back and only the proprietor can access it.
• Many clients come to the front and are processed one by one.
• Comment. The modern `store' is considered by many to be the most important innovation of the 20th century. (Yes, including the transistor, the computer, quantum mechanics, antibiotics, etc.) A whole lot of work that was previously done by store personnel is now done by the client. This is possible only because extensive codes of conduct have been internalized by clients. (That is, a large collection of new behaviour norms have been created and propagated.)
• Somebody has to sit out back waiting for the truck and bringing it to the proprietor

Kernel is handling hardware in this example

#### Notifier Code for a UART

• Initialize
```Receive( &serverTid, eventId );
```
• Work
```FOREVER {
data = AwaitEvent( eventid );  // data includes event type and volatile data
switch( data.event-type ) {
case RCV_INT:
Send( serverTid, {NOT_RCV, data.byte}, ... );
break;
case XMT_INT:
// test transmitter, turn interrupt off and on?
Send( serverTid, {NOT_XMIT}, byte );  // byte is to be transmitted
store( UART..., byte )
break;
default:
ASSERT( "This never happens because our kernel is bug-free." );
}```

#### Proprietor/Notifier Code for a UART

• Initialize
```// queues & fifos
notifierPid = Create( notifier );     //Should notifier code name be hard coded?
Send( notifierTid, MyTid( ), ... );   //On return notifier is known to be okay
RegisterAs( );                        //On return requests can begin.
```
• Work
```FOREVER {
requesterTid = Receive( request, {request-type, data} );
switch ( request-type ) {
case NOT_RCV:
enqueue( rcvfifo, data );
if ( ! empty( rcvQ ) ) Reply( dequeue( rcvQ ), dequeue( rcvfifo ) );
break;
case NOT_XMIT:
enqueue( xmitQ, requesterTid );
if ( ! empty( xmitfifo ) ) Reply( dequeue( xmitQ ), dequeue( xmitfifo ) );
break;
case CLIENT_RCV:
enqueue( rcvQ, requesterTid );
if ( !empty( rcvfifo ) Reply( dequeue( rcvQ ), dequeue( rcvfifo ) );
break;
case CLIENT_XMIT:
enqueue ( xmitfifo, data );
if ( ! empty( xmitQ ) ) Reply( dequeue( xmitQ ), dequeue( xmitfifo ) );
break;
default:
ASSERT( "Never executed because notifiers and clients are bug-free." )
}
}```

#### Notes

1. Notifier is usually of higher priority than server
• Notice the early reply in the proprietor
2. When, and how, do interrupts get turned on and/or cleared?
3. Who coordinates hardware ownership?
4. We have made the code
• exhibit duality explicitly
• easy to break into parts
• easy to extend

## 2. Using a Courier

Simplest is best

#### Transmit Notifier Code

• Initialize
```Receive( &courierTid, ... );
```
• Work
```FOREVER {
data = AwaitEvent( eventid );
}```

#### Transmit Courier Code

• Initialize
```Receive( &serverTid, notifierTid );
Send( notifierTid, ... );
• Work
```FOREVER {
Send( notifierTid, {data} );
Send( serverTid, {req}, {data} );
}```

#### Transmit Proprietor Code

• Initialize
```// queues & fifos
notifierTid = Create( notifier );
courierTid = Create( courier );
Send( courierTid, notifierTid, ... ); // On return courier & notifier are known to be okay
RegisterAs( );                        //On return client requests will begin.
```
• Work
```FOREVER {
requesterTid = Receive( request, {request-type, data} );
switch ( request-type ) {
case NOT_XMIT:
enqueue( requesterTid, xmitQ )
if ( ! empty( xmitFifo ) ) Reply( dequeue( xmitQ ), dequeue( xmitFifo ) );
break;
case CLIENT_XMIT:
enqueue ( xmitFifo, data );
if ( ! empty( xmitQ ) ) Reply( dequeue( xmitQ ), dequeue( xmitFifo ) );
break;
default:
ASSERT( "..." );
}
}```

#### Notes

This gets you through a bottleneck where no more than two events come too fast.

Remember that all the calls provide error returns. You can/should use them for error recovery

• static error recovery: debugging
• dynamic error recovery: at run time

Another possible arrangement for task creation

• Server creates the courier
• Couier creates the notifier

Another possible arrangement for initialization