XML

kent logo

CO538 Anonymous Questions and Answers Keyword Index

This page provides a keyword index to questions and answers. Clicking on a keyword will take you to a page containing all questions and answers for that keyword, grouped by year.

To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.

Keyword reference for mars

2012

Question 52 (2012):

Submission reference: IN2315

How much commenting should we put in our code for Life on Mars?

Answer 52:

See Question 30 (2001) for the kinds of comment that should not be made!

Otherwise, you should summarise the purpose of each program entity (e.g. PROC or PROTOCOL) in comments just above its header. Ideally, this should conform to the syntax for occamDoc documentation used in, for example, your q4.occ and q7.occ starter codes and PROC draw.hit.line in the mars-sim.occ file. However, free-format comments will be fine.

In the body of a PROC, 'clever' code must be explained – anything whose purpose would not be obvious to a reader familiar, in this context, with occam-pi. For example, if there is special code to eliminate a danger of deadlock but not otherwise contributing to the purpose documented above the header, you must explain why it's there and how it does its job. It's essential to make your code understandable to readers. A base reason would be that they might be marking it! But one of those readers might be you in a few weeks time and, just because you understood it once, this does not mean you will understand it in the future. Obscure code is, in practice, worthless ... regardless of whether it works or is efficient. Obscure code cannot be maintained. Code that cannot be maintained will be thrown away.

Diagrams are an important part of the documentation of occam-pi systems. Remember to submit a process network diagram (or diagrams) if you have used concurrency in your robot.control logic. This is needed even for networks that are temporary (e.g. for the duration of a turn, move, find or deploy), but not if the concurrency is very short-lived (e.g. a parallel input/output). Diagrams for temporary networks should be enclosed in a box labelled by the PROC that sets it up (with all its external channels) and some text (or number scheme) that indicates when it is set up and for how long it lasts.

Keywords: mars , comments , diagrams


Question 51 (2012):

Submission reference: IN2297

I'm currently stuck on Task 3 - finding the blobs.

Everything seems to work fine apart from one little thing - the bearings given are SOMETIMES incorrect.

... (Ed: rest of question hidden, as it gives too much away.)

Do you think you'd be able to identify what the problem may be?

Answer 51:

From your description (not shown in the question), your robot.control inputs from the camera? channel (seeking a BLOB with the required colour) only when the robot is stationary. That seems reasonable: you are trying to get a bearing on the BLOB and do not want to get an observation that happened whilst the robot was turning.

Unfortunately, you are receiving BLOB data observed by the camera during the preceding turn! During the turn, BLOBs may come into the field of view of the camera and the image processing software will send processed BLOB data (including their bearings at the time of observation) towards your robot.control process. Since no inputs are taken from camera? during this turn, that BLOB data is not lost (this being occam-pi) but held in buffers for delivery whenever robot.control does decide to take them. When your robot finishes its turn and inputs from the camera?, stale BLOB data will be seen. This is why the bearing information you are sending back to Mission Control is often wrong.

A real-time system must always make best efforts to take data from its sensors whenever available, even it it does not need (or has no time) to process them. If any of that data is buffered for later processing, care must be taken not to use that buffered data if logic requires that only fresh data is relevant.

For the robot.control component on Life on Mars, this means taking camera data and hazard data at all times, even when turning and moving. When turning or moving, the camera data can be discarded but the hazard data, of course, must be processed. Motor feedback data only happens when turning or moving, so can probably be ignored at other times (to be safe, though, it should be still be monitored). Ideally, the opr.req? channel from Mission Control should also always be monitored (for emergency or cancel messages, though this will not happen in this assessment scenario).

To monitor external inputs at all times, an elegant solution is to have monitor processes running in parallel all the time. Alternatively, if your code is sequential, use ALTs to process inputs from all sources, even when your primary focus is on just one (or two) of them.

Keywords: mars


Question 50 (2012):

Submission reference: IN2300

For the Life on Mars assessment, are we allowed to changed some of the robot.control channels to SHARED?

Answer 50:

Yes. But you will have to work hard on the mars-sim.occ file to let it compile. The channel that gets plugged into your robot.control needs to be declared with its writing-end SHARED. Now, mars-sim.occ caters for multiple robots on mars and provides arrays of opr.req and opr.resp channels back to its (simulated) mission.control process – for your assessment, the number of robots is set to 1. Unfortunately, the occam-pi compiler does not currently allow arrays of channels to be declared with SHARED ends – if you need them, you will need to investigate MOBILE CHAN TYPEs (from "Mobiles" slides 24 onwards, which have not been presented in this module and are not examinable). A simpler solution, however, would be to modify mission.control to a single pair of opr.req / opr.resp channel-ends whose other end (at the robots on mars) is SHARED.

If you do this, you will need to submit your revised mars-sim.occ file (along with mars-main.occ) plus adequate documentation (in both files) explaining your changes and the reason(s) why you made them. This is a lot of work.

Why do you want to make some of the robot.control channels SHARED? I know no good reason. Please read Question 49 (2012), where the questioner was having a technical problem for which a SHARED channel was raised as a possible solution ... but the real problem was some weak software engineering (low cohesion: putting too much functionality into a PROC) and over-engineering (result channels instead of reference parameters to return results). Maybe your problem is similar?

Keywords: mars , shared-channel


Question 49 (2012):

Submission reference: IN2295

I have a hazard.monitor process as suggested in the answer to Question 59 (2011) and that seems to be working.

For Task 3 of the mars assessment, I'm trying further parallelism. I have a turn.robot process in parallel with a find.blob, with a cancel channel between them. If find.blob finds the specified blob, it sends a cancel to turn.robot which stops its turn. I have a result process that receives results from both turn.robot (how much it turned) and find.blob (if it found the specified blob and, if so, the blob itself).

However, turn.robot is also used to respond to a turn command and has to send to opr.resp!. My result process also wants to send to opr.resp!. But the opr.resp! parameter given to robot.control is not SHARED, so I cannot run turn.robot, find.blob and result in parallel. If I put result in sequence and after running the other two in parallel, it compiles but, of course, gets stuck as soon as turn.robot and find.blob try to report their results to result which hasn't yet started!

Is there any way out of this impasse, please?

Answer 49:

You have two problems.

First, see Question 55 (2011), the paragraph in the answer starting: "From the software engineering principle of cohesion ...". That was talking about a move process, but it applies to turn as well. Task 4 will need lots of turns and you'll want to reuse your turn.robot ... but you won't want it reporting on opr.resp! each time! Do what it says there: remove the opr.resp! parameter from turn.robot and promote your local variable that is accumulating the ticks to a reference parameter. Then, whoever invokes turn.robot will get the ticks it found (when turn.robot finishes) and can report, or not, to opr.resp! as needed. Now, the need for its ticks-reporting channel has gone, so get rid of it.

In general, an initialisation channel that just delivers one value to a process should be replaced with a VAL parameter with that value. Similarly, a reporting channel that delivers only one final report should be replaced by a reference parameter to which the report value is assigned.

