How to detect line using RemoteAPI

Typically: "How do I... ", "How can I... " questions
Post Reply
renyee95
Posts: 3
Joined: 13 May 2020, 07:29

How to detect line using RemoteAPI

Post by renyee95 »

Hi, I just start to learn CoppeliaSim last week. I wanted to use RemoteAPI in C language for controlling the line follower robot in CopeliaSim. Currently, my problem is unable to detect the black line on the ground. I able to connect to the vision sensor in CoppeliaSim using simxGetObjectHandle and simxReadVisionSensor both return values are simx_return_ok (0). But, I was unable to detect the black line on the floor in CoppeliaSim.

Is there any suggestion or ways to do line detection through RemoteAPI? Thank you.

Below is my code.

Code: Select all

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> 
#include <extApi.h>

int main()
{
    bool VERBOSE = true;
    int clientID = 0;
    //ROBOT
    int leftmotorHandle = 0;
    int rightmotorHandle = 0;
    //LIGHT SENSOR
    int leftS = 0;
    int midS = 0;
    int rightS = 0;
    int vs = 0;
    float* auxValues;
    int* auxValuesCount;
    
    bool WORK = true;
    simxFinish(-1);                                                     
    clientID = simxStart((simxChar*)"127.0.0.1", 19000, true, true, 5000, 5);  //!< Main connection to V-REP
    Sleep(1000);
    if (clientID != -1)
    {
        printf(" Connection status to VREP: SUCCESS \n");
        simxInt syncho = simxSynchronous(clientID, 1);
        int start = simxStartSimulation(clientID, simx_opmode_oneshot_wait);
        int TEST1 = simxGetObjectHandle(clientID, "DynamicLeftJoint", &leftmotorHandle, simx_opmode_oneshot_wait);
        int TEST2 = simxGetObjectHandle(clientID, "DynamicRightJoint", &rightmotorHandle, simx_opmode_oneshot_wait);
        int SENSOR_L = simxGetObjectHandle(clientID, "LeftSensor", &leftS, simx_opmode_oneshot_wait);
        int SENSOR_M = simxGetObjectHandle(clientID, "MiddleSensor", &midS, simx_opmode_oneshot_wait);
        int SENSOR_R = simxGetObjectHandle(clientID, "RightSensor", &rightS, simx_opmode_oneshot_wait);
        int sensorReadingL = simxReadVisionSensor(clientID, leftS, 1, &auxValues, &auxValuesCount, simx_opmode_oneshot_wait);
        int sensorReadingM = simxReadVisionSensor(clientID, midS, 1, &auxValues, &auxValuesCount, simx_opmode_oneshot_wait);
        int sensorReadingR = simxReadVisionSensor(clientID, rightS, 1, &auxValues, &auxValuesCount, simx_opmode_oneshot_wait);



        if (VERBOSE)
        {
            printf("Computed object handle: %d \n", TEST1);
            printf("%d \n ", leftmotorHandle);
            printf("Computed object handle: %d ", TEST2);
            printf("%d \n ", rightmotorHandle);
        }

        while (simxGetConnectionId(clientID) != -1 && WORK)
        {
            simxSetJointTargetVelocity(clientID, leftmotorHandle, 5, simx_opmode_oneshot_wait);
            simxSetJointTargetVelocity(clientID, rightmotorHandle, 5, simx_opmode_oneshot_wait);
            printf("%d ", sensorReadingL);
            printf("%d ", sensorReadingM);
            printf("%d ", sensorReadingR);

            if (sensorReadingL == false ) //turn left
            {
                simxSetJointTargetVelocity(clientID, rightmotorHandle, 8, simx_opmode_oneshot_wait);
                Sleep(1000);
            }

            else if (sensorReadingR == false  ) //turn right
            {
                simxSetJointTargetVelocity(clientID, leftmotorHandle, 8, simx_opmode_oneshot_wait);
                Sleep(1000);
            }

        }

        //simxPauseCommunication(clientID, 0);
    }
    else
    {
        printf("Connection status to VREP: FAILED");
    }
    simxFinish(clientID);
    return clientID;
}


coppelia
Site Admin
Posts: 7838
Joined: 14 Dec 2012, 00:25

Re: How to detect line using RemoteAPI

Post by coppelia »

Hello,

sorry for the late reply.
In your program you are actually only reading the sensors once, at the program start. You need to read the sensors in your while loop, as you do with setting motor velocities.

You can use the blocking operation mode (as you do), but that will be quite slow. Typically you would use that mode for retrieving object handles, and when you need to wait for data from CoppeliaSim before going on.
But when just sending data to CoppeliaSim (e.g. setting motor velocities), use a non-blocking mode (simx_opmode_oneshot), and when streaming data, use simx_opmode_streaming and simx_opmode_buffer.
Make sure to carefully read more about those modes on this page.

Cheers

renyee95
Posts: 3
Joined: 13 May 2020, 07:29

