Author Archives: admin

CodeIgniter and XMLRPC

What are we going to do?

We’ll mimic what we already achieved in CodeIgniter and NuSOAP post using XMLRPC method.

So, we’ll create two endpoints, one is for getting a CD info (function name : getCdInfo) and the other is for getting all of CDs listed (function name : getCds).

We’ll still implement all of our function inside Welcome controller. The difference is that the registration process is placed inside index() function while the implementation is outside index() function but still within Welcome class.

The Server

Here’s the configuration and registration process inside index() function:

        public function index()
    {
    $this->load->library('xmlrpc');
        $this->load->library('xmlrpcs');
        
        //REGISTRATION AND CONFIGURATION
        $config['functions']['getCdInfo'] = array('function' => 'Welcome.getCdInfo');
        $config['functions']['getCds'] = array('function' => 'Welcome.getCds');
        $config['object'] = $this;

        $this->xmlrpcs->initialize($config);
        $this->xmlrpcs->serve();
    }

Notice how I defined the endpoint name and register it. So, getCdInfo endpoint will be implemented in Welcome controller and getCdInfo function, while getCds endpoint will be implemented in Welcome controller as getCds function.
Now, here’s the implementation:

        //IMPLEMENTATION
    public function getCdInfo($request)
    {
    $this->load->library('xmlrpc');

        $parameters = $request->output_parameters();

        $id = $parameters[0];  // first parameter
        $this->db->where('id', $id);
        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()==1) {
            $ret = $qcd->row_array();
        } else {
            return $this->xmlrpc->send_error_message('404', 'Invalid results');
        }

        $response = array(
            array(
                'titel'  => array($ret['titel'], 'string'),
                'interpret'    => array($ret['interpret'], 'string'),
                'jahr'       => array($ret['jahr'], 'int'),
                'id'     => array($ret['id'], 'int')
            ),
             'struct'
        );

        return $this->xmlrpc->send_response($response);
    }

    public function getCds()
    {
    $this->load->library('xmlrpc');

        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()>0) {
            $ret = array();
            $i = 0;
            foreach ($qcd->result_array() as $row) {
                $ret[$i] = array(array(
                        'titel'  => array($row['titel'], 'string'),
                        'interpret'    => array($row['interpret'], 'string'),
                        'jahr'       => array($row['jahr'], 'int'),
                        'id'     => array($row['id'], 'int')
                ), 'struct');
                $i++;
            }
        } else {
            return $this->xmlrpc->send_error_message('404', 'Empty results');
        }

        $response = array(
                $ret,
                 'array'
        );

        return $this->xmlrpc->send_response($response);
    }

getCdInfo takes one parameter, so, we need to pass $request as getCdInfo function parameter while getCds function doesn’t take any parameter, so we omit it.
Pay attention on getCds function, you’ll learn how I implement an XMLRPC endpoint that return an array of array (a data table).

The Client

Same as CodeIgniter and NuSOAP, for simplicity, we’ll implement the client as part of Welcome controller. Here’s the client code:

        public function testClient()
    {
    $server_url = site_url('welcome');

        $this->load->library('xmlrpc');

        //Call getCdInfo
        $this->xmlrpc->server($server_url, 80);
        $this->xmlrpc->method('getCdInfo');

        $request = array(array(1, 'int'));
        $this->xmlrpc->request($request);

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }

        //Call getCDs
        $this->xmlrpc->method('getCds');

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }
    }

getCdInfo call will output something like this:

array(4) {
  ["titel"]=>
  string(6) "Beauty"
  ["interpret"]=>
  string(16) "Ryuichi Sakamoto"
  ["jahr"]=>
  string(4) "1990"
  ["id"]=>
  string(1) "1"
}

While getCds will return something like this:

array(3) {
  [0]=>
  array(4) {
    ["titel"]=>
    string(6) "Beauty"
    ["interpret"]=>
    string(16) "Ryuichi Sakamoto"
    ["jahr"]=>
    string(4) "1990"
    ["id"]=>
    string(1) "1"
  }
  [1]=>
  array(4) {
    ["titel"]=>
    string(33) "Goodbye Country (Hello Nightclub)"
    ["interpret"]=>
    string(13) "Groove Armada"
    ["jahr"]=>
    string(4) "2001"
    ["id"]=>
    string(1) "4"
  }
  [2]=>
  array(4) {
    ["titel"]=>
    string(4) "Glee"
    ["interpret"]=>
    string(13) "Bran Van 3000"
    ["jahr"]=>
    string(4) "1997"
    ["id"]=>
    string(1) "5"
  }
}