[Side-note: check out the answer to Question 58 (2010) for the concept of RESULT parameters. We've not presented them in the course, so they are not examinable. However, they are very simple to understand and use and give added safety (against programming error) and elegance to the recommendation in the second sentence of the preceding paragraph.]

So, get rid also of the reporting channels in find.blob. Replace them by promoting the local variables holding the report values (whether it found a blob with the specified colour and, if so, the blob itself) to reference (or RESULT) parameters. Now, like the changed turn.robot, it has no need to communicate with your result process via a channel and no need, therefore, for that result process to be running in parallel with it.

Now, put result in sequence and after running the other two in parallel, declaring and passing variables for ticks, found-the-blob and blob (as needed by result and the other two). This time, it compiles and result gets the information it needs. Indeed, now that result no longer need to input result data, its code should be trivial enough to write in-line (without a PROC).

Don't forget that, with this modified turn.robot, the code for responding to a turn command (from opr.req?) needs a little extra.

Things should work better now.

You're not there yet though. If a blob is sought that is not in vision range even after a full turn, does your find.blob keep waiting? If so, your response to a find command will never finish – the robot will do a complete turn and nothing else will happen.

Just as your find.blob cancels turn.robot if it finds a blob, so your turn.robot should cancel find.blob if it completes a full turn (plus a couple of seconds to allow for camera processing of the image in its final position). But there's deadlock lurking if they both commit to cancelling each other around the same time – this needs to be avoided. There is a simple solution, but we leave it to you to find.

Keywords: mars , shared-channel

Referrers: Question 50 (2012)


Question 48 (2012):

Submission reference: IN2294

I'm trying to do Task 3 of Life on Mars, but I'm having issues with the timeout - specifically, the actual time it waits is often absurdly long, sometimes minutes.

    tim ? t
    PRI ALT
      tim ? AFTER t PLUS CAMERA.SCAN.TIME     -- 2 seconds
        ...  turn robot 90 degrees and increment a 'count'
      BLOB b:
      camera ? b
        ...  if 'b' has the sought colour, set 'searching' FALSE & report to mission control

It doesn't matter whether there are any blobs in view or not, and recompiling or rerunning doesn't produce consistent results.

Answer 48:

You don't show the enclosing loop. From what you show, I'm guessing something like:

    WHILE searching AND (count < 4)
      SEQ
        tim ? t
        PRI ALT
          tim ? AFTER t PLUS CAMERA.SCAN.TIME     -- 2 seconds
	    ...  turn robot 90 degrees and increment a 'count'
          BLOB b:
          camera ? b
	    ...  if 'b' has the sought colour, set 'searching' FALSE & report to mission control

Now, suppose a BLOB is reported on camera but not with the sought colour; then execution goes round the loop and the timeout is reset for another 2 seconds. The 'mandelbot' rock formations are reported (by the image processing processes running in parallel with your robot.control) as potential BLOBs down the camera channel, but will have different colours to the BLOBs sought by mission control. Further, so long as a potential blob is in view, it will continue to be reported down camera at least once every CAMERA.SCAN.TIME. In practice, CAMERA.SCAN.TIME is a bit generous and blobs may be reported a little more often than that.

So, if the sought BLOB is not in vision but something else is and that something gets sent down camera before your code times out, the potential blob is ignored and your timeout is reset for 2 more seconds. This can carry on indefinitely, the timeout never happens and your robot in never told to turn!

See "Choice" slide 46 for the right way to set the timeout times.

Keywords: mars , timers


Question 47 (2012):

Submission reference: IN2273

Hi,

I am trying really hard to implement the move process for the mars assignment and have got stuck with what is happening in my code...

I've been trying to follow advice in Question 55 (2011).

I have implemented a nested replicated ALT (as suggested) and believe before my loop gets to run I check that you can move by looking at the hazard array (as suggested) but for some reason my code gives unexpected behaviour:

When you first move it will move up till a hazard is detected, eg move 1000 moves 180 and stops. Subsequently, I would have thought telling it to move again would cause it to not move forward anymore (as it would check the sensors, which would discover a hazard and never allow the "moving" Boolean to be set TRUE and thus the robot not move). However, subsequent calls to move always allow the robot to move but with smaller amounts. You can keep repeating this until the robot moves all the way through a hazard which is clearly wrong.

I know this must be something to do with the way I am polling the hazard channels in my first bit (where I check before I drive) but I can't see how I would structure this to not happen. The Hazards are prioritized over the SKIP guard so surely, if a hazard exists, the robot shouldn't move!

My code:

    PROC robot.move (...)
      ...  (Ed: code hidden)
    :

Answer 47:

A hint to your problem is the first sentence in the last paragraph of your question. As we've said before, polling is usually the wrong thing to do. It certainly is wrong here. For one thing, you poll all four hazard channels and take a response from only one of them - or SKIP if none were sending. So, one might be reporting a zero level and the other three screaming 10 (DANGER!) ... your poll may take the one reporting zero, ignore the other three and issue the drive.forward command to the motor.

However, the Mars web page says:

"You will receive communications on these channels only when and if the value changes."

So if the vehicle is stationary, nothing will be coming down those hazard warning channels – even if you are facing a brick wall! Polling the hazard channels will see nothing.

The hazard warnings would have been sent as your robot was approaching the obstacle. Your robot control should have remembered the warnings.

As the answer to Question 55 (2011) says, the simplest way to remember is to have a dedicated process to monitor the hazard channels at all times and maintain the information on current hazard levels. This runs in parallel with the process doing the move. The latter can check hazard levels before starting the motors by asking the former.

The move process could continue to do this as it moves, by asking after each click motor.feedback. This is not very efficient and may miss a hazard warning if motor feedback signals were ever delayed for some reason. Better would be to ask the hazard process to let the move process know if a hazard (significant to its direction of movement) has been spotted – then the move process just ALTs between a warning channel (from the hazard process) and the motor feedback channel. If the move completes with no hazard warning, the move process needs to cancel its request to the hazard process. Careful: there is a danger of deadlock here that must be avoided.

On the other hand, if your control logic is serial, the move PROC must ALT between motor feedback and all hazard channels. But it must initially know the current hazard levels and, when finished, return them. Clearly, this must be through a reference data parameter.

Final thought ... if using serial logic ... does your turn PROC need to do the same?

Keywords: mars

2011

Question 71 (2011):

Submission reference: IN2104

my hazards dont seem to be working. currently, i have a process that takes an array of hazard channels, and stores the values that come in on each of them using a replicated alt. it then sends that value out, zlong witha boolean variable to detrmine whither it is the front or the back set of sensros to any prcess that is connected to it, such as my move rpocess. the move prcess cheks the boolean to see if the sensor data is related tot he direction it is traveling in, if it is, then it should stop the rover. but it doesdtn seem to be. what would be the best thing to do to solve this?

Answer 71:

How often does your move process listen on the channel from the process you describe that forwards specific hazard warnings? Does it listen inside a loop in sequence, or in parallel, with listening to the motor feedback channel? If so, that is the same mistake as reported in Question 67 (2011) (para starting: "You also wait ...") and Question 55 (2011) (para starting: "There are other problems though ..."). Your problem is also similar to Question 58 (2011).

Please read carefully through those Q&As.

Keywords: mars


Question 70 (2011):

Submission reference: IN2103

all the tasks have been complteded, thing is, i never get a message back on the terminal. the robot moves/turns etc sucessfully, but then does nothing. im sednign the correct value on the operator respone channel, and the right hting happens on the screen. but just no messages on the termianl. any suggestions on how to fix this?

Answer 70:

If you send a correct message on the opr.resp! channel, it will be relayed to your screen. For example, just try sending:

    opr.resp ! turn.complete; 42

as an immediate response to any turn request (i.e. without actually doing anything!) to see the response relayed to your screen.

If your program turns the robot successfully (as seen in the animation window) but your screen shows nothing, it's because your code has not reached the line in your code where you send your response to opr.resp!. Try adding log! messages – e.g.

    out.string ("===> turn complete, about to send response ...*c*n", 0, log!)

just before your opr.resp! message. Do you see that log! message? If not, put in more log! messages further back in your code (e.g. into the loop in your turn logic ... does that loop ever exit?).

Time is short, but hope this helps!

Keywords: mars


Question 69 (2011):

Submission reference: IN2102

Hello, With regards to Question 63 (2011), what kind of inefficiency will be penalised?

Is it code-wise or in solving the task? I make a ridiculous number of sweeps over the same territory. My robot has amnesia.

Answer 69:

Code-wise. We will penalise programming inefficiencies that are needless ... like busy-polling (see the answer to Question 68 (2011)), recalculating the same thing more than once, testing variable values that don't need testing, searching more of an array than needs to be searched, etc.

Strategic inefficiencies in the plan for solving Task 4 will not be penalised ... so long as they are not too gross and easily avoided. A strategy that is infinitely inefficient (i.e. has no chance of success) will, of course, be penalised. A strategy that takes a long time, but gets the rover roughly to the required deployment point, is fine!

Keywords: mars


Question 68 (2011):

Submission reference: IN2101

This is in response to my earlier Question 59 (2011). I have included some code that probably requires omission.

So far I have implemented it where hazard.monitor works in a client-server fashion, and move continuously checks the values until it reaches the destination. However I think I am polling? There doesn't seem to be an obvious solution to implement it in a non-polling fashion.

    PROC move (VAL INT move.mm, BOOL success, INT driven.mm,
	       CHAN P.MOTOR.CMD motor.cmd!,
	       CHAN P.MOTOR.FEEDBACK motor.feedback?, 
	       CHAN BYTE log!,
	       CHAN BOOL hazard.enquire!,
	       CHAN [HAZARD.SECTIONS]INT reply?)
      
      INITIAL BOOL forward, continue, hazard.detected IS FALSE, TRUE, FALSE:
      [HAZARD.SECTIONS]INT hazard.value:
      SEQ
	success := FALSE
	...  get latest hazard values (from hazard.monitor process)
	...  if no hazards in movement direction, issue drive command to motors
	IF
	  continue    -- i.e. drive command was sent
	    
	    CHAN BOOL stop.motor.monitor, stop.check.hazard:
	    PAR

	      SEQ
		...  loop that listens on 'stop.motor.monitor?' and 'motor.feedback?'
		     channels.  If anything on 'stop.motor.monitor?', exit loop.
		     If anything on 'motor.feedback?', accumulate tick counts in
		     'driven.mm' and exit loop if 'move.mm' is exceeded.
		stop.check.hazard ! FALSE
	      
	      ...  loop that polls 'stop.check.hazard?' (from above process) and
		   exits loop if anything is received.  In the loop, if poll fails,
		   get latest hazard values (from hazard.monitor process) and,
		   if hazard found in direction of travel, send 'stop.motor.monitor!'
		   message (to break the loop in the above process), wait for
		   'stop.check.hazard?' message, set 'hazard.detected' and exit loop.
	  TRUE
	    SKIP
	motor.cmd ! stop
	success := NOT hazard.detected
    :

I'm unsure if there is chance of deadlock here? I haven't experienced any and it appears to work fine.

I have also managed to implement this move process in a sequential fashion where hazard levels are checked, then motor feedback and it loops back round. I believe this isn't too great though, as it reports it has moved 10mm closer to the hazard than when it detected it.

Answer 68:

Not bad, :), ... but there is the chance of deadlock (see below) and unnecessary inefficiency (busy polling). You also have a trivial typo error in your code for detecting hazards in the direction of travel of the rover (use of the 'BACK.RIGHT' index twice, instead of 'BACK.RIGHT' and 'BACK.LEFT').

Polling cannot be avoided with this design, since you have to send a specific request to the 'hazard.monitor' process (the second of your PAR components) at the same time as watching 'motor.feedback?' (the first of your PAR components) to see if the target distance has been reached ... and occam-pi does not support ALTing between a send and a receive.

However, your polling is needlessly busy! Your second PAR component gets new hazard levels each time the poll on 'stop.check.hazard?' fails (which takes around two or three nano-seconds and will almost always be the case). This is far too often and will keep a processor core at 100% and very hot! Rather than PRI ALT against a SKIP guard, PRI ALT against a timeout (set for, say, every tenth of a second ... which should be often enough, given the slow speed of the rover). The rover movement should be the same, but the processor loading should now be minimal (along with demands on its battery ... which is a key consideration for any embedded application).

Deadlock can happen with your design as follows. The loop in the first of your PAR components exits because the requested distance, 'move.mm' has been exceeded. At roughly the same time, the loop in your second PAR component detects a hazard and sends a 'stop.motor.monitor!' to the first component. That first component is no longer listening, because it's exited its loop and is trying to send a 'stop.check.hazard!' to the second component. Deadlock!

This deadlock is unlikely to show up ... but that's not acceptable! One day it will happen. The rover is on Mars and may be tricky to reboot, :(. There is a (fairly simple once you know it) way to avoid such deadlocks – and it's the same solution as is needed for implementing the cancellable service pattern (described in the answer to Question 64 (2011)).

However, it may be simpler to follow the suggestion in the last sentence of the Postscript of the answer to Question 59 (2011). For your code, combine the two PAR components into a single loop that ALTs between 'motor.feedback?' and a timeout (every tenth of a second). Respond to a 'motor.feedback?' in the usual way (exiting the loop if the target distance is achieved). Respond to a timeout by getting the hazard levels (exiting the loop if a hazard is detected). Simples, :).

The above may be close to the "sequential fashion" you mention ... but please use timeouts (not busy polling)! From your description, it sounds like you only check the hazard levels after every 'motor.feedback?' ... which is wrong (and would account for the 10mm overrun you report). You need to ALT ... as described in the preceding paragraph.

Hope this helps.

Keywords: mars

Referrers: Question 69 (2011)


Question 67 (2011):

Submission reference: IN2100

In response to my earlier Question 65 (2011) about the never ending while loops, here's my code for the turn process. I've had a look at both the previous questions and they still don't solve my problem. Here is my turn process:

    PROC turn (VAL INT distance, CHAN INT output!, CHAN INTERNREP feedback?, 
               CHAN P.MOTOR.CMD sigsender!, CHAN P.MOTOR.FEEDBACK info?)
      ...  code omitted
    :

The feedback channel in here is to gather info from the sensors. It delivers two items: a BOOL that indicates if the sensor is from the front or the back, and then the threat level.

Also, is it possible to use the AND operator to determine whether two expressions are both true? I've switched from using nested IFs to this method while debugging my code, but the computer is coming up with an error.

Answer 67:

[Note: although this answer is about code that is not shown, it should be worth reading by those other than the questioner since it describes misunderstandings about the problem and errors in approach that may be of help generally.]

You use the IABS function correctly on the info channel tick counts to accumulate always a positive total amount of turn. But you should also use IABS on distance (the commanded amount of turn) when checking to see if that total exceeds the commanded amount. Otherwise, if the turn were anti-clockwise (i.e. distance were negative), your loop would never end.

You also wait (inside the loop body) for sensor information (warning you about hazards) from your feedback channel. If none arrives, your code blocks at that point until some comes. Meanwhile, the rover keeps on turning and you keep missing ticks from the motor feedback info channel. It's not that the loop keeps looping ... it just gets stuck! This is almost exactly the same mistake as pointed out in Question 55 (2011) (the paragraphs following: "There are other problems though ...").

Also, if and when you do get sensor information from your feedback channel, the code you sent does nothing with it ... possibly because of the question you raise in your last paragraph?

In that last paragraph of your question: when you say "the computer", I assume you mean "the compiler"? If so, you must be having trouble with the syntax of boolean expressions containing boolean operators (AND, OR, etc.). Remember that occam-pi has no binding precedence for any of its operators – for the good reason that it's hard to remember them! So, when writing expressions with more than one operator, we must bracket them to group them in whatever way we want (what-you-see-is-what-you-get). For example:

    IF
      (x > y) OR (x > Z)
	...  do something
      TRUE
	... do something else

or:

    WHILE (distance.turned < absolute.distance) AND (danger < theshold)
      ...  do something

Hope that helps ...

Keywords: mars

Referrers: Question 71 (2011)


Question 66 (2011):

Submission reference: IN2099

Can we leave the debug dumps (log!) in our code (I use it to display all the calculations and steps)?

If I leave it there, it messes up the operator response part of the output.

Answer 66:

If you have masses of log reports and the screen output is too messy, please comment them out ... but read on ...

A better way (than commenting) to switch on and off debugging reports is to declare somewhere close to the top of your program:

    VAL BOOL debugging IS TRUE:      -- for no debug reports, change to FALSE

and then to wrap all debugging reports with:

    IF
      debugging
        ...  sequence of "log !" reports
      TRUE
        SKIP

Then, you can easily switch off debugging with a single-line change of the declared VALue of debugging to FALSE.

Set this FALSE for your submission. If your program does not work for some tasks, include a README.txt file in your submission that says what does not work and mention the debugging reports in your code and how to switch them on. Making it easier for your markers is always a good idea!

Keywords: mars , debugging


Question 65 (2011):

Submission reference: IN2098

Hi, I've been working on the move and turn parts of the mars assessment. I seem to have implemented the sensor section correctly, as my robot stops for obstacles, but refuses to stop other than this. Currently, I have a while loop that only runs while the total amount moved/turned is less than the amount given by the operator. This is worked out by adding each value being received on the feedback channel to the total distance travel. I can't seem to figure out why its not stopping.

Answer 65:

This sounds similar to the problem reported in Question 55 (2011). Check out its answer – especially the paragraphs following the one starting: "There are other problems though ...". Also, check out Question 58 (2011) and its answer – this question reports the same problem, but the mistake was for a different reason.

If these don't help, you have to post more information on your code. I'll edit out too much information before replying.

Keywords: mars

Referrers: Question 67 (2011)


Question 64 (2011):

Submission reference: IN2097

Regarding Mars:

I'm having some trouble getting the hazard detection to work as I would like. I can receive the values and act upon them easily enough when moving – the problem is checking them prior to moving. I would like to check them before the robot moves; for example in the case were the robot has stopped for a hazard and then told to move again towards that hazard. I want the values I had previously so that I can prevent the robot from ever moving, until it’s facing/moving away from the hazards.

