Please login or register.

Login with username, password and session length

News:

Registration is only required if you want to post, and is not needed to read any posts. To avoid excess 'spam' accounts, all accounts where no posts have been made will be deleted after two weeks. Please register again if you wish to post.

Author Topic: Creating a controller program  (Read 11899 times)

January 21, 2014, 11:11:12 PM
  • Member
  • **
  • Posts: 12
    • View Profile
I am working with my kids on a science project that requires us to write a program (most likely in python) that would control and track a boat, among other things.  I think BridgeCommander would be a great simulator for us to use to test our programming before putting it on the boat itself.  I am going through the documentation now to see how I could model our boat, but I am not exactly sure where to start as far as controlling the boat from an external program (instead of the built-in UI).  Could you point me in the right direction on how I could go about it?

Thanks.

January 23, 2014, 06:32:37 PM
Reply #1
  • Administrator
  • Member
  • *****
  • Posts: 99
    • View Profile
That sounds an interesting project. Will your controller give the speed and heading of the boat, or the rudder and engine settings? Both approaches should be possible, using the UDP networking messages.

These are defined in http://bridgecommand.co.uk/Doc/networkprotocol.php

If you are controlling the engine and rudder settings, the boat's dynamics will be simulated in Bridge Command. For this approach, you'd run Bridge Command in 'Networked (Main)' mode, but instead of connecting to the 'Map Controller', you would connect to your own controller program, which would send 'MC' messages to Bridge Command via UDP. In particular, you would use the 'Engine and rudder failure record', using this to set the engine and rudder parameters.

Instead, if you are simulating the boat's dynamics yourself, giving speed and heading, you will need to use these to generate a current position in metres (relative to the South West corner of the sea area). You would then run Bridge Command in Secondary (3d) mode, and update its position by sending 'BC' messages to Bridge Command. You would also need to send at least one 'SC' message as well to set up the scenario.

Hopefully this and the documentation in http://bridgecommand.co.uk/Doc/networkprotocol.php should help you get this set up, but please ask if you have any questions.

January 23, 2014, 06:55:13 PM
Reply #2
  • Member
  • **
  • Posts: 12
    • View Profile
Thanks for the reply.  I think this is going to work really well.  The MC engine and rudder failure record will be precisely what we need as that is the level of control we will have on the actual boat.

As far as tracking the boat it looks like BC record will have the info I need.  Can you confirm the following statements relative to the position data that is in the BC record:
1.  If I was in the most southern and most western position, it would be reporting 0,0
2.  BridgeCommander would never send negative numbers for position.
3.  In order to translate to a latitude, longitude, I will need to take the latitude, longitude of the most south-western position and calculate it based on the meters from south and west points.

That should be a good start.  I am sure I will have some more questions as I start to create my world and boat.  Very excited about using this tool.  Thanks for building it and helping.

January 24, 2014, 03:52:19 AM
Reply #3
  • Member
  • **
  • Posts: 12
    • View Profile
Making progress...I am reading the BC records just fine.  Getting a memory access violation and crashing BridgeCommander when I try to send the MC record.  It is likely something I will figure out, but if you have any thoughts on what might be the issue, I would appreciate.

Thanks again for your help.
Ken

January 24, 2014, 08:41:11 AM
Reply #4
  • Member
  • **
  • Posts: 12
    • View Profile
I have my prototype working!!  So excited for how this is going to work out.

My MC issue was due to not putting the length integer at the beginning of the string.

January 31, 2014, 03:20:00 AM
Reply #5
  • Member
  • **
  • Posts: 12
    • View Profile
Is this true?
In order to translate to a latitude, longitude, I will need to take the latitude, longitude of the most south-western position of the scenario and calculate it based on the meters from south and west points that is returned in BC record.

January 31, 2014, 08:26:16 AM
Reply #6
  • Administrator
  • Member
  • *****
  • Posts: 99
    • View Profile
Sorry for missing this part of the question.

Bridge Command uses a very simple projection, and this means that the translation from the position in metres sent over UDP to lat/long is:

Longitude[Degrees] = (X[Metres]  * TerrainLongExtent / terrain_x_width) + TerrainLong
Latitude[Degrees] = (Z[Metres] * TerrainLatExtent *  / terrain_z_width) + TerrainLat

In this, X and Z are the position from the South West corner in metres (the values sent over UDP), TerrainLat, TerrainLong, TerrainLongExtent and TerrainLatExtent are all set in the world model terrain.ini file.

Terrain_x_width is the world model width in metres, and is calculated:
terrain_x_width = TerrainLongExtent * 2 * Pi * EarthRadius * Cos(TerrainLat + (TerrainLatExtent/2)) / 360

similarly for terrain_z_width:
terrain_z_width = TerrainLatExtent * 2 * Pi * EarthRadius / 360

(EarthRadius is defined as 6.371e6 metres, and this assumes that your calculations are all in degrees.)

As Bridge Command does not stop you at the limits of the world model, it may return a negative X and Z value.

I hope that this helps!

February 02, 2014, 05:11:33 AM
Reply #7
  • Member
  • **
  • Posts: 12
    • View Profile