As you can see, the output of XMLRPC method is the same as NuSOAP method. No fixing needed!
Here’s the complete source code of our controller:

defined('BASEPATH') or exit('No direct script access allowed');

class Welcome extends CI_Controller 
{
    public function index()
    {
    $this->load->library('xmlrpc');
        $this->load->library('xmlrpcs');

        //REGISTRATION AND CONFIGURATION
        $config['functions']['getCdInfo'] = array('function' => 'Welcome.getCdInfo');
        $config['functions']['getCds'] = array('function' => 'Welcome.getCds');
        $config['object'] = $this;

        $this->xmlrpcs->initialize($config);
        $this->xmlrpcs->serve();
    }


    //IMPLEMENTATION
    public function getCdInfo($request)
    {
    $this->load->library('xmlrpc');

        $parameters = $request->output_parameters();

        $id = $parameters[0];  // first parameter
        $this->db->where('id', $id);
        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()==1) {
            $ret = $qcd->row_array();
        } else {
            return $this->xmlrpc->send_error_message('404', 'Invalid results');
        }

        $response = array(
            array(
                'titel'  => array($ret['titel'], 'string'),
                'interpret'    => array($ret['interpret'], 'string'),
                'jahr'       => array($ret['jahr'], 'int'),
                'id'     => array($ret['id'], 'int')
            ),
             'struct'
        );

        return $this->xmlrpc->send_response($response);
    }

    public function getCds()
    {
    $this->load->library('xmlrpc');

        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()>0) {
            $ret = array();
            $i = 0;
            foreach ($qcd->result_array() as $row) {
                $ret[$i] = array(array(
                        'titel'  => array($row['titel'], 'string'),
                        'interpret'    => array($row['interpret'], 'string'),
                        'jahr'       => array($row['jahr'], 'int'),
                        'id'     => array($row['id'], 'int')
                ), 'struct');
                $i++;
            }
        } else {
            return $this->xmlrpc->send_error_message('404', 'Empty results');
        }

        $response = array(
                $ret,
                 'array'
        );

        return $this->xmlrpc->send_response($response);
    }

    public function testClient()
    {
    $server_url = site_url('welcome');

        $this->load->library('xmlrpc');

        //Call getCdInfo
        $this->xmlrpc->server($server_url, 80);
        $this->xmlrpc->method('getCdInfo');

        $request = array(array(1, 'int'));
        $this->xmlrpc->request($request);

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }

        //Call getCDs
        $this->xmlrpc->method('getCds');

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }
    }
}

CodeIgniter and NuSOAP

What are we going to do?

We’ll use NuSOAP to create a webservice using CodeIgniter and consume it using CI also.

In this tutorial, we’ll use “cds” table from “cdcol” database bundled from XAMPP. “cds” table content looks like this:

cds table content

cds table content

Download NuSOAP here : https://sourceforge.net/projects/nusoap/
Extract “lib” folder from nusoap-0.9.5.zip into your CI “application/libraries/”. We’ll create simple library warper for NuSoap.
Now, enter your CI “application/libraries/” folder and create a new file named “Nusoap_library.php”. Here’s the content:


We'll use default controller from CI, i.e. Welcome.php. We'll create two webservice endpoints: one for getting info about a CD based in it's "id" and one for getting all of CDs.
All of webservice data types definition, registration and implmentation will be placed inside Wellcome controller's "__construct()" function. Here's the complete code for "__construct()" function:

    function __construct() 
    {
        parent::__construct();

        $this->load->library("Nusoap_library"); //load the library here
        $this->nusoap_server = new soap_server();
        $this->nusoap_server->configureWSDL("MySoapServer", "urn:MySoapServer");
        $this->nusoap_server->wsdl->schemaTargetNamespace = 'urn:MySoapServer';

        //DATA TYPES
        $this->nusoap_server->wsdl->addComplexType(
            'Cd',
            'complexType',
            'struct',
            'all',
            '',
            array(
                'id' => array('name' => 'id', 'type' => 'xsd:integer'),
                'jahr' => array('name' => 'jahr', 'type' => 'xsd:integer'),
                'interpret' => array('name' => 'interpret', 'type' => 'xsd:string'),
                'titel' => array('name' => 'titel', 'type' => 'xsd:string')
            )
        );

        $this->nusoap_server->wsdl->addComplexType(
            "CdArray",
            "complexType",
            "array",
            "",
            "SOAP-ENC:Array",
            array(),
            array(
                array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:Cd[]")
            ),
            "tns:Cd"
        );

        //REGISTRATION
        $this->nusoap_server->register(
            'getCdInfo',
            array('id' => 'xsd:integer'),  //parameters
            array('return' => 'tns:Cd'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCdInfo',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get CD Info by ID' //description
        );

        $this->nusoap_server->register(
            'getCds',
            array(),  //parameters
            array('return' => 'tns:CdArray'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCds',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get all CDs' //description
        );

        //IMPLEMENTATION
        function getCdInfo($id)
        {
            $ci =& get_instance();
            $ci->db->where('id', $id);
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                return $qcd->row_array();
            } else {
                return false;
            }
            
        }

        function getCds()
        {
            $ci =& get_instance();
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                $ret_val=array();
                $i=0;
                //echo "masuk hasil";
                foreach ($qcd->result_array() as $row) {
                    //var_dump($row);
                    $ret_val[$i]=$row;
                    $i++;
                }
                //var_dump($ret_val);
                return $ret_val;
            } else {
                return false;
            }
            
        }
    }

The first step is loading the library and configuring your webservice:

$this->load->library("Nusoap_library"); //load the library here
$this->nusoap_server = new soap_server();
$this->nusoap_server->configureWSDL("MySoapServer", "urn:MySoapServer");
$this->nusoap_server->wsdl->schemaTargetNamespace = 'urn:MySoapServer';

We'll define a new data type for our CD info based on "cds" table structure:

        $this->nusoap_server->wsdl->addComplexType(
            'Cd',
            'complexType',
            'struct',
            'all',
            '',
            array(
                'id' => array('name' => 'id', 'type' => 'xsd:integer'),
                'jahr' => array('name' => 'jahr', 'type' => 'xsd:integer'),
                'interpret' => array('name' => 'interpret', 'type' => 'xsd:string'),
                'titel' => array('name' => 'titel', 'type' => 'xsd:string')
            )
        );

Now, our complex type that will hold list of CDs (array of CDs).

        $this->nusoap_server->wsdl->addComplexType(
            "CdArray",
            "complexType",
            "array",
            "",
            "SOAP-ENC:Array",
            array(),
            array(
                array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:Cd[]")
            ),
            "tns:Cd"
        );

After finished defining all needed data types, we'll register all needed webservice endpoint.
First endpoint is "getCdInfo" to get info about a CD based on it's "id". It takes one parameter ("id") and return a "Cd" type.

        $this->nusoap_server->register(
            'getCdInfo',
            array('id' => 'xsd:integer'),  //parameters
            array('return' => 'tns:Cd'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCdInfo',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get CD Info by ID' //description
        );

Second endpoint is "getCds" to get all stored CD in the "cds" table. It takes no parameter and return an array of CDs.

        $this->nusoap_server->register(
            'getCds',
            array(),  //parameters
            array('return' => 'tns:CdArray'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCds',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get all CDs' //description
        );

Registration is finished, now onto the implementation. Here's the code:

        function getCdInfo($id)
        {
            $ci =& get_instance();
            $ci->db->where('id', $id);
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                return $qcd->row_array();
            } else {
                return false;
            }
            
        }

        function getCds()
        {
            $ci =& get_instance();
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                $ret_val=array();
                $i=0;
                foreach ($qcd->result_array() as $row) {
                    $ret_val[$i]=$row;
                    $i++;
                }
                return $ret_val;
            } else {
                return false;
            }
            
        }

Pay attention, that I'm using "get_instance()" in order to query the database because we can't call "$this" inside these endpoint functions.
Next, we'll edit the default "index()" function, replace it with these:

        public function index()
    {
        $this->nusoap_server->service(file_get_contents("php://input")); //shows the standard info about service
    }