The problem is that the values aren’t persistent since the move proc ends so I have to request new values. However, the hazard monitor doesn’t have new values since they only update when the values change (i.e. whilst moving).

I can see how I would do this with a request system: have my monitor run continuously, and ask for the hazard values whenever I need them, and then just keep asking every set amount of time whilst moving. However, this sounds like a bad solution. I would rather keep a system similar to my current one, in which I ALT on the hazard channel and respond based on the values. However I can't get it to work as a check before movement and at the same time work whilst moving.

Any tips or advice would be appreciated. :)

Answer 64:

As you say in your last but one paragraph, a request solution (see the answer to Question 59 (2011)) works but is awkward and inelegant – as it depends on choosing a suitable polling interval between requests (see the Postscript in the answer to Question 59 (2011)). The rest of that Postscript describes an elegant modification to this, but leaves you with a challenge to implement it in a way that avoids any possibility of deadlock.

The solution to that challenge is an example of a general, and very useful, concurrency pattern: the cancellable service. This is an extension to the pure client-server pattern (see Overview slides 39-43). In a cancellable service, a client can interact with a server in the normal way (send a request message, wait for reply). However, the client can also send a cancel message, following its request, if it has a reason that it no longer needs that service. The server must be able to receive and deal with such a cancel, even though it may be about to send a reply to the client – without causing deadlock. Dealing with a cancel would mean undoing any state change made in the server as it processed the now-cancelled request. Something to think about ... ;).

There's a sequential way to solve this problem (i.e. without installing a concurrent hazard monitor that provides a cancellable service) that may be easier.

You said: "the hazard monitor doesn’t have new values since they only update when the values change (i.e. whilst moving)". That's true, but hazard values also change when the rover is turning. They could also change if other moving obstacles (e.g. other rovers) are on the scene – although that doesn't happen in the simulation environment you have been given. To cope with this, all hazard channels must be observed at all times and the most recent warning levels kept up to date. Of course, this is what a a concurrent hazard monitor does.

But this can be done sequentially. The robot.control process has various states that it goes through is various sequences: wait for an operator command, do a turn, do a drive, do a find and do a deploy. So, listen to the hazard channels when doing all these things, keeping the latest warning levels in an array that is passed to all implementing PROCs (as a reference parameter, of course). Then, when asked to do a drive, you have the current hazard levels in that array – so you can check before moving. The important thing is to monitor the hazard channels when turning, even though that information is not relevant for the turn itself. Although not necessary for the environment we have given you, monitoring the hazard channels when waiting for mission control commands is trivial to add (and useful, in case of aliens or other robots).

Everything said in the last two paragraphs applies also to monitoring the camera channel – just save the latest BLOB. Then, when told to find one and the rover is stationary, you may already have it!

Keywords: mars

Referrers: Question 68 (2011)


Question 63 (2011):

Submission reference: IN2096

Super Simple Question:

Will our marks be affected by the efficiency of Task 4?

Answer 63:

My demo answer takes a pretty long time for the rover to find its way to very roughly the midpoint between the two blobs. Sometimes it fails completely (e.g. when too many obstacles are in the way it wants to move).

Following a strategy that takes a long time to find a place, very roughly, where the sensor is to be deployed will definitely not be penalised!

Of course, unnecessary inefficiencies in lower-level logic will continue to be penalised.

As always, your code must be elegant and clean – well-chosen PROCs that abstract coherent pieces of logic, no repeated sections of code with only trivial differences (e.g. magic constants), sensible comments explaining aspects of your code that are not obvious (e.g. the high-level search strategy you have devised), etc.

Keywords: mars

Referrers: Question 69 (2011)


Question 62 (2011):

Submission reference: IN2095

For the Mars assessment, Do we just submit mars-main.occ?

Answer 62:

Thank you for this question. Perhaps we did not make it crystal clear! The fourth bullet of the Getting Started section of the Starting out on Mars web page says: "mars-main.occ. This is the file you'll spend your time editing, and eventually submit, as detailed in the submission guidelines." I've updated those guidelines in the Assessment 5 box on the Moodle page and repeat them here for convenience:

Please only submit your edited mars-main.occ file, together with process network diagram(s) if you have used concurrency in your implementation of the robot.control process. Network diagrams can be in the formats approved for earlier assessments (or could be handed in to the CAS office on paper with signed cover sheet). If you have changed any of the other files in this assessment's set of files, you must also submit those – together with a README file explaining the changes you have made. [Note: we do not expect you to have changed any files (other than mars-main.occ, of course)].

Keywords: mars


Question 61 (2011):

Submission reference: IN2094

Task 3 of the mars assessment.

If the robot turns a full rotation (360 degrees), and hasn't found anything so therefore stops find.blob execution, should it return a value of 0 for new heading or is 360 acceptable?

Answer 61:

The instructions for Task 3 say: "return the new heading of the robot relative to the heading you started at". A heading of 360 degrees relative to the initial heading is the same as 0 degrees – so either figure is acceptable.

Keywords: mars


Question 60 (2011):

Submission reference: IN2093

Regarding the Mars assessment:

As turning an odd number of degrees always turns the robot one more than the amount specified e.g. input is 39 robot turns 40. Is it ok to check for an odd number and then subtract one from that number so the correct number of degrees is always turned?

Answer 60:

Nope – don't worry about it.

The click counts when turning tend to be plus-or-minus 2 (and, when driving, plus-or-minus 10) – but you don't need to know that. Just turn or drive till the total click counts is greater than or equal to the amount commanded (or less than or equal if going anti-clockwise or backwards). If asked to turn 39 and your robot turns 40, report what actually happened (i.e. 40) and that's fine. If asked to drive 41 and your robot drives 50, just report 50 and that will be OK.

[Note: when driving, we cannot assume that the click counts will always plus-or-minus 10. So, there's no need to do something clever ... like backing up if the rover overshoots (although you will not be penalised, of course, for doing this).]

Keywords: mars


Question 59 (2011):

Submission reference: IN2092

I have been trying to implement the hazard detection for the last few days, specifically ensuring that the values are monitored at all times. However I am struggling to think of a solution that will allow me to read the latest values of the hazard channels when necessary.

Currently I have:

    PROC hazard.monitor ([]CHAN P.HAZARD.DETECTOR hazard?, []INT hazard.value)
      WHILE TRUE
        ALT i = 0 FOR SIZE hazard
          hazard[i] ? hazard.value[i]
    :

This updates an array in the main robot.control to always contain the latest hazard values. The move process takes in this array as a reference data parameter, and attempts to read values when required.

My problem is I can't have the values being updated at the same time as they are read, as it complains they an array cannot be read and assigned to in parallel – this is understandable but I can't work out how to solve my implementation.

Answer 59:

Your hazard.monitor and robot.control are non-terminating processes and must be running in parallel. As you report, parallel processes cannot communicate by shared access to the same data – an array of hazard values in this case. As always, parallel processes communicate by sending information over channels.

Your hazard.monitor and robot.control need to be be connected by channels (not by a shared piece of data). Your hazard.monitor needs to be a server, responding to hazard warnings and saving them (as it currently does) ... but saving those warning values in its own locally declared array (not a reference parameter). This hazard.monitor also has to service enquiries from robot.control: when robot.control (or some PROC that it invokes to do some commanded action) needs to know about hazard levels, it simply asks hazard.monitor, which then replies with its latest values. This server is trivial:

    PROC hazard.monitor ([]CHAN P.HAZARD.DETECTOR hazard?,
                         CHAN BOOL enquire?, CHAN [HAZARD.SECTIONS]INT reply!)
      [HAZARD.SECTIONS]INT hazard.value:
      SEQ
        ...  initialise hazard.value array to zeroes (indicating no hazards so far)
        WHILE TRUE
          ALT
            BOOL any:
            enquire ? any
              reply ! hazard.value
            ALT i = 0 FOR SIZE hazard
              hazard[i] ? hazard.value[i]
    :

Simples, :).   [Note: HAZARD.SECTIONS is declared in the file "mars-robot.inc" and is set to 4.]

Now, all your movement code needs is its own array of hazard levels in which to receive data from hazard.monitor (whenever it asks for it). Of course, this code cannot have connections to the hazard channels itself – they are held by hazard.monitor and the occam parallel usage rules do not (for good reason) allow any parallel process also to hold them – so it has no choice but to ask hazard.monitor.

Postscript: the above hazard.monitor server is a little awkward to use ... because the robot.control driving logic has to decide when and how often to make its enquiries (e.g. every 100 milliseconds, depending on how fast it is moving). Better would be to put more intelligence into hazard.monitor – for example, programming it to check the hazard values it receives and, if they are over some threshold, send a warning (e.g. hazard channel index and over-threshold value) to robot.control without being asked. Then, the robot.control driving logic just needs to ALT between motor feedback and the warning channel from hazard.monitor.

However, hazard.monitor will in that case need to be told whether the rover is driving forwards or backwards or, indeed, whether it is driving at all (so that it knows which channels, if any, should be checked to trigger warnings to robot.control). Unfortunately, the process that can do that telling is robot.control. So, there is a danger of deadlock – e.g. if robot.control decides to tell hazard.monitor that it is stopping (because the rover has travelled the requested distance) just as hazard.monitor detects an obstacle is too close and decides to send robot.control a warning.

There is an elegant solution to this ... but we'll leave you to think about it. Meanwhile, asking the server (as programmed above) for the hazard levels every so often when driving (i.e. ALTing between motor feedback and a timeout) will work.

Keywords: mars

Referrers: Question 49 (2012) , Question 64 (2011) , Question 64 (2011) , Question 68 (2011) , Question 68 (2011)


Question 58 (2011):

Submission reference: IN2091

This question is related to the movement of the robot in Task 2 of the mars assessment.

After trying to solve this Task for several days and looking at other questions I am still at square one. The robot moves but stops only when a hazard is detected even though the clicks of the motor are monitored to break the loop if and when the required clicks have been met.

The following code fragment is what I have for the move process:

    PROC move.robot (...)
      ...  code omitted
    :

Where am I going wrong?

Furthermore, relating to Task 3, the following code in theory should work but does not. The robot continues to rotate regardless:

    ...  code omitted

If you could clarify my errors, I would be most appreciative.

Answer 58:

[Note: although this answer is about code that is not shown, it should be worth reading by those other than the questioner since it describes misunderstandings about the problem and errors in approach that may be of help generally.]

The first thing wrong with your move.robot is that the OR in your WHILE-condition should be an AND. This is why the loop does not exit when the required distance has been travelled.

There are other problems though. Why do you look at three hazard channels when moving ... and always the same three (indices 0, 1 and 2) whether moving forwards or backwards? Your ALT replicator is "i = 0 FOR 3" ... which runs "i" though 3 values only (0, 1 and 2). You should be listening on all four channels ... which needs the replicator to be "i = 0 FOR 4". Of course, you should only respond to danger on channels 0 and 1 when moving forwards ... and 2 and 3 when moving backwards. You always need to listen to all hazard channels in order to keep an up-to-date array of the latest warning levels (see the last paragraph of this answer).

You almost duplicate the code for moving forward and backwards: the only differences are a ">" instead of a "<" and adding 9 to the motor.feedback click count (why do you do this?!). Long sections of logic should never be repeated in programs (and will lose marks)! In this case, it can be avoided by using the IABS function mentioned in "Tips for Task 1" in the Starting out on Mars webpage (look at its coding in the file mars-robot.inc).

You report the wrong value in your hazard.detected report back to mission control ... which shouldn't be done here anyway ... see the quotation in Question 56 (2011).

What theory says that your code for Task 3 should work? The robot continues to rotate because your code for this Task has the same mistake as your Task 2 code – the OR in the WHILE-condition should be an AND.