Re: How to detect line using RemoteAPI

Post by renyee95 »

Hello

Thank you for your reply.

Code: Select all


#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> 
#include <extApi.h>

int main()
{
    bool VERBOSE = true;
    int clientID = 0;
    //ROBOT
    int leftmotorHandle = 0;
    int rightmotorHandle = 0;
    //LIGHT SENSOR
    int leftS = 0;
    int midS = 0;
    int rightS = 0;
    float* auxValues;
    int* auxValuesCount;
    int AA;
    int BB;            

    //wheel detail
    float nominalLinearVelocity = 0.3;
    float wheelRadius = 0.027;
    float interW_distance = 0.119;
    double s = 1.0;

    bool WORK = true;
    simxFinish(-1);                                                     
    clientID = simxStart((simxChar*)"127.0.0.1", 19000, true, true, 5000, 5);  //!< Main connection to V-REP
    Sleep(1000);
    if (clientID != -1)
    {
        printf(" Connection status to VREP: SUCCESS \n");
        simxInt syncho = simxSynchronous(clientID, 1);
        int start = simxStartSimulation(clientID, simx_opmode_blocking);
        int LM = simxGetObjectHandle(clientID, "DynamicLeftJoint", &leftmotorHandle, simx_opmode_oneshot_wait);
        int RM = simxGetObjectHandle(clientID, "DynamicRightJoint", &rightmotorHandle, simx_opmode_oneshot_wait);
        int SENSOR_L = simxGetObjectHandle(clientID, "LeftSensor", &leftS, simx_opmode_blocking);
        int SENSOR_M = simxGetObjectHandle(clientID, "MiddleSensor", &midS, simx_opmode_blocking);
        int SENSOR_R = simxGetObjectHandle(clientID, "RightSensor", &rightS, simx_opmode_blocking);

        printf("Computed object handle: %d \n", LM);
        printf("%d \n ", leftmotorHandle);
        printf("Computed object handle: %d ", RM);
        printf("%d \n ", rightmotorHandle);    
        char sensorReading[] = { false, false,false };
        sensorReading[0] = (simxReadVisionSensor(clientID, leftS, NULL, NULL, NULL, simx_opmode_streaming) == 1);
        sensorReading[1] = (simxReadVisionSensor(clientID, midS, NULL, NULL, NULL, simx_opmode_streaming) == 1);
        sensorReading[2] = (simxReadVisionSensor(clientID, rightS, NULL, NULL, NULL, simx_opmode_streaming) == 1);

        while (simxGetConnectionId(clientID) != -1 && WORK)
        {
            sensorReading[0] = (simxReadVisionSensor(clientID, leftS, NULL, NULL, NULL, simx_opmode_buffer));
            sensorReading[1] = (simxReadVisionSensor(clientID, midS, NULL, NULL, NULL, simx_opmode_buffer));
            sensorReading[2] = (simxReadVisionSensor(clientID, rightS, NULL, NULL, NULL, simx_opmode_buffer));
            double linearVelocityLeft = nominalLinearVelocity * s;
            double linearVelocityRight = nominalLinearVelocity * s;

            if (sensorReading[0] == false)
            {
                linearVelocityLeft = linearVelocityLeft * 0.3;
            }

            else if (sensorReading[2] == false)
            {
                linearVelocityRight = linearVelocityRight * 0.3;
            }

            simxSetJointTargetVelocity(clientID, leftmotorHandle, linearVelocityLeft / (s * wheelRadius), simx_opmode_oneshot);
            simxSetJointTargetVelocity(clientID, rightmotorHandle, linearVelocityLeft / (s * wheelRadius), simx_opmode_oneshot);
           
    }
    else
    {
        printf("Connection status to VREP: FAILED");
    }
    simxFinish(clientID);
    return clientID;
}

I do it like this. Still unable to read the line on the ground. Is there anything wrong?
Please help me.
Thank you very much.

coppelia
Site Admin
Posts: 7838
Joined: 14 Dec 2012, 00:25

Re: How to detect line using RemoteAPI

Post by coppelia »

Make sure you understand well how the legacy remote API works. In particular, simxReadVisionSensor

To prepare a vision sensor read for streaming, you would do something like:

Code: Select all

unsigned char detectionState;
simxReadVisionSensor(clientID,leftS,&detectionStateLeft,NULL,NULL,simx_opmode_streaming);
To read data from that data stream, you would do something like:

Code: Select all

int res=simxReadVisionSensor(clientID,leftS,&detectionStateLeft,NULL,NULL,simx_opmode_streaming);
if (res==0)
{
    // We have received a value. We can evaluate detectionStateLeft
}
Cheers

renyee95
Posts: 3
Joined: 13 May 2020, 07:29

Re: How to detect line using RemoteAPI

Post by renyee95 »

Thank you for your reply.

Finally, I got it.
Thank you very much for your patience in teaching me.

Cheers

Post Reply