Thanks a ton for continuing to help.  My formulas aren't returning the same as on the display of BC though.

Here is the code
Code: [Select]
     
      private const double EARTH_RADIUS = 6371000; //in meters
      double dTerrainXWidth = dTerrainLongExtent * 2 * Math.PI * EARTH_RADIUS * Math.Cos(dTerrainLat + (dTerrainLatExtent / 2)) / 360;
      double dTerrainZWidth = dTerrainLatExtent * 2 * Math.PI * EARTH_RADIUS / 360;

      double Longitude = (dXPosition * dTerrainLongExtent / dTerrainXWidth) + dTerrainLong;
      double Latitude = (dZPosition * dTerrainLatExtent / dTerrainZWidth) + dTerrainLat;

Here is the lat/longs I used in my calc from Santa Catalina:
Lat "32.58333"
Long "-119.0"
Lat Extent "1.0"
Long Extent  "1.0"

dXPosition is the first value of the Own ship location data from BC row.  dZPosition is second value.

See anything wrong here?


February 02, 2014, 09:39:02 AM
Reply #8
  • Administrator
  • Member
  • *****
  • Posts: 99
    • View Profile
I think the only change required is to convert the angle used in the Cos() function into radians - you're currently giving it an input in degrees.
i.e.
Code: [Select]
Math.Cos(dTerrainLat + (dTerrainLatExtent / 2))becomes
Code: [Select]
Math.Cos((Math.PI/180)*(dTerrainLat + (dTerrainLatExtent / 2)))

February 02, 2014, 07:15:24 PM
Reply #9
  • Member
  • **
  • Posts: 12
    • View Profile
Thanks again.  Getting closer...Latitude is on track, but still off a little on longitude.

I ran the boat aground so that I could play with it a bit.  With a X/Z position of 43944.3,94138.5 on the Santa Catalina map, the BC UI was showing long of 118 deg 31 min (and change).  My calc was showing 118.178848 which seems to come in at 118 deg 10 min (and change).

February 03, 2014, 10:10:09 PM
Reply #10
  • Administrator
  • Member
  • *****
  • Posts: 99
    • View Profile
Hi,

It may be worth checking through each calculation step comparing the result to a manual calculation to check for any problems. The code I've tested, based on what you posted above, seems to give the correct result. This is in C++:

Code: [Select]
#include <iostream>
#include <cmath>

const double EARTH_RADIUS = 6371000; //in meters
const double PI = 3.141592653589793;

int main ()
{
    //Inputs (in metres)
    double dXPosition = 43944.3;
    double dZPosition = 94138.5;

    //Terrain parameters
    double dTerrainLongExtent = 1.0;
    double dTerrainLatExtent = 1.0;
    double dTerrainLong = -119.0;
    double dTerrainLat = 32.58333;

    //calculate width of terrain in metres
    double dTerrainXWidth = dTerrainLongExtent * 2 * PI * EARTH_RADIUS * cos( (2*PI/360)*(dTerrainLat + (dTerrainLatExtent / 2))) / 360;
    double dTerrainZWidth = dTerrainLatExtent * 2 * PI * EARTH_RADIUS / 360;

    //find lat & long
    double Longitude = (dXPosition * dTerrainLongExtent / dTerrainXWidth) + dTerrainLong;
    double Latitude = (dZPosition * dTerrainLatExtent / dTerrainZWidth) + dTerrainLat;

    //print out
    std::cout << "Long: " << Longitude << std::endl;
    std::cout << "Lat:  " << Latitude << std::endl;

    return 0;
}

Gives:

Code: [Select]
Long: -118.528
Lat:  33.4299

Which matches with the BC output.

February 04, 2014, 05:37:26 AM
Reply #11
  • Member
  • **
  • Posts: 12
    • View Profile
Once again, big thanks.  found the issue and it was some misplaced parens. 

I really appreciate it and probably not the last time you hear from me, but hopefully, I can find someway to return the favor.

February 08, 2014, 02:18:06 PM
Reply #12
  • Member
  • **
  • Posts: 12
    • View Profile
I was going to simulate a really long journey, not really caring about land features.  So, I created an empty world and off we went.  Things seem to be working fine for several hours (no we aren't just sitting there watching it), but eventually it reports "Aground" and becomes unresponsive.  Is there anyway around this?

Thanks in advance,
Ken

February 09, 2014, 09:23:45 PM
Reply #13
  • Administrator
  • Member
  • *****
  • Posts: 99
    • View Profile
Hi, I haven't come across this before but can investigate more. When it became unresponsive, was the position displayed in Bridge Command reasonable, or did it go to Inf or NaN?

February 09, 2014, 09:32:34 PM
Reply #14
  • Member
  • **
  • Posts: 12
    • View Profile
I haven't had a chance to fully see what all worked and didn't work.  The position seemed to be reporting correctly and I think the BC records were going to my listener just fine.  It just said "Aground" for speed in the UI, but pretty sure the BC record reported it fine.  It didn't respond to speed and rudder changes in the UI, but I didn't try via network communications.

I realize that I am using the tool for something outside its original intent, so no rush.  It still will have a lot of value for our project.  Thanks for all your work on it and your responsiveness to this thread.