But your Task 3 code also contains mistakes similar to those reported in the answer to Question 55 (2011), even though that answer was about Task 2 code. You repeatedly issue a turn.right command in each loop body ... when that should be done once only, before entering the loop. Inside the loop, you wait each time for motor.feedback and poll the camera channel. The message rates on these channels are unrelated ... but this code only checks the camera once for each motor.feedback. If the camera tries to report blobs faster than the motor feedback reports clicks, you will miss some of the blobs (which will be lost in overwriting buffers because your code didn't take them).

You must always be processing messages from the camera and from all hazard channels and (if the motor is running) from the motor feedback. To do this, your loop should be ALTing between the motor feedback and camera channel, not reading one in parallel with a poll on the other! You should also include the hazard channels in the ALT and be saving the values that are sent somewhere ... so that you always have up-to-date information on nearby obstacles (which is for useful when the rover is next commanded to move).

Keywords: mars

Referrers: Question 65 (2011) , Question 71 (2011)


Question 57 (2011):

Submission reference: IN2090

I'm receiving a "spurious hazard.detected" warning, but unsure why? I see something similar in Question 44 (2010), but it doesn't particularly help in my case. Here's the full log:

    Commanding robot 0: move 444
    Response: ... hazard.detected; moved 320
    
    Please select a command (t)urn, (m)ove, (f)ind blob, (d)eploy sensor:
    Warning: spurious hazard.detected

Answer 57:

There's not much more to say other than the answer to Question 44 (2010). Mission control sends the Mars rover commands and, eventually, the rover replies with an appropriate report. If the rover (i.e. your robot.control logic) replies with the wrong variant of message, the system will crash. If the rover sends a message back to mission control without mission control sending it a command, mission control issues a "Warning: spurious ..." (where the "..." refers to whatever variant of message was incorrectly sent).

From the log you report, it looks like your move logic sends back a hazard.detected message twice?

Keywords: mars


Question 56 (2011):

Submission reference: IN2089

In Question 55 (2011), you wrote:

"From the software engineering principle of cohesion, your move process should just move the rover, reporting back its success and distance moved through reference data parameters. It should not have the additional responsibility of reporting that result back to mission control (which it currently does via the opr.resp channel). The latter should be done separately by whatever has invoked the move. In this way, you will be able to reuse this move code for other purposes – e.g. for Task 4."

I'm not quite sure what you mean by "reference data parameters", please could you explain?

Answer 56:

See basics slides 37, 67 and 68. The parameter result is a reference data parameter and, in this example, is expected to be set by the code within the body of the foo process before that terminates. When foo is invoked, an INT variable must be supplied as its third argument (slide 68) – anything the foo code does with result will actually be done to the variable supplied. See also this relevant bit from the occam-pi Reference wiki (which is linked from the "Practical Resources" box on the Moodle page for this course).

In this way, occam-pi PROCs can return results (plural: there can be any number of reference parameters), as well as interact with their environments (through channel communications, barrier syncs etc.). [Aside: occam-pi FUNCTIONs also return results (plural), but they are not allowed side-effects (e.g. interacting with their environments).] For the example provoking this discussion, your move process could have a reference boolean parameter (for success) and a reference integer (for distance).

Revision: VALue data parameters cannot be changed by their PROC body (i.e. they are constants). Supplied arguments may be variables, constant literals or expressions (basics slides 37and 67).

Constant literals or expressions may not, of course, be supplied as arguments for reference parameters.

Also, the answer to Question 57 (2010) is highly relevant to this question – so, do check this as well. The question in Question 57 (2010) may be best ignored!

Final note: better than reference parameters for returning PROC results are RESULT parameters. RESULT parameters are new in occam-pi, not in any course materials and, of course, not examinable. However, they are very simple, easy to use and improve security – see Question 58 (2010) and (the end bit of) Question 60 (2010).

Keywords: mars , parameter , reference , value , result

Referrers: Question 58 (2011)


Question 55 (2011):

Submission reference: IN2088

Follow up of Question 54 (2011).

This is the entire block of my move command. What it does is move the motor while monitoring for hazards, and it can only exit if the move is completed or obstructed. After days of investigating the problem, I was still unable to figure out why the robot stops randomly and sometimes even "motor.cmd ! stop" does not even stop the robot, even after the "opr.resp!" block has executed.

    PROC move (...)
      ...  code skipped
    :

As for the PRI ALT timeout guard, the degree.turned\90 condition is always triggered when degree.turned reaches 90, 180, 270 and 360 degrees during testing, but I will look into it. The PRI ALT guard prints out "Timeout!" everytime without ever waiting for CAMERA.SCAN.TIME (2sec), such as below. I'm very lost at this one. Some Output:

    ...
    ?robot 0: 90
    ?robot 0: Timeout!92
    ?robot 0: 94
    ...
    ?robot 0: 180
    ?robot 0: Timeout!182
    ?robot 0: 184
    ...
    ?robot 0: 270
    ?robot 0: Timeout!272
    ?robot 0: 274
    ...
    ?robot 0: 358
    ?robot 0: 360
    ?robot 0: Timeout!blob not found; turned = 360
    Please select a command (t)urn, (m)ove, (f)ind blob, (d)eploy sensor: 

The code:

    PROC find.blob (...)
      ...  code skipped
    :

Answer 55:

[Note: although this answer is about code that is not shown, it should be worth reading by those other than the questioner since it describes misunderstandings about the problem and errors in approach that may be of help generally. Some fragments of the code under discussion are shown in Question 54 (2011).]

Your code shows a misunderstanding of the way the motors on the rover operate. In the section on motor commands and feedback in the "Starting out on Mars" website, it says:

"Motor commands continue acting until you send a stop command. When the motors are active, tickers in the motors will send values along the motor feedback channels telling you how much the robot has turned in each step."

So, you only need to send a drive.forward (or drive.backward or turn.right or turn.left) command once and the rover with start and continue driving (or turning). As the rover drives or turns, a series of click counts are sent on the motor.feedback channel from time to time, with values representing the amount driven or turned since the last message (or the original drive/turn command). These counts are usually 10 or -10 (when driving) and 2 or -2 (when turning) in the current simulator, but you cannot rely on that: they could be anything. The rover will continue to drive (or turn) – and motor feedback clicks will continue to be sent – until the motor is commanded to stop.

Your code repeatedly issues a drive (or turn) command followed by a wait to receive feedback clicks. This is wrong. The drive (or turn) command should only be sent once.

There are other problems though. In the loop in your move process (Task 2), you wait in parallel for one motor.feedback message and one hazard report (from any one of the four hazard channels). This is wrong for the following reason:

The message rates on the motor feedback and hazard channels are unrelated. For example, if the rover is in clear space all round and driving, there will be no warning messages incoming on any hazard channels. Your loop will receive the first motor feedback clicks message and will wait for a hazard message that doesn't arrive. Meanwhile, the rover will continue driving and clicks will continue to be fed back ... but your code will not be processing them ... because it's stuck waiting for a hazard message!

Eventually, the rover will get close enough to an obstacle and a hazard message (probably below your set threshold) will arrive: the first loop of your move process will now take that report and complete. In the next loop, it will receive in clicks the accumulated total of all the clicks that it missed whilst waiting for that hazard message – i.e. your distance.travelled will suddenly jump by the amount the rover travelled before the first hazard was detected. That loop iteration now has to wait for another hazard message before it loops around to discover the distance travelled (probably) exceeds that requested. That excess depends upon the distance to the first obstacle that caused a hazard warning and will be unrelated (apparently random) to the distance in the original command. I think this accounts for the behaviour you report.

The motor feedback and hazard channels should be monitored independently. The nicest way to do this is in parallel monitoring processes, each with their own loop. The simplest way, given your existing code structure, is for the loop body to have a single ALT between the motor feedback channel and all the hazard channels (done by a nested replicated ALT). Of course, the motor command to drive forward or backward should be done just the once – before the loop starts. [Your code also crashes if the distance it is asked to drive is zero and needs fixing.]

By the way, you should be aware of relevant hazards before issuing any drive command. Otherwise, you may crash into something. Look before driving!

From the software engineering principle of cohesion, your move process should just move the rover, reporting back its success and distance moved through reference data parameters. It should not have the additional responsibility of reporting that result back to mission control (which it currently does via the opr.resp channel). The latter should be done separately by whatever has invoked the move. In this way, you will be able to reuse this move code for other purposes – e.g. for Task 4.

Your find.blob process makes the same mistake of repeatedly issuing motor.cmd commands. Your (degree.turned\90) only works because the clicks value you receive is always 2, so that degree.turned does go though even numbers that include 90, 180, 270 and 360. This is unsafe since the clicks received could sometimes be 4 or 6 or 8 or 33 or 42 ... or anything.

I don't yet know why your code seems to timeout straight away (at least, within 2 clicks of turning), but its structure is wrong. Every 90 degrees of turn, your code tries to spend up to CAMERA.SCAN.TIME (2 seconds, unless you changed it!) processing camera data. While doing this, the rover is still turning! So, the bearing angles on any blobs reported will be out of date.

You must stop the turn every 90 degrees and, then, process camera data for 2 (and a bit more, to be sure) seconds. Simplest would be to invoke the process written for Task 1 (excluding any report back to mission control!) to turn the rover 90 degrees – where the turn command and stop command logic is already done. Of course, you will need to correct that Task 1 logic so that the turn command is only issued once.

Keywords: mars

Referrers: Question 47 (2012) , Question 47 (2012) , Question 49 (2012) , Question 56 (2011) , Question 58 (2011) , Question 65 (2011) , Question 67 (2011) , Question 71 (2011)


Question 54 (2011):

Submission reference: IN2087

I have problem moving the mars robot on different position on the map accurately: distance.travelled is returned as a random value initially, even when it is initialised to 0. Making move 50mm being reported as moved -840mm or 70mm and such, and sometimes it just moves all the way without stopping until it hits the map border. The code responsible:

    INITIAL INT distance.travelled IS 0:
    motor.feedback ? clicks
    distance.travelled := distance.travelled + clicks

I also have a problem where the PRI ALT timeout guard just executes directly without even waiting for the timeout to happen.

    IF
      (degree.turned\90) = 0
        SEQ
          motor.cmd ! stop
          tim ? t
          WHILE waiting
            PRI ALT
              tim ? AFTER (t PLUS CAMERA.SCAN.TIME)
                SEQ
                  out.string ("Timeout!", 0, log!)
                  waiting := FALSE
              camera ? camera.feedback
                SEQ
                  out.string ("BLOB detected...Do Something!*n", 0, log!)
      TRUE
        waiting := TRUE

Answer 54:

Your first code fragment just waits for one message from the motor.feedback channel and adds the number received to distance.travelled. If a motor command (to drive) has not been made, no message will be sent on motor.feedback and nothing will happen. If a motor command (to drive) has been made, your code processes the first motor.feedback message and nothing else – the motor will keep going and the rover will move through all obstacles to the image boundary.

To move the rover the commanded distance, you must have more code than this ... to keep processing motor.feedback and the hazard channels until either the distance.travelled reaches (or exceeds) the commanded distance or the rover gets too close to a hazard. You have not shown such code so we cannot say why the distance.travelled you return is unrelated to the commanded distance. Check that all variables that need initialising are initialised correctly.

For your second code fragment, CAMERA.SCAN.TIME is defined to be 2000000 (i.e. 2 seconds). So, the timeout guard cannot execute until 2 seconds after reading the timer value into t just before the WHILE-loop.

Your code does not show the value of waiting before it starts. Are you sure it's TRUE? Has it been initialised? If it is FALSE, then that whole WHILE-loop will be skipped.

You say that that timeout guard executes directly ... but how do you know that ... it only gets executed every 90 degrees of turn (maybe, see below) ... do you ever see the "Timeout!" message on the log channel (which is routed to the screen)?

Also, I don't trust your (degree.turned\90) test against zero. I'm assuming your degree.turned variable is accumulating ticks from motor.feedback? But those ticks could be any number (i.e. not necessarilly 1 or 2). Note the remark in the "Starting out on Mars" website about the motor.feedback information: "You can't (and shouldn't) rely on these ticks being a fixed value anywhere in your code". So, your increasing degree.turned variable could get larger than 90 without ever equalling 90 (i.e. degree.turned\90 may never be zero).

Check the Warning messages from the compiler. Those about use of uninitialised variables ought to be upgraded to Error messages and compilation refused. Unfortunately, the compiler logic is woefully too cautious and gives too many false positives regarding uninitialised variables – which is why they are warnings only and compilation continues (and for which we apologise). But you should check those warning messages and either see that they are correct (and fix the problem) or deduce they are incorrect (and ignore).

Keywords: mars

Referrers: Question 55 (2011) , Question 55 (2011)


Question 51 (2011):

Submission reference: IN2084

Hi, I'm currently doing Task 3 for the life on mars assessment. Whenever I run the program and attempt to enter a colour for the robot to find, the screen simply flashes and doesn't accept the input.

Answer 51:

This is a new improved user interface for selecting from a long list of options. Try pressing the TAB key, as the initial prompt suggests. You will be shown the legal colours and be prompted again. You will only be able to type letters that go towards those colour names. Press TAB at any time and either you will be shown remaining possible options (given what you have typed so far) or characters will be supplied for you (as far as possible towards an option, until there is a choice). If only one option is possible (given what you have typed so far), pressing TAB completes the word. Of course, you can type BACKSPACE at any time. Press SPACE or ENTER to complete your selection – this will be ignored if you still have an incomplete word.

This user interface is modelled on file and command name completion in the bash shell of Unix. It is implemented by the ask.select process defined in the "ask_select.occ" file and invoked by the mission.control process in "mars-sim.occ" (and supported by the small function in "alpha_numeric.occ"). The ask.select logic is fairly complex, but made amenable through the declaration of loop invariants (a general and extremely useful programming mechanism that can be used in any language).

Keywords: mars , loop-invariant


Question 36 (2011):

Submission reference: IN2068

This question is related to the mars project.

Upon trying to complete task 2, I have hit a wall in which when trying to read from the array of channels hazard to an array of INTs. I recieve the error message:

  "Error-occ21-mars-main.occ(83)- hazard subscripted too many times" 

The following code fragment is what I have attempted to do:

  ...  code omitted

Answer 36:

Your code has a BOOL variable named hazard, declared in the scope of an array of channels also named hazard. With multiply declared names, only the most recent one is used. Your code has a replicated ALT trying to read from the channel array ... but all the compiler sees if the boolean variable ... which doesn't have subscripts!

Fix: choose a different name for your boolean!

Keywords: mars

2010

Question 68 (2010):

Submission reference: IN1963

I'm really sorry this is not a question!

I wanted to say thanks a lot for the answers you've given me. I submitted a first question and thought: "well no-one is going to reply on a sunday so I will have to wait till monday" – but you still replied and the answer really helped me! Then I submitted another (I think around 4-5am) and thought: "well no-one is going to be awake at this time so I might as well go to sleep and check the answer tomorrow" – but I stayed up anyway and then found a very useful answer to my question!

I'm actually really surprised - I hope you are getting paid overtime for this! Thanks a lot!

Answer 68:

:)