You may try accessing your webservice from your browser and see how it looks

WSDL schema

WSDL schema

webservice description

webservice description

Now, some fixing!

Before accessing our webservice via a SOAP client, we need to fix NuSoap library. Open "application/libraries/lib/nusoap.php", go to line 6132 and comment that line so it would look like this:

//$this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");

If you didn't do this fixing step, you'll get a blank result when calling an endpoint that return an array of data. Further testing using SoapUI will reveal some error like this:

A PHP Error was encountered

Severity: Notice Message: Array to string conversion Filename: lib/nusoap.php Line Number: 6132

Fixing is done, now we'll test it.
For simplicity reason, we'll put our client inside our Welcome controller. Here's the code:

    public function testClient()
    {
        $wsdl = 'http://localhost/ci_soap/?wsdl';
        $this->load->library("Nusoap_library"); //load the library here

        $client = new nusoap_client($wsdl, 'wsdl');

        $res1 = $client->call('getCdInfo', array('id'=>1));
        var_dump($res1);

        $res2 = $client->call('getCds');
        var_dump($res2);
    }

As you can see, the code is quite simple, $res1 will contain output from "getCdInfo" endpoint

array(4) {
  ["id"]=>
  int(1)
  ["jahr"]=>
  int(1990)
  ["interpret"]=>
  string(16) "Ryuichi Sakamoto"
  ["titel"]=>
  string(6) "Beauty"
}

and $res2 will contain an array of CDs as a result from calling "getCds".

array(3) {
  [0]=>
  array(4) {
    ["id"]=>
    int(1)
    ["jahr"]=>
    int(1990)
    ["interpret"]=>
    string(16) "Ryuichi Sakamoto"
    ["titel"]=>
    string(6) "Beauty"
  }
  [1]=>
  array(4) {
    ["id"]=>
    int(4)
    ["jahr"]=>
    int(2001)
    ["interpret"]=>
    string(13) "Groove Armada"
    ["titel"]=>
    string(33) "Goodbye Country (Hello Nightclub)"
  }
  [2]=>
  array(4) {
    ["id"]=>
    int(5)
    ["jahr"]=>
    int(1997)
    ["interpret"]=>
    string(13) "Bran Van 3000"
    ["titel"]=>
    string(4) "Glee"
  }
}

Here's the complete source code of our controller, in case you missed something:

defined('BASEPATH') or exit('No direct script access allowed');

class Welcome extends CI_Controller
{

    function __construct() 
    {
        parent::__construct();
        //$this->load->model(''); //load your models here

        $this->load->library("Nusoap_library"); //load the library here
        $this->nusoap_server = new soap_server();
        $this->nusoap_server->configureWSDL("MySoapServer", "urn:MySoapServer");
        $this->nusoap_server->wsdl->schemaTargetNamespace = 'urn:MySoapServer';

        //DATA TYPES
        $this->nusoap_server->wsdl->addComplexType(
            'Cd',
            'complexType',
            'struct',
            'all',
            '',
            array(
                'id' => array('name' => 'id', 'type' => 'xsd:integer'),
                'jahr' => array('name' => 'jahr', 'type' => 'xsd:integer'),
                'interpret' => array('name' => 'interpret', 'type' => 'xsd:string'),
                'titel' => array('name' => 'titel', 'type' => 'xsd:string')
            )
        );

        $this->nusoap_server->wsdl->addComplexType(
            "CdArray",
            "complexType",
            "array",
            "",
            "SOAP-ENC:Array",
            array(),
            array(
                array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:Cd[]")
            ),
            "tns:Cd"
        );

        //REGISTRATION
        $this->nusoap_server->register(
            'getCdInfo',
            array('id' => 'xsd:integer'),  //parameters
            array('return' => 'tns:Cd'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCdInfo',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get CD Info by ID' //description
        );

        $this->nusoap_server->register(
            'getCds',
            array(),  //parameters
            array('return' => 'tns:CdArray'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCds',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get all CDs' //description
        );

        
        //IMPLEMENTATION
        function getCdInfo($id)
        {
            $ci =& get_instance();
            $ci->db->where('id', $id);
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                return $qcd->row_array();
            } else {
                return false;
            }
            
        }

        function getCds()
        {
            $ci =& get_instance();
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                $ret_val=array();
                $i=0;
                foreach ($qcd->result_array() as $row) {
                    $ret_val[$i]=$row;
                    $i++;
                }
                return $ret_val;
            } else {
                return false;
            }
            
        }
    }
    