... but they don't pay overtime!

Keywords: mars


Question 67 (2010):

Submission reference: IN1964

Hello! Can you answer a question for me? I am working on part 3 of mars!! It says: "At the end of the search you should return the new heading of the robot relative to the heading you started at (as you will have rotated)." What does that mean?

Say the robot is facing NORTH and it rotates 90 degrees clockwise and then sees the blob which is 95 degrees from NORTH do I return, 90 or 95??

Thanks, see you at 10!

Answer 67:

The sentence quoted only talks about the robot – not the blob. So, if the robot has rotated x degrees, it should return x.

It must also return whether it found the blob and, if so, the blob data. This data includes information about the bearing of the blob relative to the orientation of the robot when it saw the blob ... which you need to ensure is the orientation of the robot when making its report ... i.e. the blob must be observed (or re-observed) when the robot is at rest.

The short answer to your question is: 90.

Keywords: mars


Question 66 (2010):

Submission reference: IN1962

A question for task 3 of the mars assignment. I want a full "turn 360" to occur when it can't find a blob, but I noticed that when I use "camera ? b" to check for blobs (b being the variable for blob) - it turns about 60 degree more than 360 (and displays that it turned a total of 380ish) ...

I'm assuming that this is because using "camera ? b" will delay the other processes somewhat ...

Will I lose marks for my current implementation?

Answer 66:

Probably!

Using "camera ? b" won't delay anything if it's a guard in an ALT with other guards (e.g. motor feedback or a timeout) that can be taken ... or if it's done in a process running in parallel with other actions.

Hope this has helped ... it is 5:41am (and we've a lecture at 10)!

Keywords: mars


Question 65 (2010):

Submission reference: IN1957

I'm having the same problem as Question 48 (2010), );. The colour returned for blue by the camera is #0064220A while the robot is looking for #0000FF. Is there a way to implement the colour in hex instead an INT, coz that's where I think the problem is ...??

Answer 65:

Sorry – I don't understand "The colour returned for blue by the camera"? I guess you mean the colours of the blobs returned by the camera are numbers like #0064220A (while the robot is looking for blue, although that's not relevant)?

Your question asks how to "implement the colour in hex" ... but numbers like #0064220A and #0000FF are in hex! Sorry, don't understand ... ?

Keywords: mars


Question 64 (2010):

Submission reference: IN1960

A question for the mars assignment. I've just noticed that when I want the robot to move 1 mm it will move 10, 11 mm will move 20 mm ... and so on. Is this correct or am I fluffing something up somewhere?

Answer 64:

Mine does the same! It's OK.

Given the feedback from the motors comes in tens, you could anticipate – e.g. if asked to move x mm, tell it to move (x - 5) or zero, whichever is larger. Then, the robot will move to the nearest 10 mm of the distance asked. But you weren't told the feedback is like this and it may change ... i.e. don't worry on this point! :)

Keywords: mars


Question 63 (2010):

Submission reference: IN1959

Having a bit of a problem with the mars assignment. When I read in the values from hazard, I get a runtime error (STOP error):

  SEQ i = 0 FOR 4
    hazard[i] ? h[i]    <--- this line

Any help would be greatly appreciated.

Answer 63:

The hazard array we plug into robot.control indeed has 4 channels. Are you sure your array h has four elements? If it has less, the runtime error you describe must happen.

Keywords: mars , stop

Referrers: Question 31 (2012)


Question 62 (2010):

Submission reference: IN1958

Hi, Just wondering if there is an occam-pi alternative to the Java/C continue inside a while loop? For the mars assessment, I have sent an operator response and no longer want to continue with the rest of the code in that iteration of the loop. Thanks in advance :-)

Answer 62:

Nope – continue statements are evil and lead to tears. Set a BOOL flag when you send to the operator and use an IF construct to skip the rest of the code. That's explicit and we can see what's happening.

Keywords: continue , break , loops , mars


Question 61 (2010):

Submission reference: IN1961

I'm stuck on Task 3 for the last few hours.. dont't know where the problem is, but the colors from the camera and the color provided by the user don't seem to match.. It'd be great if you could tell me where I'm going wrong.. Here's the full code:

  ...  code deleted

Answer 61:

Your find.blobs process has two ALTs, each with only one guarded process. They are the same as no ALTs – just do their input guard and response code in sequence!

The second ALT takes input from the camera and it's within a search loop. If no blob with the target colour appears, the camera eventually exhausts the blobs it can see and sends nothing ... and your find.blobs gets stuck. Fix this by setting a timeout on waiting for the camera – see the end of the answer to Question 52 (2010).

Keywords: mars


Question 59 (2010):

Submission reference: IN1955

Hi, Could you explain what motor.feedback returns during movement in the Mars animation? It returns degrees when turning, as stated in the help pages but I've not been able to fathom its output during straight movement. Thanks!

Answer 59:

On the Life on Mars web page, it says:

You can't tell the robot to go forward 60, but you can tell it to go forward, add up all the values for the amounts it moves and stop when that value is 60.

So, you may assume the values from the motor.feedback channel when moving are in the same units (probably millimetres) as the distance the robot has been commanded to move.

Keywords: mars


Question 57 (2010):

Submission reference: IN1952

Hey, this is in follow up response to my earlier Question 50 (2010): "Does the output from the opr.resp channel (that turn sends data to) have to be stored somewhere ... rather than just sent down a channel that is only connected at one end?"

You reply: "I don't understand the last sentence of your second paragraph ... it doesn't parse well. Sending data down a channel copies the data – i.e. it's still stored in the variables used in the send command. It's only with mobile data (discussed in the last lecture) that the sender loses what it sends – that's not the case with your code. Why do you think the opr.resp channel is only connected at one end?"

My question is this. Inside my PROC find.blob, I use my PROC turn and this sends data down a channel that is declared in find.blob (this channel is only connected to PROC turn and nothing else). This causes PROC find.blob to stop/freeze up and left waiting on response. But when I connect the turn response to the actual CHAN P.OPERATOR.RESPONSE that is used to send feedback about whether it has found a block, it works up until it the move command gets a response (I'm guessing it's because it was expecting a find.blob appropriate message rather than a turn message). So how are we supposed to deal with the messages that are generated by PROCs that we don't need?

Sorry for the mass of text above but it was the best way I could come up with to demonstrate my question.

Answer 57:

OK – you have the turn (and move?) logic abstracted into a PROC. This logic looks like it includes sending the response from the turn (or move) back to the operator. This is too big an abstraction – it's doing more than one thing: making the turn (or move) and reporting back to the operator. Better is to have an abstraction that only makes the move (or turn), letting its invoker know through result reference parameters (how much it turned/moved, whether a hazard was encountered). Now, the invoker can report back to the operator (which you need for tasks 1 and 2) or not (which you need for tasks 3 and 4).

But your turn tries to report back. Within find.blob, connecting its report channel to one that doesn't go anywhere (as you first describe) just means deadlock – a process has to receive the report and there is none. Connecting it to the actual CHAN P.OPERATOR.RESPONSE causes a run-time error for the reasons you guess. I suppose you could connect the report channel from your turn to a black hole process (which you would have to write and run in parallel with your code inside robot.control) – but you would still be left not knowing the result of the turn (or move).

So, the answer to your question is: don't generate those un-needed messages! Reduce your turn (and move) abstractions as described in the first paragraph of this answer and all is simple, :).

Keywords: mars

Referrers: Question 56 (2011) , Question 56 (2011) , Question 58 (2010) , Question 58 (2010)


Question 56 (2010):

Submission reference: IN1953

Is there any chance of a FORWARDing keyword to be made e.g.

  out ? FORWARD in

which, if in and out were channels carrying INTs, would be the same as:

  INT i:
  SEQ
    in ? i
    out ! i

This would be very useful in the case of variant protocols e.g.

  out.variant ! FORWARD in.variant

This would replace:

  INT i, j, k:
  in.variant ? CASE
    x.case; i
      out.variant ! x.case; i
    y.case; i, j
      out.variant ! y.case; i; j
    z.case; j, k
      out.variant ! z.case; j; k

which would be much smpler to write. I think this would be useful if you were writing an id process for variant protocols, or in channel bundles wanting to send a request and then forwarding on the response (e.g. having a main control process in mars robots and then forwarding the response from a process (turn etc) to the operator response channel).

Either that or being able to store a variant protocol as a variable e.g.

  VARIANT OPERATOR.RESPONSE variant.variable:
  -- where OPERATOR.RESPONSE is a protocol that the VARIANT is a type of
  INT result:
  in ? CASE
    turn
      variant.variable := turn.complete
      ... do turn
    move
      variant.variable := move.complete
      ... do turn
  ... later
  out ! variant.variable; result

This would reduce the amount of coding where the output on a variant protocol is dependent on the input on a variant protocol. A permutation of that would be to save the whole output in the protocol e.g.

  variant.variable := turn.complete, result

Or something like that.

Answer 56:

You are right that routine forwarding/buffering of messages carried by variant protocol channels is tedious (though trivial) and that something should be done about it.

One proposal is for union types, which give you something like the variant.variable in your question. This, together with an idea for automatic dynamic memory allocation (which saves memory bloat), look promising for the future.

The current list of enhancement proposals for occam-pi can be browsed here.

Keywords: mars , protocol , union

Referrers: Question 30 (2011)


Question 53 (2010):

Submission reference: IN1949

I am sorry if you did not understand my previous Question 51 (2010). I asked if we are allowed to use the Camera to write the move process. I have seen that the Camera reports Rocks from the hazard, so it can help to come closer. Am I right?

Answer 53:

Ah, I think I understand now – I think you mean: are we allowed to use information received from the Camera in the implementation of the move process?

Yes. But there is no need to do this ... when moving, the robot needs to avoid hazards ... so monitor the hazard channels!

I guess you're thinking of checking out the size field of the BLOB data returned by the camera? But the camera gives no distance information ... so a large blob could just be a very large blob a long way away ... i.e. not a hazard!

Keywords: mars


Question 52 (2010):

Submission reference: IN1948

Is it possible to loop over some code for a specified duration? Something like:

  SEQ
    tim ? t 
    PRI ALT 
      NOT (tim ? AFTER t PLUS 2000000)
        ...  still waiting, do stuff
      SKIP
        SKIP

I've had a look over lecture slides and cannot find anything. I want to be certain I am receiving all the blobs from the camera before I start searching them for the correct colour.

Answer 52:

Yes, but this is typically simpler than the code you have above. The "AFTER" operator can be used to test whether one time is after another, so can be used in conditionals. For example:

  TIMER tim:
  INT start, stop:
  SEQ
    tim ? start
    stop := start PLUS 2000000
  
    INITIAL BOOL waiting IS TRUE:
    WHILE waiting
      INT now:
      SEQ
        tim ? now
        IF
          stop AFTER now
            ...  still waiting, do stuff
          TRUE
            waiting := FALSE