    public function index()
    {
        $this->nusoap_server->service(file_get_contents("php://input")); //shows the standard info about service
    }

    public function testClient()
    {
        $wsdl = 'http://localhost/ci_soap/?wsdl';
        $this->load->library("Nusoap_library"); //load the library here

        $client = new nusoap_client($wsdl, 'wsdl');

        $res1 = $client->call('getCdInfo', array('id'=>1));
        var_dump($res1);

        $res2 = $client->call('getCds');
        var_dump($res2);
    }
}

GMap.NET component : Moving Marker

WTH is GMap.NET?

Simply put: it’s an open source .net component that can show online mapping service (such as Google Map, Bing Map, OpenStreetMap) in your .NET app.
Download the binary here: http://greatmaps.codeplex.com/
Extract it. You’ll get the .net 2.0 and .net 4.0 version, since I’m using VS 2015, we’ll use the .net 4.0 version.

What will we do now is about how to move a marker inside the map (for tracking/visualizing object movement, etc). We’ll just move the marker randomly in this tutorial.

  • Create new VB Windows Form project
  • Add GMap.NET component into your project reference
GMap.NET component reference

GMap.NET component reference

  • Add GMap.NET component into your toolbar.
Add GMap.NET component step 1

Add GMap.NET component step 1

Add GMap.NET component step 2

Add GMap.NET component step 2

  • Now drag and drop the GMap.NET control into your Form, I name it myMap
  • We’ll also add another controls: 1 Button (name: btnMove), 1 Timer (name: tmr1), 1 Label (name: lblInfo)
List of components

List of components

I also add new bitmap resource into our project properties. This will be used as our marker symbol.

Resource for marker symbol

Resource for marker symbol

You can see the Form’s full source code at the bottom of this post. I’ll just point out some important parts:

  • Map initialization is on Form1_Load event code (zoom level, initial position, provider used, marker type, etc)
  • When you click on the btnMove, it’ll start generating new random position for our marker. The random change is happened in the timer event (tmr1_Tick)
  • The process to update the map visual is delegated into function update_map(), so it will run in different thread and the form still responsive
  • In this tutorial, we are using BingSatelliteMapProvider, you can use another provider such as GoogleMapProvider or OviSatelliteMapProvider. Just see MapProviders namespace to see all supported providers.

Running the app

Running the app


Here’s the full source code:

Imports GMap.NET
Imports GMap.NET.WindowsForms

Public Class Form1
    Private Delegate Sub UpdateFormDelegate()
    Private UpdateFormDelegate1 As UpdateFormDelegate

    Private copter_lat, copter_lon As Double
    Private WithEvents copter_marker As Markers.GMarkerGoogle
    Private WithEvents copter_layer As GMapOverlay

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        copter_lat = -7.076275
        copter_lon = 110.428952

        myMap.MinZoom = 5
        myMap.MaxZoom = 20
        myMap.Zoom = 17
        myMap.Position = New PointLatLng(-7.076275, 110.428952)
        myMap.MapProvider = MapProviders.BingSatelliteMapProvider.Instance
        myMap.Manager.Mode = AccessMode.ServerAndCache
        copter_layer = New GMapOverlay("copter_layer")
        copter_marker = New Markers.GMarkerGoogle(New PointLatLng(-7.076275, 110.428952), My.Resources.purple_drone)
        copter_layer.Markers.Add(copter_marker)
        myMap.Overlays.Add(copter_layer)
        myMap.UpdateMarkerLocalPosition(copter_marker)
        myMap.Invalidate()
        update_map()
    End Sub

    Private Sub tmr1_Tick(sender As Object, e As EventArgs) Handles tmr1.Tick
        Randomize()
        Dim delta_lat As Double = ((100 * Rnd()) + 20) / 10000000.0
        Dim delta_lon As Double = ((100 * Rnd()) + 20) / 10000000.0
        Dim not_lat As Single = Rnd()
        Dim not_lon As Single = Rnd()

        If not_lat >= 0.5 Then
            copter_lat += delta_lat
        Else
            copter_lat -= delta_lat
        End If
        If not_lon >= 0.5 Then
            copter_lon += delta_lon
        Else
            copter_lon -= delta_lon
        End If

        UpdateFormDelegate1 = New UpdateFormDelegate(AddressOf update_map)
        Invoke(UpdateFormDelegate1)
    End Sub

    Private Sub btnMove_Click(sender As Object, e As EventArgs) Handles btnMove.Click
        If tmr1.Enabled Then
            tmr1.Enabled = False
            MsgBox("Random Move stop")
        Else
            tmr1.Enabled = True
            MsgBox("Random Move start")
        End If
    End Sub

    Private Sub myMap_OnMapZoomChanged() Handles myMap.OnMapZoomChanged
        lblInfo.Text = "Info : Lat= " + CStr(copter_lat) + ", Lon= " + CStr(copter_lon) + ", Zoom Level= " + CStr(myMap.Zoom)
    End Sub

    Private Sub update_map()
        copter_marker.Position = New PointLatLng(copter_lat, copter_lon)
        myMap.UpdateMarkerLocalPosition(copter_marker)
        myMap.Invalidate()
        lblInfo.Text = "Info : Lat= " + CStr(copter_lat) + ", Lon= " + CStr(copter_lon) + ", Zoom Level= " + CStr(myMap.Zoom)
    End Sub
End Class

cygwin: failed to build ArduPilot because of isnan / isinf

Upon building SITL on Windows 10 via cygwin following this tutorial: Setting up SITL on Windows, I encountered build error in this step :

cd ~/ardupilot/ArduCopter
make sitl -j4

Something like these (the original error is very long):

/home/achmadz/ardupilot/libraries/AP_Math/quaternion.h: In member function 'bool Quaternion::is_nan() const':
/home/achmadz/ardupilot/libraries/AP_Math/quaternion.h:51:24: error: 'isnan' was not declared in this scope
return isnan(q1) || isnan(q2) || isnan(q3) || isnan(q4);
^

So, it seems the libraries is trying to use isnan function but can’t find it.
The solution is quite simple (although I’m not sure if it’s the correct way, but hey.. my solution works!): we edit all .cpp and .h files inside ardupilot/libraries/ folder (and subfolders) and replace all isnan and isinf appearance into std::isnan and std::isinf, for example inside ardupilot/libraries/AP_AHRS/AP_AHRS.cpp line #271, replace:

 if (isinf(_cos_roll) || isnan(_cos_roll)) {

into

 if (std::isinf(_cos_roll) || std::isnan(_cos_roll)) {

to find files that references isnan and isinf, you can use find command (from within ardupilot/libraries/ folder) like this one:

find ./ -type f \( -iname "*.h" -o -iname "*.cpp" \) -exec grep --color=auto -inH 'isnan' {} \;
find all .h and .cpp files that contain "isnan" reference

find all .h and .cpp files that contain “isnan” reference

and for isinf:

find ./ -type f \( -iname "*.h" -o -iname "*.cpp" \) -exec grep --color=auto -inH 'isinf' {} \;

It’ll show you the files that need to be edited. (You might need to install nano to edit the files — just for convenience).

And done! You are good to go to build SITL in Windows!!

SITL running in windows 10 64bit

SITL running in windows 10 64bit

Test 4G LTE Semarang

Lokasi:
[gmap title=”Lokasi percobaan” show_heading=”1″ latitude=”-7.0761649″ longitude=”110.4245947″ zoom=”16″ width=”100%” height=”250px” map_type=”ROADMAP”]
Modem:
Huawei E3372 (M150-2) Black – MegaFon Version

Indosat Ooredoo

Kekuatan sinyal
Sinyal Indosat Ooredoo di lokasi

SpeedTest

Dilakukan beberapa kali dan diambil yang terbaik

Dilakukan beberapa kali dan diambil yang terbaik

Telkomsel

Kekuatan Sinyal

Sinyal Telkomsel di Lokasi

SpeedTest

Dilakukan beberapa kali dan diambil yang terbaik

Dilakukan beberapa kali dan diambil yang terbaik