There are probably better (more elegant) ways to code this, but that should do what you want. If you really wanted to use an ALT with a timeout it could be coded something like:

    TIMER tim:
    INT t:
    SEQ
      tim ? t
  
      INITIAL BOOL waiting IS TRUE:
      WHILE waiting
        PRI ALT
          tim ? AFTER (t PLUS 2000000)
            -- timeout reached
            waiting := FALSE
          SKIP
            ...  still waiting, do stuff

However, this is polling a timer ...so probably isn't the best way to go about it. How about:

    TIMER tim:
    INT t:
    SEQ
      tim ? t
  
      INITIAL BOOL waiting IS TRUE:
      WHILE waiting
        PRI ALT
          tim ? AFTER (t PLUS 2000000)
            -- timeout reached
            waiting := FALSE
	  BLOB blob:
          camera ? blob
            ...  check out this blob (if target, set waiting FALSE)

? That's much better, :). Now, it only does stuff if the camera sends a blob or the timeout happens – and this is the basic pattern for setting timeouts on waiting for things to happen!

You may need some more stuff in the above ... so that you can tell whether you exit the loop because you found the blob or timed out.

Keywords: timers , mars , polling

Referrers: Question 61 (2010)


Question 51 (2010):

Submission reference: IN1947

Are we allowed to use the Camera to move forward/backward? Indeed, Camera reports rock that may help to come closer.

Answer 51:

Sorry, I don't understand your question.

You have to use the wheel motors (by sending commands to the motor.cmd channel) to move the robot!

Yes, the camera reports blobs when rocks come into its field of view ... just as it reports blobs when it sees artificial ones (that are the real targets).

Keywords: mars

Referrers: Question 53 (2010)


Question 50 (2010):

Submission reference: IN1946

In Task 2 of the mars assessment, are we likely to lose a lot of marks if it goes through objects when multiple moves are called (similar to the demo application we are given)?

I'm also currently on task 3. After telling it to turn, my program just seems to freeze after turning 90 degrees and stays there on waiting on response. Does the output from the opr.resp channel (that turn sends data to) have to be stored somewhere ... rather than just sent down a channel that is only connected at one end?

Here is my current code which might demonstrate the above question a bit further:

  ...  code deleted

Also the part of the assessment sheet (Task 3 still) that says: At the end of the search you should return the new heading of the robot relative to the heading you started at (as you will have rotated).

So does that mean if I turn 180 degrees, I should return 180 degrees as the new heading?

Answer 50:

Yes – we've said that the demo implementation is deficient. You will lose marks if your robot can get moved through obstacles.

Blobs will only be reported to the robot if they are in its field of view, which is indicated by the longer red rays beamed from the robot. Your code starts its loop with a committed read (i.e. with no ALTernative) from the camera channel. So, if there are no blobs that the camera can see, nothing will be sent and your find blob process will wait forever. In the run you describe, it sees a blob (but not one with the target colour), turns 90 degrees, doesn't see a blob and gets stuck. Your loop should not start each cycle with a committed read from the camera channel!

I don't understand the last sentence of your second paragraph ... it doesn't parse well. Sending data down a channel copies the data – i.e. it's still stored in the variables used in the send command. It's only with mobile data (discussed in the last lecture) that the sender loses what it sends – that's not the case with your code. Why do you think the opr.resp channel is only connected at one end?

Yes, if you turn 180 degrees and find the target blob, you send back 180 (and the blob data, of course). Note that you may turn by any amount – not just by 90 degrees each time.

Keywords: mars

Referrers: Question 57 (2010)


Question 49 (2010):

Submission reference: IN1945

I appreciate that having separate PROCs for move/turn etc. is useful and allows for a 'cleaner' design; but would we necessarily have marks deducted for having the move/turn logic contained within the main robot.control process rather than in separate PROCs?

Answer 49:

Clean engineering will always gain more marks than less clean engineering.

Having said that, if all you do is Task 1 (turn), you may get away with in-line coding within robot.control. But it shows a lack of forethought and ambition: the turn operation is needed for Tasks 3 and 4 – as is the move operation of Task 2. So, abstracting them into individual PROCs makes sense. If you do that, you may as well use them in Tasks 1 and 2 ... which may as well be the place to develop and test them.

Keywords: mars


Question 48 (2010):

Submission reference: IN1942

In the Life on Mars assessment, I'm having problems comparing the colours of blobs seen by the camera with the colour input by the user.

During execution of the find.blob task, I'm printing the 'colour' INT passed in the find.blob; INT protocol, along with the blob[colour] from blob records that the camera sends.

The problem is that these never seem to be the same. Even after noting down the INT values for each colour the user can specify, I cannot see these reflected in the blob[colour] values. Worse yet, I can't match any reported blob[colour] values to any of the four known INT values of red/green/blue/purple ...

I assume that there must be some problem with receiving blobs from the camera, although I cannot understand what it is given that reported blob colours can't be matched with colours input.

Answer 48:

You are looking at the right things: the INT colour requested for the target blob, the blob[colour] values received from the camera. When the camera has blobs within range, it sends blob data with colour fields set to the colours of the seen blob. For the environment you are given, these will be red, green, blue or violet (not purple – see Question 45 (2010)). When the camera has "rocks" (represented by parts of the Mandelbrot image shown) within range, it reports blob data with colour fields set to those of the seen rocks (which are not colours from the set of possible blob colours).

Sorry – can't help much here! If still stuck, mail your seminar leader or me (p.h.welch@kent.ac.uk). If there's an obvious mistake, we may point you at it ...

Keywords: mars

Referrers: Question 65 (2010)


Question 46 (2010):

Submission reference: IN1941

For task 3 in Life on Mars, the task description says: "At the end of the search you should return the new heading of the robot relative to the heading you started at".

Will we lose marks if we return a relative heading of 120 degrees if the blob was located at a heading of 100 degrees? As the camera reports every 2 seconds, the blob may not be reported as soon as it comes into view, giving us an incorrect heading of the blob by the time it actually comes through.

Also: "If multiple matches are found, you may return any of them". Don't we specify a colour to look for, of which there will only be one? Or does this mean it should support returning any blob if there happened to be multiple similarly coloured blobs?

Answer 46:

Yes, you will lose marks for this. You must return the heading of the blob from wherever the robot is pointing at the time of making its report. If the robot spots a target blob when turning, it should stop turning and wait for the next report(s) from the camera. If the robot hasn't turned too much since the target was spotted, the target will still be in the scan. If not, it'll have to turn back – it knows the target is there!

The environment given has only one blob of each colour. Other environments may have many blobs with the same colour. Your robot must be able to cope with this. Returning the first one found (if any) is a simple and valid policy.

Keywords: mars


Question 45 (2010):

Submission reference: IN1939

My robot has trouble identifying the purple blob :( It can find all the others fine, but regardless of how close it is the the purple one, it just doesn't seem to detect it. Would the smaller size of the purple blob affect the robot's ability to see it?

Answer 45:

The small blob in the environment given is violet, not purple. Apologies – I agree that's not terribly obvious!

Keywords: mars

Referrers: Question 48 (2010)


Question 44 (2010):

Submission reference: IN1938

What is a "spurious move.complete" and why does my robot tell me that every time it finds a hazard?

I am reporting hazard.detected when one is found, but only move.complete when the move is completed (obviously), which it isn't if a hazard is found because I am telling the robot to stop.

Answer 44:

The "spurious" messages are displayed if the mission.control process (back on Earth) receives an unexpected message from the robot.

If the robot is commanded to move and completes the move to the distance asked, it should report back move.complete. If the robot is commanded to move and does not complete the move (because it detects a hazard), it should report back hazard.detected only – it should not precede that hazard report with a move.complete! This is as specified in the life_on_mars PDF (section headed "Task 2"). If the robot replies with both messages, the first is taken as the full answer and the second as spurious.

Keywords: mars

Referrers: Question 57 (2011) , Question 57 (2011)


Question 42 (2010):

Submission reference: IN1937

On the moodle page, it links to an example implementation for assessment 5 but "its solution for Task 2 is not entirely correct". I assume this means that you can spam move commands to the robot to make it slowly edge towards a hazard and eventually make it go through the hazard? At the moment, my robot will stop when it detects a hazard and moves back even if I've moved it very close to the hazard. I'm having difficulty thinking of a way to determine if a move command will increase the sensor value without actually moving it though. Any tips? :) I've come up with a few ideas but they will fail if say I move forward, get within hazard range, turn 180 and then move backwards.

Answer 42:

Yes – the demo implementation is incorrect since it allows move commands to be sent that bludgeon the robot through obstacles.

The robot should move as commanded, unless a hazard level in the direction of movement is too high (and you have to decide what is "too high") – in which case, it should stop. (It doesn't need to back off, although that may be a nice touch and won't be marked down!) If a robot that stopped short is told to continue moving towards the hazard, it should not move! If a robot was moving forward and stopped (because a hazard was detected) and is then turned 180 and told to move backwards, that is still towards the hazard and it should not move.

The robot has two forward hazard detectors (front-left and front-right) and two backward detectors (back-left and back-right). These detector channels should always be monitored – the robot should always know the latest hazard level from all four detectors. See Question 40 (2010) and Question 32 (2010) (second paragraph in each answer).

Before and when moving forwards, the robot should check its forward hazard levels. Before and when moving backwards, the robot should check its backward hazard levels. To determine "if a move command will increase the sensor value without actually moving it", just check the relevant hazard levels.

Now, with the robot always monitoring all detectors (even when turning), its hazard levels will always have the most up-to-date values available. If the robot moves forward too close to a hazard and stops, one of its forward hazard levels was too high. If it then turns 180 degrees, its forward hazard levels will be OK and one of its backward levels will now be too high – if then asked to move backwards, it won't! :)

Keywords: mars


Question 41 (2010):

Submission reference: IN1936

Hi, Having a small issue with the life on Mars assignment.

I know all the protocols are in the file mars-robot.inc, and I have stored it in the same folder as my mars-main.occ file (and indeed all the other files to do with the assignment), but my program can't find any of the protocols defined in it. The compiler keeps coming up with statements like "P.MOTOR.FEEDBACK. is not declared".

I was wondering if I needed to write an #INCLUDE statement for it, but I'm not sure. Any help would be greatly appreciated!

Answer 41:

Make sure the file you are compiling is mars.occ, which has just 7 lines (3 comments, one blank, 3 includes). Do not try to compile the mars-main.occ file on which you are working!

If this is not your problem, contact your seminar leader or me (p.h.welch@kent.ac.uk).

Keywords: mars


Question 40 (2010):

Submission reference: IN1935

Hi, I am currently quite stuck on the Life on Mars assessment, part 3, where you have to scan for a blob and return if you've found it.

I don't quite understand how the robot's camera is supposed to work, and looking over the mars-sim.occ file hasn't helped either.

I have two ideas on how it works, though neither really help when I try to work my code around them:

Am I missing something obvious? The lack of questions on this make me feel like I'm doing something stupid. The document isn't very clear, at least.

Answer 40:

The camera is working all the time; its images are scanned and data on blobs, if any, identified and sent towards your robot.control process every few seconds – regardless whether your process inputs them or not.

If your robot.control does not input camera data for a while, the data is likely to be stale (e.g. the bearing of the blob ... because the robot has turned since the blob was found). It may be that the image processing sub-system buffers up many stale blob findings (and may overwrite some), if your robot.control does not take them. To avoid this, your system should always be prepared to take sensor data (from its camera, hazard detectors and motor feedback) whenever they might be available. For the camera and hazard detectors, that is at all times. For the motor feedback, that is whenever the robot is moving. Your robot control should never listen solely to one sensor channel: if it does, it will have to wait for some data to arrive ... which may not be for a second or two, which is far too long to be doing nothing! See also the second paragraph in the answer to Question 32 (2010).

Hope this helps! You do not have to understand the code in mars-sim.occ (or mars-robot.inc), though you are welcome to browse!

Keywords: mars

Referrers: Question 42 (2010)


Question 39 (2010):

Submission reference: IN1934

Hey, This is in relation to my earlier question, Question 32 (2010). After doing the steps suggested in Question 31 (2010), I now receive the following error:

  The Transterpreter encountered s runtime error:
  STOP error
  The error occurred on or around line 288 in mars-sim.occ
  mars.tbc exited with error code: 10

I have also downloaded the source again but still receive these two errors. Any idea how to fix it?

Answer 39:

Your program should not be executing line 288 of mars-sim.occ!

The only way it could do this if line 10 of mars-sim.occ has not been commented out – which the answer to Question 31 (2010) tells you to do.

Make sure you have cleared your browser's cache when looking at the Life on Mars web page. Make sure the starter code you are downloading is the latest version: life_on_mars-20101130.zip, which has been on-line since last Tuesday (30th. November). This starter code does not need any editing on the mars-sim.occ (line 10 is already commented out).

Keywords: mars


Question 35 (2010):

Submission reference: IN1929

For the Mars Rover assignment it mentions in "Starting out on Mars" page that we should consider using the IABS function. Will we lose any marks for not using it?

Answer 35:

No – you won't lose marks for not using it ... but using it may help you write simpler code.

The IABS function takes an integer argument and returns it without any minus sign (if present). So, for example, IABS(21) returns 21 and IABS(-21) returns 21. The function is trivial and declared in the file mars-robot.inc.

Keywords: mars


Question 32 (2010):

Submission reference: IN1922

Hey, I have a few questions related to the life on Mars assessment. Should each task be implemented in a PROC and then wired up in PROC robot.control.

Also I had the error:

    exiting... (unimplemented instruction)
    The error occurred on or around line 91 in cordic.occ
    mars.tbc exited with error code: 999

That was described on the web page linked from moodle, I have followed the directions to fix this but I am now receiving another error that says:

    The transterpreter has encountered a runtime error:
    STOP error
    The error occurred on or around line 29 in ppmwrite.occ
    mars.tbc exited with error code: 10

Any idea on what im doing wrong or how to fix it? Thanks.

Answer 32:

Task items 1 and 2 could be answered in-line – i.e. without abstracting the code into a separate procedure (PROC). However, items 3 and 4 require the robot to perform more than one turn and/or move, so having procedures for moving and turning would be very helpful here. The trick is to define sufficiently general abstractions (i.e. parameter list and parameter list meaning) so that they are easy to use when doing items 3 and 4. The simple way to test these abstractions is, of course, to use them for items 1 and 2, which also yields a more elegant solution.

The PROCs suggested in the previous paragraph would be used in SEQuence with other code. You may want to define and run other PROCs in PARarallel - so that, for example, messages arriving from the motors, camera or hazard detectors are always accepted and saved (perhaps in a one-place overwriting buffer?) ... so that the latest (and not stale) reports are always available to the robot control process. But you could do this instead by ALTing on all those motor/camera/hazard channels whenever you need input from any one of them.

Re. your other problem with runtime error from the transterpreter, see Question 31 (2010). If that doesn't fix it, let us know again – thanks.

Keywords: mars

Referrers: Question 39 (2010) , Question 40 (2010) , Question 42 (2010)


Question 31 (2010):

Submission reference: IN1924

Why is it that after closing down the graphics panel that opens up once mars.occ is run, the transterpreter encounters a STOP run-time error forever after?

I have to delete the files and unzip them again just to be able to re-run the program. This happens when either closing the simulation or pressing the stop button JEdit.

I have downloaded the more recent TVM.

Answer 31:

There seems to be a bug with our code that writes out the "background.ppm" file, once it's been computed. Given that the starter zip file includes this file, your program doesn't have to make it. So, the work-around to our bug is not to make that file. To do this, comment out line 10 of the file "mars-sim.occ" – i.e.

  --#DEFINE GENERATE.BACKGROUND

The starter zip file has now been updated with the above work-around.

Keywords: mars

Referrers: Question 32 (2010) , Question 39 (2010) , Question 39 (2010)

2009

Question 58 (2009):

Submission reference: IN1858

I notice for Question 56 (2008), you say that the person's code is probably wrong because ticks are expected to increment in single units.

However, I am having the exact same problem as the person that asked that question, where all my movement is 10mm at a time (and on the odd occasion, 20mm).

And for my turning, I always seem to turn 2 degrees at once (or occasionally 4).

I don't see where in my code there is any problem where I'm not taking the machine responses fast enough, and the fact it's dead on 10 or sometimes 20 suggests to me it's something else? otherwise I should expect to see values around say, 9-11 (however long it takes my computer to run the statements before I wait for a new tick again).

My code is like this (feel free to delete before response :) ):

    ...  code deleted, :)

Even if I comment out the debug print lines, I still move in chunks of 10 (tried moving 14, went 20).

Also, as a side question, what is the set tolerance for move distances? I'm aware for turning it's 5 degrees either way.

Answer 58:

The answer in Question 56 (2008) is, as someone once said about Watergate, non-operational.

The exercise does not specify what numbers (representing degrees of turn or millimetres of movement) are returned by the motor feedback channel. Please see Question 52 (2009) for an answer that is operational! This also answers your side question.

Keywords: mars


Question 57 (2009):

Submission reference: IN1857

When looking at answers with key lifeonmars, the first one I saw was the one asking for an extension to thursday. I thought it was for us at first and was happy, but then I noticed this was a question from last year.

We all (or at least, all second year compsci students) had an assignment for co525 dynamic web due in today (which is worth 25% of the total marks for that module. 50% of the coursework marks).

Because of this it seems most people have prioritised that work since it was due in first and is worth a lot more in terms of marks, but has left us with less time for the final occam assessment. I, and most others I imagine, would be grateful for a little more time to do the occam to a standard we would be happy with.

If possible, could you give us the no-penalty re-submission extension to thursday? This is the last piece of coursework due in this term now so it won't interfere with any other deadlines (I speak for people on the same course as myself here, can't make assumptions).

Cheers.

Answer 57:

I have asked the coursework manager if this can be done. Watch this space for an answer ...

OK, an extension of 24 hours has been authorised (pushing it back further runs up aganist other deadlines). So, the submission directories will now remain open throughout Wednesday (16th. December, 2009).

Keyword Index: I've merged the keyword list lifeonmars into the mars list. Apologies for having two lists before!

Keywords: mars


Question 56 (2009):

Submission reference: IN1856

My move command is not working, I'd appreciate it if you could hint/tell me why. Thanks.

    ....  code omitted

Answer 56:

Sorry! It says at the top of each of the Q&A pages: "When asking questions, please do not simply paste in your code and ask what is wrong with it ...".

Look at your code and ask: "Why should this code work?". Read through it line by line, noting everything that happens.

Two problems with your code are of general interest, so can be addressed here.

First: you only need to issue a motor.cmd (e.g. to move or turn) just once. That starts the robot moving (or turning) until you send a stop message.

Second: you do, of course, have to listen to the motor.feedback channel while it's moving or turning (i.e. in a loop) until you can deduce the move (or turn) is complete. However, if you haven't started to move (or turn), there will be nothing arriving down motor.feedback; so don't listen there before sending the move (or turn) command ... or you will wait forever!

Keywords: mars


Question 55 (2009):

Submission reference: IN1855

Considering that the life on mars assignment is due in on tuesday, is there any possibility of knowing how to submit it yet?

Answer 55:

Submission directories will be set up in the usual place. This assignment is number 5 – hence, look on raptor (or swallow):

    \proj\co538\assess5\

They should appear some time tomorrow (Monday).

Keywords: mars


Question 53 (2009):

Submission reference: IN1853

Is it possible for an implemented example to be made available for life on mars (like you did with dining philosophers), so we can see how the program is meant to work?

Answer 53:

OK – copy all the files on raptor from \courses\co538\answers\mars-transterpreter\. Read the README.txt file.

Keywords: mars


Question 52 (2009):

Submission reference: IN1854

You've stated before in previous answers (Question 36 (2008)) the acceptable tolerance of turning (e.g. turning 91 instead of 90), but what tolerance would you accept for moving? Would this be the same?

Answer 52:

The numbers coming back on the motor.feedback represent either degrees turned (if your command was to turn) or millimeters moved (if your command was to move). The web page for this exercise says: "You can’t (and shouldn’t) rely on these ticks being a fixed value anywhere in your code." If you look at these numbers (e.g. by using the log channel), you will see that they are not just 1 or -1, though they do seem to be constant. However, you can rely neither on the particular values being reported nor their constancy – the robot is a long way away and in an alien environment and motors and sensors will wear down.

So, overshoot on both turning and moving is not preventable, but it must be kept to the minimum possible.

Keywords: mars

Referrers: Question 58 (2009) , Question 56 (2008)


Question 51 (2009):

Submission reference: IN1850

For life on mars, I'm trying to work out if we need lots of headache-y non-determinism. It says, interplanetary internet is minutes/hours delay. So we could assume that turn 20 will complete. In fact, it says it should return move complete or hazard detected. However, somewhere further on it says commands override the previous - preventing arc turning. I would find it much easier if we made each command complete before any further, but I presume you may wish to overwrite a long command like find.blob with a turn on the spot (or possibly not because that would prevent the return of blob.not.found etc.).

Answer 51:

Carl Ritson (msl9@kent.ac.uk) writes ...

I assume this is a reference to: "each new motor command overrides the previous mode". That statement describes the behaviour of the motor command stream output by your robot.control process, not the commands sent to it from its operator (back in mission control).

Your robot.control process only needs to deal with one operator command at a time (turn, move, find.blob, etc). There is no need to deal with the present command being overridden; no further commands will be issued until the present command completes and returns its response to the operator.

Keywords: mars

2008

Question 60 (2008):

Submission reference: IN1727

With the third year project deadline last Thursday and lots of other commitments all coming to a climax this week it's been a real struggle to finish the Life on Mars assessment in order to get Task 4 working correctly. I've asked a number of colleagues on the course if they have manage to complete it fully but it appears that very few have. As this is the first time the assessment has been run, and the hence the best timing of the assessment hasn't perhaps yet been fully determined, is there any chance you could consider extending the deadline for everyone, perhaps to Thursday midnight?

Answer 60:

OK. You'll have to mail me (p.h.welch@kent.ac.uk) your solution. Imrpoved re-submissions may also be mailed to me. No penalty if received by end of Thursday, 9th. April.

Keywords: mars


Question 59 (2008):

Submission reference: IN1726

For task 3, I have the following;

  camera ? blob
    SEQ
      clr := blob[colour]
      IF
	 clr = colour.in 

where colour.in is passed as a parameter. Why do I get a runtime error when this bit of code is run? It always fails on the IF statement. All I want to do is to compare the blob colour value found by the camera with that given, if it is the same then stop and report back to operator.

Answer 59:

Assuming that colour.in is declared elsewhere, have you checked that your IF statement has a TRUE condition – IF statements without the TRUE condition will work as long as one of their conditions is passed, but if you get into a state where none of its conditions hold, a runtime error is thrown.

For further information, see the questions under the if keyword, specifically Question 2 (2006).

Keywords: mars


Question 58 (2008):

Submission reference: IN1725

I've finally got my robot to rotate x degrees, but then the transterpreter sits there going "Response: ..." How can I fix this?

Answer 58:

The simulator expects you to return an appropriate protocol variant from the protocol P.OPERATOR.RESPONSE once you have completed the turn, along with the amount turned before it will continue. Your simulator is waiting for this response, hence the message.

Keywords: mars


Question 57 (2008):

Submission reference: IN1722

I'm really struggling with task 2. Can you give any more tips as to how we are supposed to implement this? Thanks.

Answer 57:

It may be easier to deal with solving the problem in two steps.

First, make your robot move forward on command, which requires a similar approach to turning: starting the motors with an a command and then reading the ticks until the condition is satisfied; then returning the correct protocol variant to signal a completed move.

Now add the second behaviour: hazard detection. Once you're in motion, you need to check that you have not exceeded a hazard threshold using the information given to you by the hazard sensors. If you have encountered a hazard, you need to stop moving and return the appropriate protocol variant to indicate a detected hazard.

Keywords: mars


Question 56 (2008):

Submission reference: IN1721

Hi there, with the move command for the current assessment I seem to only be receiving feedback in blocks on 10mm. Therefore, if I execute a move command for example for 14mm, the robot potentially moves either 10mm or 20mm (depending on hazards). Is this acceptable, or am I doing something wrong ?

Answer 56:

Apologies! The answer below is no longer correct. Please see Question 52 (2009) for the currently operational answer.

[It sounds like something is wrong with your code, ticks would be expected to increment in single units. Note that if you don't read the motor feedback channels, the ticks will be summed (so if you're not reading it frequently enough, you might find that the increments you receive are quite large). You've discovered the problem with allowing these ticks to be summed, in that it makes moving a precise amount (or within set tolerances) difficult.]

Keywords: mars

Referrers: Question 58 (2009) , Question 58 (2009)


Question 55 (2008):

Submission reference: IN1718

For the second, "move", command of lifeonmars , do we report the distance moved or the relative position? My understanding is: if we move 100mm back then the distance we moved would be 100mm, but the relative position would be -100. Thanks.

Answer 55:

The PDF and protocol definition both ask for the distance moved (i.e. 100mm in your example), but either is acceptable.

Keywords: mars


Question 54 (2008):

Submission reference: IN1716

When moving, I have the problem that once a hazard has been detected, I can't move away from it. From what I understand about how the hazard detectors work, I should only be receiving values when the hazard level changes. Therefore, If I detected a level 9 hazard which has caused my robot to stop, upon moving away from the hazard the next value I receive should be a level 8. However, I suspect that I'm infact I'm receiving a level 9 which is causing the problem. Could you confirm this? Thanks.

Answer 54:

There is a buffer between the hazard detectors and your control process which filters changes and outputs the latest value. In the event that your program cannot keep up with hazard data events, a duplicate value may be output from this buffer in the hazard detection.

If you need consistently unique values, then you will need to implement a filter process within your control program.

Keywords: mars


Question 53 (2008):

Submission reference: IN1719

On Task 3 for Life On Mars, I am trying to take a Real32 from the BLOB bearing field and add it to an INT.

This is to get its location from my starting point. However, I am unable to add it to an INT; and I am unable to cast it to an INT. I'm really stuck on this.

Answer 53:

Casting from REAL32 to INT requires you to specify what you want to do about the loss of precision in fractional numbers. See the last part of Question 111 (2003) for an explanation.

Other anonymous questions from the past dealing with casting are under the keyword cast if you need further help.

Keywords: mars , cast

Referrers: Question 54 (2010)


Question 52 (2008):

Submission reference: IN1720

I'm getting a really strange error. STOP ERROR line 1015 mars-sim It happens when I search for a blob. If the robot doesn't find the blob it starts turning, then after around 80degrees of rotation this error occurs, it seems to be the CASE section of mars-sim where it handles the protocol referring to the BLOB. I can't figure it out because it happens mid-way through a turn, the robot isn't doing anything but turning at this point.

Answer 52:

Line 1015 of mars-sim.occ contains the CASE statement which reads protocol responses for the find.blob command. The STOP error implies that you are returning a response which is not covered within the CASE statement (i.e. not one of blob.found or blob.not.found.)

Keywords: mars


Question 51 (2008):

Submission reference: IN1709

Ive finally got to task 4 and am having a difficult time working out the relationship between bearing and size. I get that you use the two blobs bearings to turn to a particular angle (in order to face middle of the blobs), but i cant figure out how to judge the distance to move. i imagine it would be to do with size, but this changes depending on the bearing, as well as the robots distance from the blobs. any chance you could give us a little more info on bearing and size's correlation with each other so we can use them to work out the distance?

Answer 51:

An approach to figuring this out would be to go forward toward the blobs, in the right direction, and print out the size values for the blobs (making sure you're throwing away the stale camera data for the 2 second stabilization period while doing this). It would be non-trivial to try and work out a distance to the object based on the size and the bearing. The size value is the percentage cover of the vision arc that the blob has. A hint would be that if you've gone right between the two points, it may well be that you've lost sight of the two objects from your frontal vision (because they are to your sides). The blob size will get larger as you progress toward the blobs.

Keywords: mars


Question 50 (2008):

Submission reference: IN1713

For the 4th task, the "Mission to Mars" document states: To get full marks you will need to appropriately modify the response protocol such that it returns the new relative position of the robot and allows the reporting of any other error conditions encountered. Could you expand on this a bit please? What is meant be relative position? Should we just return the distance travelled, or is more information required? Also what is meant by reporting errors? What type of errors? Many thanks.

Answer 50:

Your assumption that relative position is the distance travelled is correct. There are times when writing software where you must make the choices about operational behaviour. We have purposefully left the list of error conditions you need to add unspecified — you should apply knowledge you have gained from your course and the specific behaviour of your solution to craft a suitable answer.

Keywords: mars


Question 48 (2008):

Submission reference: IN1712

In task 4 of Life on Mars: to get full marks, how much accuracy is required for dropping the sensor probe between two blobs? Does it have to be dead at the centre??

Answer 48:

The sensor probe doesn't have to be placed exactly at the centre, you won't lose marks as long as the sensor is dropped in the area between the two coloured blobs, however it would be nice if you tuned your solution to put it as close to the center as possible. (Such that if we sent your robot to deploy the sensor from many different positions, it would probably end up putting it in roughly the same position each time).

Keywords: mars


Question 47 (2008):

Submission reference: IN1708

Hello, lifeonmars problem again! I am having the following curious issue. The results are surprising when I give this set of instructions: 1) Find blue 2) Move backwards such that the blue blob is out of camera range 3) Find blue Surprisingly it then - without turning but after a 2 second scan - returns that it has found the blue blob at the same bearing and size as before. This also occurs when you, for example, rotate a random amount instead of moving; or indeed when you do any combination of move/turning that gets you out of the range of the blue. Staying in range of the blue but manipulating the angle/distance seems to work fine, though. What's going on?!

Answer 47:

The object camera takes a certain amount of time to stabilize its data (camera scan time) after you have moved, you should be careful that when you start looking for objects, you have emptied any stale data that is coming from the camera (it will take at least 2 seconds to receive more good data, due to the scan time). If you don't empty this data you are liable to get stale results which don't reflect the state of the environment (which is what it sounds like in your question).

Keywords: mars


Question 46 (2008):

Submission reference: IN1702

I noticed that a new hazard value is sent every 10 mm you get closer to a hazard. So when you move forward until at a level of 9, moving forward again will go forward 10 and then detect a 10 (Hit). Because of the way hazard values are sent, this can't be avoided. Moving forward again will keep moving you forward 10 and detecting the hazard until you have past through hazard. Is this functionality ok? Or should we do something like move backward 10 before we move forward ... so we never hit anything?

Answer 46:

You should remember the last set of hazard values you received, as you only receive values when the hazard level changes. If you've moved away from the object, then you will receive values which will be lower, thereby making your stored values amenable to movement. You should check these stored values before moving at all, to prevent the problem you mention in your question.

Keywords: mars


Question 45 (2008):

Submission reference: IN1692

Hi, In lifeonmars, so far I have implemented turn and move as their own PROCs. However, there are two problems I have encountered, both stemming from this: I'm not sure how to communicate back to the robot.control process from these new PROCs. Firstly, in find.blob I can't call turn as I'd like to because it's turn that's outputting turn.complete signals (and so when I call it from find.blob, a signal is received that isn't expecting and things break). Secondly, I need move to communicate the current status of the hazard detectors to some variable somewhere, so we don't move forward until the hazard status changes everytime (e.g. we might be at 9, move forward, hit 10, and then we've crashed). The first problem I could (untidily) solve with a boolean parameter saying whether to signal or not. Or I could research into MOBILE stuff, but that seems overly complicated. It seems like there must be an easier way that solves this problem and the second one too. I can't add parameters to the robot.control process beacuse it's called externally with the set parameters. So adding communication channels to the other processes is out. So I'm a bit stuck! Any hints?

Answer 45:

You can use processes and channels inside the robot.control process, with their own protocols. You probably don't want to let the turn & move processes reply to the messages, because this will impede their re-use later on (as you have found). You could use a client/server protocol internally between your main loop and these other processes, asking them for the action and returning the relevant results to your control process - which can return the appropriate variables. You shouldn't need to modify the top level of the robot.control process if you are adding processes inside of it, since the channels and processes are declared internally.

Keywords: mars


Question 44 (2008):

Submission reference: IN1693

For Life On Mars, when implementing turn, it states we should expect to actually turn a few degrees difference to the amount specified. In order to do this there obviously needs to be a check of degrees actually turned against degrees requested. Am i right in assuming we should keep going til equal or more than request, and that we should not stop short when we are a few degrees less than the request?

Answer 44:

If you are integrating the ticks that come back from the motors you will most likely have a value which stores the amount that has been turned in total. It doesn't make sense to stop the turn early, because you may be able to turn exactly to the required heading, but you may find you are over because the ticks add up to more than the amount required. Stopping short is not really a natural property of the system, and is not something we would expect. The expectation would be +1 on most values, but I have posted below about the acceptable tolerances.

Keywords: mars


Question 43 (2008):

Submission reference: IN1691

I always have strict on, however unlike all the other assignments, with the 'life on mars' assignment, are you aware that a load of error messages spew out of the compiler when strict is on?

Answer 43:

Since we intended for you to be using the Transterpreter, and do not tend to use the --strict flag to kroc ourselves, we didn't notice these messages. They do not affect the functioning of the simulation.

Keywords: mars


Question 42 (2008):

Submission reference: IN1695

In lifeonmars task 2, what integer hazard.detected amount is considered "too close" ?

Answer 42:

You can experiment with the simulation, driving the robot through the wall (assuming it isn't doing hazard detection already) to see the hazard values as it approaches and hits the surface, and choose a value that you feel is appropriate. You could use a hazard value of 9 as a boundary between 'acceptable' and 'too close'.

Keywords: mars


Question 41 (2008):

Submission reference: IN1682

Hi im trying to use the log CHAN for debugging the life on mars thing but nothing's happening. E.g.

    out.string ("x", 0, log!)

Am I doing anything wrong? I tried sending a FLUSH afterwards as well, but so far nothing is happening...???

Answer 41:

We've tested the log channel, and it appears to work in all the cases we tested. The problem may lie in other parts of your code, as what you have done and explained in your question should work (the flush is important, as you note, when using the TVM).

If you need further assistance, you should contact your seminar leader with the actual code in question.

Keywords: mars


Question 40 (2008):

Submission reference: IN1665

In task 4 of the "Mission to Mars" assignment:

The "bearing" field, of the BLOB structures returned, can contain both positive or negative numbers. What do these numbers represent and how can they be used to position the robot. Any hints ???

Cheers.

Answer 40:

The bearing field of the BLOB structure is the offset of the object from the robot's dead-reckoning of 'forward'. If you do a scan with the camera and find a BLOB at bearing -30, you could turn left 30 degrees to make the robot point at the object.

Keywords: mars


Question 39 (2008):

Submission reference: IN1678

Hi I'm looking at these hazard channels on the robot. What is the coverage of the channels? Are the channels split by 90* so 2 for the front and 2 for the back? Or are they done starting at a 45* offset so that there's one for the front and back and 2 more for the sides? (although this makes less sense to me as the side ones would be fairly redundant being as the robot only actually moves forwards and backwards). Anyway my main question is - how are the channel array numbers applied? Thanks.

Answer 39:

The document isn't very clear about this (I'll think about how to improve it). There are some constants in the mars-robot.inc file to help with this task though.

You should think of each hazard sensor as an object camera, pointed at the center of the 45 degree offsets (i.e front left, front right, back left, back right), which covers 90 degrees of scan range (front to left, front to right etc.) The hazard value you get on each channel is created by assessing the hazard using the minimum distance to an object in each quadrant.

The constants should help you get a grip on where things are pointing/looking, and you can use them in place of numbers when writing code that uses the hazard array. Hope this helps!

Keywords: mars


Question 36 (2008):

Submission reference: IN1666

Regarding Mission to Mars, is it acceptable for the operator to send a command, for example, turn -180 degrees, and to have the robot turn -181 degrees?

Answer 36:

It is acceptable to turn slightly more than the amount, and the tolerance suggested here is fine. If the difference in the amount turned and the amount commanded is much more than 3, you should investigate your code, as there is probably a bug.

It certainly wouldn't be acceptable to turn >185 if the user asked for a turn of 180.

Keywords: mars

Referrers: Question 52 (2009)


Question 35 (2008):

Submission reference: IN1656

Why does the robot always turn left no matter which one of the commands (turn.left or turn.right) you send to it ???

Is this deliberate and we are supposed to fix it, or otherwise?

Answer 35:

This is most definitely not deliberate, and should not be occuring. A test of movement commands by replacing the SKIP in your default mars-main.occ file with motor.cmd ! turn.left and motor.cmd ! turn.right indicates that the robot can move both ways, so you may want to check the other pieces of your code.

Note that your task is to implement the movement code upon receiving a turn command from the console, which will accept positive values to turn clockwise (right) and negative values to turn anti-clockwise (left). The motor.cmd channel accepts the turn.left and turn.right protocol variants to initiate turns in the respective directions.

Keywords: mars

Valid CSS!

Valid XHTML 1.0!

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
Last modified Mon May 20 13:50:28 2013
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.