问:
using range-only sensors for mapping in SLAM
SLAM noob here but trying to implement an algorithm that fuses odometry data and mapping based on wifi signal strengths for a 2D robot.

1)
After various readings of different resources,
I came across this - http://www.qucosa.de/fileadmin/data/qucosa/documents/8644/Dissertation_Niko_Suenderhauf.pdf
that explained what sensors are used in mapping and how they are categorized.

There are range-bearing sensors (stereo cameras,RGB-d cameras) that provide both distance and angle (range and bearing), from which is easy to locate (x,y) coordinates of landmarks ---> I can develop a map.

But in case I'm using wifi signal strengths (Received signal strengths) etc, in which case it is range-only (meaning, I can only establish from a robot pose(x,y,theta) as to how far this signal is coming from), how am I developing a map at all?

My question is similar to this - What algorithm can I use for constructing a map of an explored area using a number of ultrasound sensors? but not quite same.

Even if I were using IMU/GPS, how am I using GPS to develop a map? What is my state space there? If I am getting GPS signals / wifi signals/ radio signals, am I estimating the transmitter/AP's location as the map? or the walls of a room I'm navigating in, as a map?

A lot of SLAM literature talks about motion model and measurement model, the former gives me the pose of the robot quite easily because of the odometry and imu.

The latter though is more for development of a map. Am I right in understanding this? If yes, say
a] I have walls in a room and I'm using Lidar scanner -
this still gives me the location of the wall using the number of beams that give me bearing, and the average distance from all the beams.

b] Or if I have just a single laser scanner, I can still use a camera (distance) and the heading of the robot to calculate the location of wall (the map). https://shaneormonde.wordpress.com/2014/01/25/webcam-laser-rangefinder/#more-403

But If I have wireless signal strengths, I have a distance (distance of the transmitter from which I'm getting the RSS, not the distance of the wall) as to where they are coming from. But how am I estimating the location of walls here?

2) What does the term "correspondences" mean in SLAM literature?

答:
I think you are confusing two distinct things here. You can of course use Wi-Fi signals for SLAM, but you cannot use them to create a map directly from the RSS. As you have already stated yourself, this only gives you information about where the access point / router might be located, i.e. $\left(x_{ap},y_{ap}\right)$. There is hardly any information about the structure of the room in this data, and pursuing this to build a map is not going to be very productive.

What Wi-Fi and similar beacon-like systems like GPS are typically used for, is providing constraints for the dead reckoning via odometry / IMU. By integrating this external positioning data, e.g. using a Kalman Filter or a graph based representation of a MLE problem, you can reduce the estimation error over the robot's trajectory while performing SLAM. Basically it would act like a weak loop closure algorithm, which corrects the robot current pose (and consequently the prior trajectory) by integrating external "semi-ground truth" data. Having a better estimation of the robot trajectory, i.e. the localization aspect of SLAM, can be automatically translated into more accurate mapping. After all, if you knew the ground truth trajectory of the robot, creating the map would simply require translating all sensor measurements to their accurate measurement poses and then combining them into one large measurement (e.g. a point cloud or an occupancy grid / voxel map). This still assumes a dense metric sensor like a LIDAR or a 3D depth camera to actually get sensor measurements of the structure of the environment!

All of this being said, you can of course create a map simply from the RSS of the Wi-Fi. This would be estimating a sparse representation of the environment, where the estimated state of the environment comprises solely of the locations of the access points. This kind of map would allow you to localize the robot to some degree and even navigate (in the absence of obstacles), but I am quite certain this is not what you are after.

In summary, I think you are confusing metric mapping (dense SLAM) and landmark based mapping (sparse SLAM). Positioning systems like Wi-Fi/GPS can either supplement dense SLAM (requiring a dense metric sensor though), or provide the landmarks for sparse SLAM. Sparse SLAM will not typically give you a metric map of an environment though, but rather a map that spatially relates abstract landmarks.

As for your question about correspondences, it refers to observing landmarks at two distinct timesteps $t$ and $t+1$, and identifying these landmarks in the associated sensor measurements $z_t$ and $z_{t+1}$. Correspondences therefore represent a mapping $\lbrace a : z_t\rbrace\rightarrow\lbrace b : z_{t+1}\rbrace$ where $a=b$ are the same landmark observed in sensor observations $z_t$ and $z_{t+1}$. Correspondences indicate a geometric constraint between observation poses $x_t$ and $x_{t+1}$, as the same feature of the environment was observed, which is the information SLAM is based on.


问:
Send numerical values from Matlab to arduino
I have an array (2x4) in Matlab which may contains integer values as well as values in decimals. For example: [1.1, 23, 1.56, 5.29; 2.14, 2.39, 67, 4.001]. I have to send these values to arduino using matlab. How to do so? I know how to send integer values to arduino from matlab but it is not working with decimal values.

Matlab Code to send integer values is below:

```<code>portName = 'COM5';
s = serial(portName,'BaudRate',9600,'Terminator','LF');
s.timeout = 1;
try
    try
        fopen(s);
    catch
        delete(s);
        fopen(s);
    end
catch
    disp('Unable to open the port ');
end

angle = [1.3,2];
    dataOut = angle;
    dataOut_ = char(dataOut);
    fprintf(s,'%d',dataOut_);
</code>```

Arduino code is given below:

```<code>int d1,d2;
char d[4];

    void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(13, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
if(Serial.available()>0)
{
  for(int i=0; i<3;i++)
  {
    d[i]= Serial.read();
  }
  d1 = d[0]-'0';
  if (d1 == 1.3)
  {
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(2000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
  }
}
}
</code>```

答:
You haven't posted any of the code you're using to receive the values, but I'm guessing the problem is with your casting and decoding of the dataOut value.

Consider the following (direct from my copy of Matlab):

```<code>dataOut = 1.3;
dataOut_ = char(dataOut);
fprintf('%d\n',dataOut_);

1
</code>```

This is because your dataOut_ variable is not a string or character array of values! If you were to instead try fprintf('%d\n',dataOut); (note the lack of trailing underscore), you get:

```<code>fprintf('%d\n',dataOut);

1.300000e+00
</code>```

If you want to convert 1.3 to a character array (what I'm assuming you actually want to do, but again you never posted the receiving code so I don't know really what you're anticipating receiving), then you should use either the long-hand form:

```<code>dataOut_ = char(string(dataOut));
</code>```

or the built-in function that does the same thing:

```<code>dataOut_ = num2str(dataOut);
</code>```

Both of those return the same:

```<code>dataOut_ = char(string(dataOut));
fprintf('%d\n',dataOut_);
49
46
51
</code>```

These are bytes that correspond to Unicode characters. You can translate those bytes back to characters by casting them to ascii/unicode on the receiving end, BUT then you also need to put those characters into a character array and then convert that character array back to a number.

Matlab has a built in function that could do that, but you're (presumably) not using Matlab on the receiving end:

```<code>>> dataIn = native2unicode([49,46,51])

dataIn =

1.3
</code>```

But again, that 1.3 is a character array. You need to cast it to a number, usually with double(dataIn).

There is an easier solution.

Multiply the number by 100. Round using the Matlab command round, pass that value. On the receiving end, divide by 100. Now you have timing control to a hundredth of a second. A uint8 could do up to 2.55 seconds, a uint16 could do up to 655.35 seconds.

Keep in mind that you'll need to send multiple bytes anyways if you're planning on converting a floating point number to a character array, so using a uint16 shouldn't be a problem as far as your data packets go.

```<code>dataOut = 1.3;
dataOut_ = round(dataOut*100);
fprintf('%d\n',uint16(dataOut_));
130
</code>```

:EDIT:

OP posted some more code, but it doesn't look like everything, but I can comment from here:

I don't see where you multiply by 100 in your transmit code. Is that code current?

In your Arduino code, you use Serial.read(); but you don't ever cast the output. This means that each byte of d is a number from 0-255. If you want to use it as a character array, you (probably) need to cast it to a string/char before you make the comparison check.

In your Arduino code, you're just checking if d is the floating point number 1.3. You haven't done anything (like char(1.3) or string(1.3)) to cast 1.3 to a character array so you can do byte-by-byte comparisons.

You have a number of options here, but I'm not sure what you want to do:

Cast the floating point number to a byte array, send the resulting byte array, and then recast the byte array back to floating point. In Matlab, use fprintf('%d\n',typecast(1.3,'uint8')).

Cast the floating point number to a character (Unicode) byte array, transmit the byte array, and then convert the byte array back to characters, then convert the characters back to a number. In Matlab, use fprintf('%d\n',char(string(1.3))).

Multiply from fractional seconds to tenths or hundredths or milliseconds, etc. Round/truncate the number, transmit the number, then convert back to fractional seconds. In Matlab, use fprintf('%d\n',uint16(round(1000*1.3))).

Matlab inherently uses 64 bit (double) numbers for everything, so keep that in mind when you try to reassemble the bytes on the Arduino end. If you want to transmit the byte array for a 32 bit number, use the single() command, as in fprintf('%d\n',typecast(single(1.3),'uint8')). This produces a four byte array, as opposed to the eight byte array produced when you run the same command without the single command.

ContentLicense: CC BY-SA 3.0

Body:
You haven't posted any of the code you're using to receive the values, but I'm guessing the problem is with your casting and decoding of the dataOut value.

Consider the following (direct from my copy of Matlab):

dataOut = 1.3;
dataOut_ = char(dataOut);
fprintf('%d\n',dataOut_);

1

This is because your dataOut_ variable is not a string or character array of values! If you were to instead try fprintf('%d\n',dataOut); (note the lack of trailing underscore), you get:

fprintf('%d\n',dataOut);

1.300000e+00

If you want to convert 1.3 to a character array (what I'm assuming you actually want to do, but again you never posted the receiving code so I don't know really what you're anticipating receiving), then you should use either the long-hand form:

dataOut_ = char(string(dataOut));

or the built-in function that does the same thing:

dataOut_ = num2str(dataOut);

Both of those return the same:

dataOut_ = char(string(dataOut));
fprintf('%d\n',dataOut_);
49
46
51

These are bytes that correspond to Unicode characters. You can translate those bytes back to characters by casting them to ascii/unicode on the receiving end, BUT then you also need to put those characters into a character array and then convert that character array back to a number.

Matlab has a built in function that could do that, but you're (presumably) not using Matlab on the receiving end:

>> dataIn = native2unicode([49,46,51])

dataIn =

1.3

But again, that 1.3 is a character array. You need to cast it to a number, usually with double(dataIn).

There is an easier solution.

Multiply the number by 100. Round using the Matlab command round, pass that value. On the receiving end, divide by 100. Now you have timing control to a hundredth of a second. A uint8 could do up to 2.55 seconds, a uint16 could do up to 655.35 seconds.

Keep in mind that you'll need to send multiple bytes anyways if you're planning on converting a floating point number to a character array, so using a uint16 shouldn't be a problem as far as your data packets go.

dataOut = 1.3;
dataOut_ = round(dataOut*100);
fprintf('%d\n',uint16(dataOut_));
130

:EDIT:

OP posted some more code, but it doesn't look like everything, but I can comment from here:

I don't see where you multiply by 100 in your transmit code. Is that code current?

In your Arduino code, you use Serial.read(); but you don't ever cast the output. This means that each byte of d is a number from 0-255. If you want to use it as a character array, you (probably) need to cast it to a string/char before you make the comparison check.

In your Arduino code, you're just checking if d is the floating point number 1.3. You haven't done anything (like char(1.3) or string(1.3)) to cast 1.3 to a character array so you can do byte-by-byte comparisons.

You have a number of options here, but I'm not sure what you want to do:

Cast the floating point number to a byte array, send the resulting byte array, and then recast the byte array back to floating point. In Matlab, use fprintf('%d\n',typecast(1.3,'uint8')).

Cast the floating point number to a character (Unicode) byte array, transmit the byte array, and then convert the byte array back to characters, then convert the characters back to a number. In Matlab, use fprintf('%d\n',char(string(1.3))).

Multiply from fractional seconds to tenths or hundredths or milliseconds, etc. Round/truncate the number, transmit the number, then convert back to fractional seconds. In Matlab, use fprintf('%d\n',uint16(round(1000*1.3))).

Matlab inherently uses 64 bit (double) numbers for everything, so keep that in mind when you try to reassemble the bytes on the Arduino end. If you want to transmit the byte array for a 32 bit number, use the single() command, as in fprintf('%d\n',typecast(single(1.3),'uint8')). This produces a four byte array, as opposed to the eight byte array produced when you run the same command without the single command.


问:
Fastest maze algorithm for robot
I'm planning on programming a prebuilt robot to solve a maze as fast as possible.  The robot has forward obstacle sensors (no side sensors) and 3-axis accelerometer.  I'm planning on using the wall following algorithm.  Is this the fastest possible algorithm?  Also, since there are no side sensors, the robot needs to continuously turn to check if there is a wall on its side, so is there a clever way to use the accelerometer and sensors?</p>

答:
For any given algoritm (which does not know the maze beforehand) there is a particular maze, where the argorithm does not choose the fastest way on first try.

Many algorithms do the trick, that they travel all ways in maze first, recording the way, than they find optimal way and on second try they drive just to the target by the fastest way.

If your maze is known to be a tree (no loops), with ways just wide for the robot to move, but not too wide and if it have just right angles (which many simple mazes are), then you can use some tricks to solve it faster second time:

side sensors would help a lot, so you would not be forced to constantly turn around

if it is not possible and you have range sensor (usually ultrasound) rather then just obstacle sensor (maybe plain bumper), you can restrict it to narrow beam and choose to just wave a little and see, if the distance is changing consistently, or if there is a hole (which means side way) and how far the hole is. Then you can run fast near to the crossing and then only slow and go full range rotations to excactly find the side way.

also having the sensor on "tank-like" rotating base would allow you to drive stight and rotate just the sensosr, which is faster, than rotating whole robot

if the ways are narrow, you can consider to add bumpers to sides and just bumping to the sides to feel them instead of rotation on place to sensor them properly. Bonus if you can have bug-like antennas to feel both sides at the same time (but they need to be flexible to not break and you need at least 3 state sensors for them (2 bits) - no touch - light touch - hard touch: no touch means side way, light touch means you are just on straight row in centre, hard touch means obstacle or turnining too much to side)

Anyway:

you go your usual "right hand on wall" way, until you find target, then continue to sthe start the same style, so you travel all the maze first time.

you mark any crossing on the way and count them creating kind of map (bonus if you measure the distance), then, when on the start back you go travel the map in memory and when you return to a crossing, you know, that you can skip the first way, that you had choose there, as it does not reach the target and it returns back. Continue, until you find target and you have half of the map solved. Then do it in reverse way from end and solve the other half of map. You should get the same result - if not, you made a mistake or the maze is not a tree.

on the second try you know, which side ways you can skip and which way you have to choose on which crossing, so you go the shorter way to target.

if you also marked the distances, you know, how far next turn should be and you can drive really fast for nearly all the distance, before you need to scan for turn precisely (and probably more slowly)

if your robot construction allows it, you even can ignore the walls and let them lightly bump you back to the centre of that way, so you need a lot less delicate navigation, so you can run even faster.

The same goes to turns, where you can stick to the wall and push a little all the time you think you are approaching turn, until it let you go in, so you know your turn is here. Again much simpler navigation, much less data to evaluate, so much faster speed possible.

If you want to be extra ultra fast, you record this run too and use that for third run, where you know, how long you have to run before turn, with all the acceleration and irrgularities of fast run versus carefull and slow exploring is already accounted for.

Title: Fastest maze algorithm for robot


问:
Navigation Potential fields algorithm
I am working with a raspberry pi which has some positional sensors and I manage it from my mobile with an app I am developing. Now I am trying to understand how to implement this algorithm to code, but I don't really know how to start, so I would be really great if someone can help me with some starting code or similar because I cant find this algorithm implementation.</p>

答:
I have studied this algorithm couple months before and i'll give you my thoughts about it.

You should really start by defining the positions of your sensor. Their position is crucial for good working algorithm. I will continue with an imaginary example robot which has a circular shape. Then i placed 8 sensors on its edge with 45degree gap. Each sensor read will return only the distance to the nearest target if in detectable range else a 0.
You can represent each vector as like this:
$$\vec {V}_{direction} = - \phi$$
Since you want to move away from the obstacle.

$$\vec {V}_{magnitute} = c $$

But there is an important part in here. You have 3 policies to choose from when evaluating the sensor values:

Constant Magnitude

This profile has some important problems. It causes jerky motion on the perimeter of potential field so i dont recommend it.

Linear Dropoff

This profile says that the magnitude of vector decreases linearly with the distance. So if you double the distance, your magnitude cuts to the half.

3.Exponential Dropoff

This profile seems to be the best suit for most of the cases. Your magnitude decreases linearly with the square of the distance ie. if you double the distance your magnitude will be %25 of the original magnitude.

After the policy select, its really easy. You read the sensors, you evaluate its values according to selected policy then for each vector you obtained(in our example 8) you sum them as vectors. The vector you obtained has everything you need:

Its magnitude is your motors base speed.

Its direction is the measure of angle you should turn.

I will give one last example about the functions and the program flow.

I will have a simple linear dropoff potential field which will only turn the opposite way of the obstacle. In this case i only have my front sensor.

$$\vec{V}_{direction} = -180 $$
$$\vec{V}_{magnitude} = \begin {cases}d \gt D,&0 \\
d \lt D,& \frac {(D - d)}{D}\end {cases}$$

Where D is the max distance you sense.

```<code>vector repulsive(double d, double D)                {
 if (d <= D) {
   outputVector.direction =   -180;
   outputVector.magnitude = (D-d)/D;}
 else {
   outputVector.direction=0.0
   outputVector.magnitude=0.0
 }
   return    outputVector;
}
</code>```

This part is the sensing part which is so simple. You can build upon this by changing the policy and reading more sensors.

Hope it's helpful.

Title: Navigation Potential fields algorithm

Body:
I have studied this algorithm couple months before and i'll give you my thoughts about it.

You should really start by defining the positions of your sensor. Their position is crucial for good working algorithm. I will continue with an imaginary example robot which has a circular shape. Then i placed 8 sensors on its edge with 45degree gap. Each sensor read will return only the distance to the nearest target if in detectable range else a 0.
You can represent each vector as like this:
$$\vec {V}_{direction} = - \phi$$
Since you want to move away from the obstacle.

$$\vec {V}_{magnitute} = c $$

But there is an important part in here. You have 3 policies to choose from when evaluating the sensor values:

Constant Magnitude

This profile has some important problems. It causes jerky motion on the perimeter of potential field so i dont recommend it.

Linear Dropoff

This profile says that the magnitude of vector decreases linearly with the distance. So if you double the distance, your magnitude cuts to the half.

3.Exponential Dropoff

This profile seems to be the best suit for most of the cases. Your magnitude decreases linearly with the square of the distance ie. if you double the distance your magnitude will be %25 of the original magnitude.

After the policy select, its really easy. You read the sensors, you evaluate its values according to selected policy then for each vector you obtained(in our example 8) you sum them as vectors. The vector you obtained has everything you need:

Its magnitude is your motors base speed.

Its direction is the measure of angle you should turn.

I will give one last example about the functions and the program flow.

I will have a simple linear dropoff potential field which will only turn the opposite way of the obstacle. In this case i only have my front sensor.

$$\vec{V}_{direction} = -180 $$
$$\vec{V}_{magnitude} = \begin {cases}d \gt D,&0 \\
d \lt D,& \frac {(D - d)}{D}\end {cases}$$

Where D is the max distance you sense.

vector repulsive(double d, double D)                {
 if (d <= D) {
   outputVector.direction =   -180;
   outputVector.magnitude = (D-d)/D;}
 else {
   outputVector.direction=0.0
   outputVector.magnitude=0.0
 }
   return    outputVector;
}

This part is the sensing part which is so simple. You can build upon this by changing the policy and reading more sensors.

Hope it's helpful.


问:
How to decide the battery power for my robot
I need my motor to be powered with 12V, 5A for 1 hour continuously. How can i decide the Ah rate of the battery. Please suggest some lithium ion battery for the specification</p>

答: The best way to measure battery capacity is Watt Hours (WHr) because they are a measure of energy. Amp hour ratings are based on the batteries nominal voltage. This is especially important if you end up using switch mode regulators later.</p>


问:
How to stabilize a quadcopter
Today was my quadcopter's first "flight". I'm running megapirate on a Crius AIOP v2 with a Turnigy Talon v2 frame.

I only touched the throttle stick on my remote, nothing else. When I felt the quadcopter was about to take off, I pushed the throttle just a little bit more, and the quadcopter oscillated 2 or 3 times and the just flipped over, landing on the propellers.

So, I broke 2 props, my frame feels a bit loose, I'll probably have to tighten the screws (I hope...). How can I tune the software so it will stabilize nicely after take off?

Edit :

I don't know if it was true oscillation or just random air flows making it unstable. I made some more tests yesterday and it was quite OK (even if I crashed a few times). This time, it was really oscillating but it was quite windy outside and the quadcopter managed to stabilize after all. So i'll probably have to tune my PIDs and find a way to do it without crashing.

Edit 2 : After some PID tuning, I managed to stabilize my quadcopter pretty well but it's still oscillating just a little bit. I guess I'll have to slightly change the values to get a perfect stabilization.

答:
The answer to the larger question here is that when running the initial test of any vehicle that has the capability to harm itself, it should be sufficiently restrained until you are satisfied that it can be kept under control.

In the case of a quadcopter, this would involve tying a bit of string to the corners, leaving enough slack so that it can rise 6-12 inches, but not enough slack for it to flip over.

Once you do that, you'll be able to test and troubleshoot with impunity.  Being scared to run a test is the fastest way to run no tests and get nothing done.

If you're suspicious of random air flows being to blame, you can try taking off from a wire mesh instead of a solid surface.  Try swapping the motor polarity on purpose, just to see how that affects the behavior.  Every experiment you can run in the controlled environment to understand the parameters of the system will help you troubleshoot more complicated control problems that arise later.

Title: How to stabilize a quadcopter


问:
Google's 'Tango' - How it works and what's special about the hardware?
I'm looking for a good breakdown and explanation of Google's 'Tango' AR platform.  Specifically how the hardware works together to generate depth maps and the SDK's use of it.

I know the hardware composes of a fisheye lens camera and an RGB-I camera.  I am only familiar with stereo vision with identical cameras and disparity maps, I am thinking the different lenses and camera elements make it easier to distinguish variations in the environment but must have some very special (and proprietary) algorithms.  However, there must actually some special hardware and dedicated chipsets for processing the depth map to take the burden off the CPU/GPU?

Also, for the AR software implementation, I assume the SDK has some GPU utilization built into it like OpenCL or CUDA (but specific for the Adreno GPU).  Does it simply use OpenCL (this is supported by the Adreno GPU) or does it have something proprietary from Google similar to CUDA for the nVidia chipsets?

Basis for the question - I work with OpenCV some and am experimenting with stereo vision applications, but would like to move on to developing apps for specialized hardware and this sounds like the right (maybe only?) platform.

答:
I suspect, but don't know, that the Tango uses a variant of volumetric reconstruction using a Truncated Signed Distance Function (Good intro at http://www.cs.nyu.edu/courses/fall12/CSCI-GA.2945-001/dl/jiakai-slides.pdf)

It uses structured IR light to obtain a dense depth map, projects these points back into 3-space as a point cloud, probably turns this into a mesh by triangulating it and then projects it into a TSDF volume representing the space being mapped.

Marching Cubes or similar algorithm can then be used to extract the 0 crossing of this isosurface into a mesh.

Given that the Tango seems to bee able to map quite large areas, I would assume that either the mapping resolution is quite coarse or else Google have implemented a streaming algorithm to move the volumetric reconstruction into and out of GPU memory.

The seminal paper here is KinectFusion (https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/ismar2011.pdf) which describes how this was done with a Kinect using depth only data.


问:
What does ardupilot do and how does it do it?
I have been using ardupilot on drones for a while and I don't exactly know what it does. I know it keeps a drone leveled, lets us set way points and automatically fly through them, etc. Is that it? If so why is the pixhawk so expensive? don't you just need a cheap imu and gps with a $5 pi zero. I might be mixing up pixhawk's hardware and ardupilot. But yeah what do they do individually? and how do they do it? It it just hard coded to add more thrust to a few motors if its tilted, just use gps to go to a location, etc or is there more to it.</p>

答:
Quick answer:
Hardware wise the Ardupilot is based on the "Arduino", I can't remember what chip it actually uses, but it's Arduino  compatible.
Pixhawk uses a 32-bit chip, this chip is faster than the Ardu's chip.</p>


问:
Difference between form closure and force closure
What exactly is the difference between both the above terms? From some of the papers I realize that force closure depends on the frictional forces. Is it correct?

Suppose I  to grasp a cylindrical object with my hand, which closure will it be considered?

答: It depends on how you grasp the object. If you grip very tightly on the cylinder with your hand and prevent it from moving in certain directions using friction then you are using a force closure. If you enclose the object so that it cannot rotate/translate then it is a form closure.</p>


问:
How to program a continuous servo motor? (Arduino)
I need to use continuously rotating servo for a camera stabilization system. My professor bought servos that have already been modified for continuous motion--there's no stop in the gears, and the potentiometer allows it to spin 360+ degrees.

I am currently using PWM with an Arduino Uno. The servo does spin continuously, but not in a stable way. I've also taken out the potentiometer in another one of the servo, and on a third servo I used a voltage divider in place of the potentiometer.

I've tried static values and a "sweep" from 0% duty cycle to 100% to get a feeling for how they work, but I just cannot figure it out. I greatly would appreciate any tips on this.

Here is my code:

```<code> //PWM test for continious motion Servo

 int servoPin = 9; // connect servo to pin 10
 int pwmVal = 0; // declare pulse width modulation value

void setup(void) {
  pinMode(servoPin, OUTPUT); //set up the servoPin as an output pin
  Serial.begin(9600); // begin serial monitor
}

void loop(void) {

  //for loop that sweeps values from 0 to 255
  for (pwmVal = 0; pwmVal <= 253; pwmVal += 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }
  for (pwmVal = 253; pwmVal >= 0; pwmVal -= 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }

  //assign a static pwm value
  pwmVal = 0;
  analogWrite(servoPin, pwmVal);
}
</code>```

答:
Doing a sweep across a range of PWM value will not results in a continous motion, since the delay times between the different vales are not correlated with the time required for the servo to arrive to the given position.

Depending on how the motor functions:

I suggest you only give 2 commands, the minimum PWM value and the maximum PWM value. This should do a complete rotations continously, if the duty cylcle of your PWM is proportional to the position of the motor.

If your motor has been modified and the pwm duty cycle is not proportional to the position of the motor, but to its velocity, then a constant PWM duty cylce should rotate the motor with a constant velocity.

Also please increase delay times to a few seconds in both cases to make sure that the motor has enough time to execute the commands.


答:
What I've found out that using char([float]) converts decimal numbers into the integer numbers in MATLAB 2016a.

```<code>>> x = [1.1, 23, 1.56, 5.29; 2.14, 2.39, 67, 4.001]

x =

    1.1000   23.0000    1.5600    5.2900
    2.1400    2.3900   67.0000    4.0010

>> xch = char(x)

xch =

C

>> fprintf('%f\n',xch)
1.000000
2.000000
23.000000
2.000000
1.000000
67.000000
5.000000
4.000000
</code>```

So you can send the values as

```<code>fprintf('%f\n',x)
</code>```

and at the arduino end you can receive the data as

```<code>float d1,d2;
float d[4];

    void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
}

void loop() {
if(Serial.available()>0)
{
  for(int i=0; i<3;i++)
  {
    d[i]= Serial.parseFloat();
  }
  d1 = d[0];
  if (d1 == 1.3)
  {
    digitalWrite(13, HIGH);
  delay(2000);
  digitalWrite(13, LOW);
  delay(1000);
  }
}
}
</code>```

Title: Send numerical values from Matlab to arduino

Body:
I have an array (2x4) in Matlab which may contains integer values as well as values in decimals. For example: [1.1, 23, 1.56, 5.29; 2.14, 2.39, 67, 4.001]. I have to send these values to arduino using matlab. How to do so? I know how to send integer values to arduino from matlab but it is not working with decimal values.

Matlab Code to send integer values is below:

```<code>portName = 'COM5';
s = serial(portName,'BaudRate',9600,'Terminator','LF');
s.timeout = 1;
try
    try
        fopen(s);
    catch
        delete(s);
        fopen(s);
    end
catch
    disp('Unable to open the port ');
end

angle = [1.3,2];
    dataOut = angle;
    dataOut_ = char(dataOut);
    fprintf(s,'%d',dataOut_);
</code>```

Arduino code is given below:

```<code>int d1,d2;
char d[4];

    void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(13, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
if(Serial.available()>0)
{
  for(int i=0; i<3;i++)
  {
    d[i]= Serial.read();
  }
  d1 = d[0]-'0';
  if (d1 == 1.3)
  {
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(2000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
  }
}
}
</code>```

Body:
What I've found out that using char([float]) converts decimal numbers into the integer numbers in MATLAB 2016a.

>> x = [1.1, 23, 1.56, 5.29; 2.14, 2.39, 67, 4.001]

x =

    1.1000   23.0000    1.5600    5.2900
    2.1400    2.3900   67.0000    4.0010

>> xch = char(x)

xch =

C

>> fprintf('%f\n',xch)
1.000000
2.000000
23.000000
2.000000
1.000000
67.000000
5.000000
4.000000

So you can send the values as

fprintf('%f\n',x)

and at the arduino end you can receive the data as

float d1,d2;
float d[4];

    void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
}

void loop() {
if(Serial.available()>0)
{
  for(int i=0; i<3;i++)
  {
    d[i]= Serial.parseFloat();
  }
  d1 = d[0];
  if (d1 == 1.3)
  {
    digitalWrite(13, HIGH);
  delay(2000);
  digitalWrite(13, LOW);
  delay(1000);
  }
}
}


问:
What kind of sensor do I need for knowing that something is placed at a position?
I have a small device that's picking up small rocks from a pile and moving them to another place. Its a kind of crude way of trying to push the whole pile onto a bigger gear and hoping one of them is pushed to one of the spaces between gears and taken around and falls off on the other side of the spinning gear. Here I want to know if the machine successfully got a rock here, if not it should spin the gear until it turns up a single rock on the other side of it. If a rock is present at the spot, the gear should stop spinning until the rock is taken care of by the rest of the machine.

What kind of device can I use to sense if I successfully succeeded in getting a rock on the other side of the gear?

This is just a part of a bigger system. To sum up, I need the sensor to signal when a rock is signaled out and separated from the rest so it can continue work on that single rock.

I am building this using an Arduino to move the gear around, so the sensor needs to be something that can be controlled by an Arduino.

答:
I would put the whole conveyor belt on two axis, and:

Have the right axis as a pivot.

Have the left part's axis rely on a switch button.

Because of the height between the spinning gear and the belt, the rock's impact will be powerful, making it easy to find a switch button that can detect it.

It is very cheap and robust to dust/misplacement.

ContentLicense: CC BY-SA 4.0


问:
How to create a Industrial Robotic arm controller?
Can anyone explain me in detail, what a industrial robotic arm controller does? What are its components? Does the industry use the opensource controllers like Arduino? I saw most of industrial controllers look very big whereas the hobby robot arms are having small controllers mostly made from arduino? Also, if I were to reconstruct it, what are the topics that I need to learn?</p>

答:
Industrial robots (e.g. Kuka, ABB, Fanuc) use a control cabinet which has the following main components:

Drive amplifiers (controllers):
The drive amplifiers are responsible for the closed loop control of the motors in the structure of the robot (and the external axes, if present). The number of drive amplifiers usually matches the number of motors. Their main function is to receive the position (and/or velocity) commands from the robot controller and to control the motors to execute the commands. In most cases some kind of communication protocol (mostly Ethernet based) is used to transmit these commands. In some cases the drive amps have additional safety functions (e.g. Safe Torque Off and Safe Brake Control) to enable a limited human robot interaction. When compared to "hobby" robots, the drive amplifiers offer much more functionality for smooth motions (e.g. jerk limiting, filtering) and motor protection (e.g. current limiting, voltage limiting) furthermore, in many cases these have thousands (!) of parameters to fine tune their performance.

Robot controller: the main function of the robot controller is to interpret the robot application program and convert the commands in the source code to motion or other commands given to the IOs or to the drive amplifiers. The robot controller has an internal model of the kinematic (and dynamic) structure of the robot and has advanced trajectory planning and synchronization capabilities. It can synchronize the motions commanded by each individual drive amplifier in a precise manner. A robot controller also has thousands (!) of parameters to make sure the robot can be set up according to the requirements of its task.

HMI: Industrial robots usually have some sort of pendant or HMI useful for programming the robot. During operation the application program will be displayed here. Also different setting are available on the HMI (e.g. teach in of a new task).

Application program: Hobby robots usually have a "firmware" running on the arduino which determines their behavior. Robot controllers are more like a PC. They have an operating system and only execute something if somebody writes a program that is called. That program is the application program and is written in a robot manufacturer specific language (e.g. KRL for KUKA, Rapid for ABB, Java language can be used to program the Kuka iiwa, their light weight robot arm).

Tech support: one feature that hobby robots do not have is tech support. Industrial robot manufacturers offer courses, hotline telephone support in case there are difficulties in using/programming their robot. Furthermore, industrial robots come with necessary certificates (CE, UL, etc.) for industrial use.

If you would like to build a robot controller which is at least comparable to today's industrial robot controllers, starting from scratch, you would need:

select industrial motors and drive amplifiers (e.g. from Rexroth, Siemens, etc.)

select an industrial PC and a real-time operating system (or extension,
e.g. WindRiver, QNX, RTLinux) and a non-real time OS (.g. Windows or Linux)

design and build a control cabinet

develop your control architecture (which module communicates with what, how are they interfaced, what needs to run in real-time what not)

develop/implement a trajectory planning module

develop/implement an IO handling module

develop/implement an interpreter for the application programming language you have selected (or define a new language and an interprtere for it), complete with variable stacks (global and local), (soft and hard) interrupts, subroutines, timers and counters, coordinate system transformations, motion commands, flow control commands, basic types, math library, etc.

"glue" together the interpreter with the motion module and the IO module

develop/implement (or buy) a communication stack to communicate with the drive amplifier

develop/implement an HMI that can be used for parameterizing the drives, the motion module, the IO module, and can be used for writing and executing application programs with the defined language

document everything (!)

test test test and test even more

get the whole thing certified by a certification body

market and sell it

offer tech support, warranty, etc.


问:
Recreating Roomba behavior in a spherical robot
Disclaimer: I am a beginner, both to this forum and to robotics.

I work in IT, and the guys in my department have decided we would like to build a robot for the office, as a sort of hobby/team-building exercise of sorts.

Our goal is to create a robot that is spherical, like BB8, but randomly navigates the room like a Roomba. I've seen examples of BB8-like robots online before, but all the ones I have found have used a remote to manually control their movements. This seems like a difficult first project, and personally I would like to try something more basic to begin with, but I figured I might as well look at feasibility of the project before I rain on their parade.

The way I see it, there's two possible ways we could go about this:
1. Use an iRobot Create 2 and somehow adapt it to a spherical body
2. Start from scratch on a BB8 robot, and write a program that mimics a Roomba's behavior. (I have seen several examples of this online using Arduino and Raspberry Pi)

My question is: how difficult is it to write a program mimicing the Roomba's behavior? If it is very difficult, then perhaps I should simply buy a Create 2 and go from there.

Sorry if this is a broad question. If it is not appropriate for this forum, please direct me to a more suitable forum for beginners in robotics who have stupid questions like mine :p

答:
I'd imagine this would be pretty difficult for a beginner. I think you'd be better off making a differential-drive robot first, since the kinematics are much more straight-forward. Either way, you're in for a lot more math than you might realize.

The primary goal will be to abstract away the low-level motor mechanics from the high level behaviors. You'll want to be able to tell the robot to turn 180 degrees if it detects a wall, for instance, but without some abstraction, you won't know exactly what low-level motor commands are required to do this. This is achieved by closing the feedback loop between the output commands and what the robot's actually doing, which can be done through some sort of tilt sensor and perhaps an accelerometer.

Once you've closed the feedback loop, you can use PID controllers to apply commands based on some error between desired state and actual state. For instance, you'll be able to calculate the error between the actual robot's tilt and the desired tilt and tie that to some motor command that can directly control the error.

Once you've achieved balancing and movement, you can add on other behaviors, such as avoiding obstacles. I'd recommend using a Subsumption architecture to determine which behavior takes priority over another (i.e. go forward or avoid obstacle).

The obstacle avoidance behavior will require a distance sensor; you're probably constrained to an IR sensor if you're wanting to build a BB8 clone. There'll be a whole bunch of vector math necessary to calculate the appropriate angle to turn based on what the robot is reading from the distance sensors.

I recommend you watch this YouTube video by David Anderson, which is probably the best intro to mobile robotics that I've seen. I've watched the whole thing probably 5 times.

I hope this was helpful. Best of luck!


问:
Why does the motor only run between 170-180?
I'm using a brushless motor of 1000kv and an ESC simon30A. I power the motor using arduino adapter AC/DC 9v. When I try to run the motor using sweep example. The motor will only run when the value is between 170-180. How come other values below 170 won't run the motor? Is my ESC broken??

The model of bldc is A212/3T. 1000kv and ESC is Simon 30A . I'm using servo Library to control the speed.

答:
The sweep example is for servos. A brushless motor is not a servo. The sweep example attempts to turn the servo from 0 to 180 degrees and back to 0. So, the 0 - 180 value is not necessarily a PWM signal; it represents the rotation of a servo.

A DC motor won't turn without enough power being applied to overcome the static magnetic pull--you can feel if you try to turn the motor shaft. So, if you only apply small voltage (below whatever voltage 170 represents in your example), then the motor will just hum.


问:
Are there any comprehensive video courses or lecture notes on Industrial robotics?
I am really new to the topic. There doesn't seem to be lot of overlap between Industrial robotics and Hobby robotics (atleast in certain areas like control etc).Please correct me if i am wrong. I actually tried going through Fanuc website, and most of the content is restricted. I would like to know if there is any course on how to operate Industrial robots? its PLC programming? or any application specific course etc?</p>

答:
To directly answer your question, you can take a look at some of the ROS MoveIt! Videos. Check out the Udacity robotics courses.

To give a more opinionated answer...

I've worked both with industrial robots and mobile robots, so my opinion is that if you learn mobile robotics concepts including manipulators and become familiar with robot system design, you'll be able to do well in industrial robotics. However, industrial robots are typically programmed in a very different way.

Mobile robots are designed to sense and respond to their environments.

Industrial robots are primarily designed to follow pre-planned instructions and manipulate their environments.

So industrial robots are typically not designed with a wide array of sensors and complex conditional logic. It's a lot of sequential programming in specialized languages such has RAPID (ABB), KUKA Robot Language, KAREL, Fanuc TP (each robot manufacturer has its own, and there are some industry standards). It's a lot more like CNC programming, but without G and M code and rather a list of human-readable sequential steps. You can watch YouTube to get up to speed on any of these languages, but none of them are that revolutionary. If you're already a programmer, you'll probably cringe a little and roll your eyes when you see these languages.

The skills in mobile robotics transfer over, and you can even make big improvements to the industrial robotics world by bringing in the more traditional skillset (which sensors, algorithms to use, metrology, etc.)

Most training on industrial robots is either done at universities that have partnerships with the robotics companies or at companies that have purchased these robots. Thus it's hard to get into the details of this field without being there. But you're not missing much in my humble opinion. I've been through those trainings and I mostly rolled my eyes because industrial robotics seems to be miles behind the rest of the robotics industry in terms of how the user would program them. Thus just learning robotics in general will help a lot.

Most industrial robots just perform DSP on the motor signals to figure out where they are. It's amazing and kind of scary, but there's no physical positioning feedback. The error adds up through the chain out to the end effector and it's a pain. Some of the more advanced robotics groups thus measure the end effector from the outside to correct these estimates, and that's done with expensive software rather than someone actually programming anything.

In general, if you learn MoveIt!, you've read about robotic arm path planning, and you are familiar with robotics concepts in general, you'll be ready to jump into the world of industrial robots, and you might even cringe a little when you see how the robots that run factories really work.


问:
Is it possible to use an arduino in hard real time
I am using the ros_arduino_bridge to control a robot, by connecting the Arduino to a main pc with a usb cable. I was thinking of using the Arduino with main pc with a serial cable and then doing real time control of the Arduino by using the real time clock.

Is it possible to communicate with the Arduino in hard real time by using the real time clock and serial connections? I want to use Arduino board as a bridge between the main computer and the sensor and motors. And i want to control those sensors and motors in real time. All the high level processing tasks like computer vision and motion planning will be running in the main computer which then sends the commands to motors from the Arduino. So it is just acting like a bridge.

The reason I want hard real time is so that my robot can control its joints at very high and accurate speed so that the robot can do human level tasks like running, jumping, assembling some parts, balancing its body while moving(walking, running, jumping) at any speed (which requires the joints to be controlled at very high speed and accuracy) etc. I will be using gazebo simulator to test most of the tasks.

答:
There are multiple different parts to your question.

Can an Ardiuno be used "in in real-time"?
Yes it can, it has hw timer interrupts, the tolerance of your oscillator will give the precision of the interrupt.

Can you communicate with an Ardiuno in real-time?Yyes, you can. A synchroneus communication, e.g. SPI is realtime capable.

Can you communicate with an Ardiuino over serial in real-time?
The serial port is an async communication. If you implement the other protocol layers ontop if it with care (e.g. maximized message length), I assume it can be done.

can you use USB to communicate with an Arduino in real-time?
No. USB is not real-time capable.

All the high level processing tasks like computer vision and motion planning will be running in the main computer which then sends the commands to motors from the Arduino. So it is just acting like a bridge.

In this case, which entity performs the closed loop control? Your description suggests, that the arduino is. It is then not a simple bridge. However, sending commands to an arduino does not necesarily need real-time communication capabilites:

The PC computes the reference values for the control system, these are then transfered to the arduino over a non-realtime channel. Tha arduino reads this channel in a non-real time part (i.e. not in the interrupt) and the interrupt on the arduino runs the control loop making sure that the reference value is mainained. You only have to take care that the time required to execute the task in the interrupt is less then (and not equal) the interrupt cycle time. This way the processor can process the communication task "between" two interrupts. The question how much less dies it have to be depends on how often you get a command and how fast do you want to react to a new command.

If the communication is not part of a closed control loop (i.e. it only sends reference values for the outmost loop in a cascasded loop), it does not have to be real-time capable.


答:
The short answer is no, you will not be able to create a distributed system that meets the criteria of 'hard real time' using the approach you describe.

The more nuanced answer is: It is theoretically possible with a heck of a lot of work. You will have the most problems in achieving hard real time from the USB communications, the ROS code, and using python. You will need understand the details of how USB communications work, how your USB bus is physically arranged, and use a real time capable driver like usb4rt. ROS is not real time capable, but once you have finished the difficult effort of achieving realtime in the USB communications, an orocos module to replace the functionality of ros_arduino_bridge should be easy for you. Python can be used in realtime if you are careful.

One small change you could make to simplify the amount of work would be to use direct RS232 serial communications instead of USB communications. I would expect realtime serial drivers to be easier to set up and work with.

Distributed real time systems are difficult to get right. If you are able to design your system such that there is only the main PC and no arduinos, you will simplify things and be able to make progress towards your goals much more quickly.

However, it's likely that you don't really need hard real time. After all, humans do all the tasks you want to do and we do not have hard real time processing. Many robotics algorithms have a basic assumption of a constant time period, and these are the ones that cause robots to work incorrectly when realtime processing is not maintained. It is possible to derive alternate algorithms that do the same thing, but without the constant time period assumption for most of them.

Title: Is it possible to use an arduino in hard real time

Body:
I am using the ros_arduino_bridge to control a robot, by connecting the Arduino to a main pc with a usb cable. I was thinking of using the Arduino with main pc with a serial cable and then doing real time control of the Arduino by using the real time clock.

Is it possible to communicate with the Arduino in hard real time by using the real time clock and serial connections? I want to use Arduino board as a bridge between the main computer and the sensor and motors. And i want to control those sensors and motors in real time. All the high level processing tasks like computer vision and motion planning will be running in the main computer which then sends the commands to motors from the Arduino. So it is just acting like a bridge.

The reason I want hard real time is so that my robot can control its joints at very high and accurate speed so that the robot can do human level tasks like running, jumping, assembling some parts, balancing its body while moving(walking, running, jumping) at any speed (which requires the joints to be controlled at very high speed and accuracy) etc. I will be using gazebo simulator to test most of the tasks.


问:
Drift in Integrating Angular Acceleration to Angular Velocity using two accelerometer data
I am trying to integrate Angular acceleration obtained from a set of accelerometers positioned specifically at opposite corners of a cube, based on "EcoIMU: A Dual Triaxial-Accelerometer Inertial Measurement Unit for Wearable Applications" paper.

I am getting the angular acceleration on each Axis

This signal is quite noisy .

Then after integrating angular acceleration to angular velocity using trapezoidal rule , I get signals which drifts heavily and randomly.

I understand that noise and also numerical integration is causing the effect. Other than low pass filtering the data, is there any other methods to reduce noise.

And the major factor for the drift is numerical integration, how can this be handled.

Please help me out with this.

答:
Some solutions:

Zero your drift when you know you are not moving.

Use better accelerometers (i.e. more bits of resolution, higher G values, and faster measurements).  Because you are integrating, any sensor noise will get amplified.  Also, if the sensor saturates at its max G value, that will also throw off your results.

Use an angular velocity sensor, aka a "gyro" instead.  They will give you a more direct measurement without needing to integrate.

Typically, accelerometers and gyros are used in conjunction and thrown into a kalman filter together.  The accelerometer is used for transnational acceleration/velocity/position by integrating once and twice, and the gyro is used for angular velocity and position by integrating once.


问:
MPU6050: Changing Gyro Output Range Throws off Positional Reading
I am using the MPU6050 in conjunction with an Arduino and Jeff Rowberg's i2cdev library, and my project requires that the gyro rate outputs be more precise than the default setting, which is 1/16.4 of a degree (+/-2000 deg/sec range). The gyro outputs can be changed with mpu.setFullScaleGyroRange(uint8_t range) for which I passed in MPU6050_GYO_FS_500 for range to get a higher precision

In this project, I also need the YPR position, which I obtain through mpu.dmpGetQuaternion(&q, fifoBuffer) and mpu.dmpGetGravity(&gravity, &q) and mpu.dmpGetYawPitchRoll(ypr, &q, &gravity).

The problem is with the new gyro output range, the YPR position changes drastically when the MPU is being rotated and slowly catches up again once the MPU is held still. I think there is an error in the filter that combines the gyro and accel data that is making the gyro to sensitive. Maybe the DMP is dividing the GYRO rate data by the default sensitivity factor (16.4) when it should be dividing by the new one (131)?

How can I get accurate YPR readings without delay?

Here is a screenshot of the data. The axis aren't labeled, but the x-axis represents about 16 seconds of time. The blue line is the gyro rate data, and the pink line is the roll position of the MPU. The graph shows two rotations of the MPU.

答: I'm having a similar issue and think it may be that when set to the more sensitive scale (250dps), your gyro readings are clipped. I.e. you turn at a rate of 400dps, but the gyro's output has a max value of 250dps, hence the YPR output values lag reality until the small proportion of accel fed in to stop gyro drift (presuming this is the technique) gradually corrects it. Guess Guess.</p>


问:
Hubsan x4 drone camera recording black
I'm unsure if this is the correct community to ask this question (vs. Electronics or Aviation Stack Exchange, for example), but I recently purchased a Hubsan x4 HD video drone from Amazon.

This is my second Hubsan drone so I am already familiar with using the recording feature. However, after every recording, the recordings are the correct length, with the correct audio, but the image is black. I tried formatting the micro SD, using different micro SDs, reading up on forums, etc. but nothing seems to do the trick.

Is mine defective, or has someone had this issue and has been able to solve it?

答:
Hubsan is a proprietary drone if I am right. But, there are several reasons why black-outs can happen.

The image-sensor/camera may be faulty (The photosensitive material may not be generating signals through photo-voltaic effect).

There may be proprietary protocols which may drop frames if parity checks are failing and faulty image-capture can be causing this.

Problems with software - This may be due to problems with post-processing and the meta-data is getting retained (may be due to hardware image buffer problems).

This question is vague without videos/descriptions/logs of the same.

Title: Hubsan x4 drone camera recording black


问:
Thermal Imaging camera activation upon detection
So I am planning on building a robot that turns on when it detects some kind of heat source, I am currently looking at thermal imaging cameras, but am not sure as to how to go about writing code to send a ping or some sort of message when the camera detects a heat source.

Does anyone know of any way to do this?

Thanks

答:
@Chuck 's comment is correct; You can have some sort of polling software which detects some image (continuously tries to detect an object from image stream).

Else, if this does not work, then, it is better to add some other sensor like proximity sensor or so to detect objects like human and then turn on thermal camera if a threshold is crossed. But, as @Chuck mentions, unless the objectives are known, it is difficult to help you out.

If an image-array is obtained, then image-processing can be done through many libraries. Some of the libraries which I remember are OpenCV, MATLAB, PIL (Python Imaging Library), BoofCV, JavaCV, SimpleCV etc (depending on your programming language).


答: I have a gut-feeling that the question cannot be answered without the details of the motors. I see that analogWrite() is being used along with a delay of 0.1s . In Arduino, analogWrite() is a PWM itself running at about 490Hz/980Hz and additional delays may not be necessary. Servos generally use 1 milli-second to 2 milli-second 50 Hz PWM as mentioned in this description https://learn.sparkfun.com/tutorials/pulse-width-modulation . Servo motors use feedback and internal softwares most of the times - http://www.electronicshub.org/servo-motors/ . So, it is better to use Arduino Servo Library and program using 'servo angles' like this: https://learn.adafruit.com/adafruit-arduino-lesson-14-servo-motors/arduino-code-for-sweep .

Title: How to program a continuous servo motor? (Arduino)

Body:
I need to use continuously rotating servo for a camera stabilization system. My professor bought servos that have already been modified for continuous motion--there's no stop in the gears, and the potentiometer allows it to spin 360+ degrees.

I am currently using PWM with an Arduino Uno. The servo does spin continuously, but not in a stable way. I've also taken out the potentiometer in another one of the servo, and on a third servo I used a voltage divider in place of the potentiometer.

I've tried static values and a "sweep" from 0% duty cycle to 100% to get a feeling for how they work, but I just cannot figure it out. I greatly would appreciate any tips on this.

Here is my code:

```<code> //PWM test for continious motion Servo

 int servoPin = 9; // connect servo to pin 10
 int pwmVal = 0; // declare pulse width modulation value

void setup(void) {
  pinMode(servoPin, OUTPUT); //set up the servoPin as an output pin
  Serial.begin(9600); // begin serial monitor
}

void loop(void) {

  //for loop that sweeps values from 0 to 255
  for (pwmVal = 0; pwmVal <= 253; pwmVal += 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }
  for (pwmVal = 253; pwmVal >= 0; pwmVal -= 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }

  //assign a static pwm value
  pwmVal = 0;
  analogWrite(servoPin, pwmVal);
}
</code>```


问:
Robot Veering to the Left
I'm currently programming in RobotC, for a Vex 2.0 Cortex. I'm using encoders to make my robot go straight.

This is my code:

```<code>#pragma config(I2C_Usage, I2C1, i2cSensors)
#pragma config(Sensor, dgtl2,  ,               sensorDigitalIn)
#pragma config(Sensor, dgtl7,  ,               sensorDigitalOut)
#pragma config(Sensor, I2C_1,  ,               sensorQuadEncoderOnI2CPort,    , AutoAssign )
#pragma config(Sensor, I2C_2,  ,               sensorQuadEncoderOnI2CPort,    , AutoAssign )
#pragma config(Motor,  port1,           RM,            tmotorVex393_HBridge, openLoop, reversed, encoderPort, I2C_2)
#pragma config(Motor,  port10,          LM,            tmotorVex393_HBridge, openLoop, encoderPort, I2C_1)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

/* Port 1 is right motor*/

//all functions expect no reverse motors (in port menu)
//**GLOBAL VARIABLES**
int buttonSTATE = 0;

//**MOVE FUNCTIONS**
void goforwards(int time)
{
    int Tcount = 0;
    int speed1 = 30;
    int speed2 = 30;
    int difference = 5;

    motor[LM] = speed1;
    motor[RM] = speed2;
    while (Tcount < time)
    {
        nMotorEncoder[RM] = 0;
        nMotorEncoder[LM] = 0;

        while(nMotorEncoder[RM]<3000)
        {
            int REncoder = -nMotorEncoder[RM];
            int LEncoder = -nMotorEncoder[LM];

            if (LEncoder > REncoder)
            {
                motor[LM] = speed1 - difference;
                motor[RM] = speed2 + difference;
            }
            if (LEncoder < REncoder)
            {
                motor[LM] = speed1 + difference;
                motor[RM] = speed2 - difference;
            }
            wait1Msec(100);
        }
        Tcount ++;
    }
}

//**CONTROL STRUCTURE:**
task main()
{

    goforwards(1);
}
</code>```

When I execute the code, the Robot's encoder values are very close, but the robot quickly starts to veer to the left. What are possible causes of this? Is it something in the code?

答:
There are 4 possibilities:

One of the wheels' centre is displaced slightly.

Wheel encoders are not properly positioned and this is causing issues (like wheel pausing at odd positions while microcontroller 'thinks' it has achieved the right position)

One of the wheels' radius is lesser than the other one.

As per @GurkanSetin 's comment, friction might be causing some issue.

It is better to timestamp every count (some counts are getting missed probably) and post logs here and use some sort of feedback; preferably imaging and using some sort of minimal localisation to correct that; preferably something like this https://www.ais.uni-bonn.de/papers/ICRA_2008_Orthogonal_Wall_Correction.pdf . Even visual SLAM can be used. Some 'basic' tutorial can be found here: https://ocw.mit.edu/courses/aeronautics-and-astronautics/16-412j-cognitive-robotics-spring-2005/projects/1aslam_blas_repo.pdf (Some people place one camera sideways - orthogonal to motion of robot for monocular vision and just use template matching/image-difference)

Title: Robot Veering to the Left


问:
Odometry vs Dead-reckoning
In terms of robotics, what are the differences between odometry and dead-reckoning?

I read that odometry uses wheel sensors to estimate position, and dead-reckoning also uses wheel sensors, but "heading sensors" as well. Can someone please elaborate on this point for me?

答:
Dead reckoning is determining pose (position and rotation) using speed estimates from sensors. For example, you know your initial position and use sensors such as encoder, accelerometers, gyros, etc... to estimate your current position by integrating sensor measurements.

Odometer is determining the pose using only the rotation of the wheels of a robot. Sometime people talking about visual odometry, and visual odometry is the same except cameras are used instead of wheel encoders.

Basically, odometry is a type of dead reckoning.

Title: Odometry vs Dead-reckoning


问:
how to move my robot to the assigned coordinates
I am working on an ground surveillance robot using an Arduino mega for programming, am using components like the HMC5883L compass, Adafruit GPS for assigning of coordinates (latitude and longitude) which are the way points, I have written up the code for both the compass and the GPS and am able to get information from them, but now what I want for my robot to move to those specified coordinates (latitude and longitude waypoints) which I don't know how to do if anyone could just write an example code for me or push me to the write place I could get a sample code please do pardon me for asking such question cause I am new to coding GPS and compass and I would appreciate it if anyone could help me out or explain a bit in details what I need to do please find my code here http://textuploader.com/drqwv</p>

答:
The GPS gives the actual coordinates. The compass gives the orientation. The waypoints also have coordinates, and as I see in your code, you have defined movement primitives for your robot.

From the actual and waypoint coordinates you cen compute the heading vector required. You can compare that with the current heading vector from the compass. Your goal is to match the required heading and then match the coordinates of the waypoints.

If you have a current measured value and a desired, waypoint value, in most cases you use a closed loop controller to make the actual value equal your desired value. PID controllers are used frequently for this. Arduino implementation here.

Your problem still is that you have defined discrete motion primitives for moving the robot, so either you go left or forward. It would help you to implement a more flexible motion submodule, which can take a direction vector and move in that direction. This direction vector should come from the unit vector of the difference for between the current position and the waypoint (desired, reference) position. The speed of the motion could (or should) be correlated with the distance between the current position and the waypoint with a threshold at the end.

A function with the header:

void move_robot(Vector2 dir, float speed)

would make it possible to use a PID controller for the heading and another PID controller for the velocity. One takes care of the heading ant the other one of the speed. Both run in the same interrupt.


问:
How to remove sound comming from servo motor?
When ever i move the servo motors from the arduino, it produces sound. I don't want the servos to make this sound. How can i remove this sound. As i think this sound must be coming from the gears used inside the servo motor, but how can i silent those sound?</p>

答:
If you have the skill, it may help to open the servo and apply some vaseline to the gear, while not messing with the electronic. If you are not totally sure you have the required skill, you probably have not and will just destroy the servo.

So you have just the normal way to suppress sound:

put it inside box

use foam around the box

attach the servo well, so it would not vibrate

suppress those vibration too (usually put some rubber between servo and the base and/or between the base and rest of your device)

Keep in mind, that the servo is manipulating something, so there must be free way for it and that the servo generate a lot of heat, when it moves or protects from move, so it may need also cooling


问:
How quickly can a driverless vehicle generate control commands?
Can anyone give me a typical frequency that a driverless vehicle could generate steering and motor thrust commands?

I am trying to model a driverless vehicle in MatLab. Right now the vehicle is generating commands at 50Hz and the integrator is solving the dynamics at a 0.01s timestep (100Hz). I just want to know if this is realistic.

I would be even more grateful if you could point to a published source for this number.

答: Tom Sheridan from MIT used to say (I am paraphrasing from 25 years ago so I am sure to have some of this wrong) that robots which operate only in free space should update around 10 Hz; if they interact with environmental impedances then they should update around 100 Hz; if they have to go from free space to hard contact with a stiff environment, then at least 1 kHz.   Based on that I would recommend starting at 100 Hz and adjusting from there, depending on the additional dynamics of the system.  </p>


问:
What is exact model of haptic interface system in the paper "Time-Domain Passivity Control of Haptic Interfaces"?
I am trying to simulate the experiments in the paper "Time-Domain Passivity Control of Haptic Interfaces", Hanaford and Ryu, 2002, IEEE transactions on robotics and automation vol .18, No1
about the simulation in Fig.8 and its results are fig.9 and fig.10. I don't know an exact model of fig.9 which I can draw again in Matlab/simulink to run. I tried drawing spring and damper as in fig.6 of the same paper, but I don't know which is my input ( force, velocity or position) and also the type of signal of input (sine, step,...) to get a similar result as the paper.

I added 2 images, one is model which i drew and another is the signal of position.

I am really confused about initial condition of position . should either I choose a initial condition at Discrete-Time Integrator1, or adding a difference of 2 adders into position.
In here: damping=0 ( i want to check the case without Passivity controller)
k=30000 and I added initial condition to Discrete-Time Integrator1 is 50

[![enter image description here][3]][3]

答:
It's usually best to contact the author directly if you have a specific question about a specific paper.

The simulations are there only to illustrate the principal of the passivity observer and controller, so it makes sense they did not elaborate on them too much.

The first simulation uses velocity and position as the input and appears to have an initial position just outside the wall.

The second simulation probably has no inputs and just lets an initial condition evolve over time, with an initial position 50mm outside the wall.

Oddly, the experimental data has the exact same starting and wall position. This either indicates a meticulous attention to detail when creating the simulation or, more likely, instead of making a model of the human and haptic interface (which is complicated and problematic) they grabbed experimental data that illustrates the point they were trying to make in the paper and used that instead for the plots.

The model of Fig. 6 is the Virtual Environment and Series PC of Fig. 8. (which includes the $F=0$ when $ x(t) < 0$ nonlinearity). You will need to add models for the Human Operator and Haptic Interface to complete the model.

You will need to model the haptic interface as a non-passive system. A mass+damper with a negative coefficient would be the minimum model. They mention an active friction compensation algorithm which would behave like this to some degree.

So you would have the human (mass+spring), the device (mass+negative damper), and environment (spring+damper with dirac-delta wall boundary) all in series.

The neutral point (where the forces of the human spring and wall spring are equal) should be some distance inside the wall. The initial conditions should be outside the wall with the human spring compressed (and the wall spring at 0 deflection because of the nonlinear condition).

With the correct damping coefficients you should be able to get an oscillation.

You would need a much more complex model to get the results they claim are from simulation 2. An out-of-phase negative damping to account for sensor latency and a model of device actuator force saturation might do it. Again, my guess is that they are showing data from an experiment on the physical device rather than simulation results.

If you understand the concept of the passivity observer and passivity controller, you can move on to the next paper without fear of missing something in this one. Most of the passivity work in haptics is in response to implementation issues in real devices and the non-linearities they inflict on the previous generations shiny clean control equations. You will need to work with real haptics devices to get a good understanding of this.

EDIT: The simulink model you show is only part of the model. It would be better if you write the equation for the model. The position of the Human is different than the position of the proxy and appears to be missing (or viewed another way, the length of the spring between the human and device). The non-linearity of the wall also appears to be missing. If it helps your intuition, think of the human position as the position of the shoulder, the device (and proxy) position where the hand is, and the spring for the human is the tendons in the elbow and wrist.


问:
What is the difference between 4-point and 8-point connectivity in graph based planning?
In graph-based planning (say, A*), states are connected to their neighbors.  How should one decide whether to connect to the 4 neighbors or the 8 neighbors?  What are the pros and cons of each approach?</p>

答:
Graph-based planning algorithms are typically performed for high level planning, for example getting a robot across an office. But, the actual actuator planning for the robot is planned completely differently. This means it completely depends on your application and your desired level of complexity. If you have a grid in which cells are either occupied or not occupied, you may not want your robot transitioning diagonally for fear of collision with the neighboring cells.

In technical terms, it doesn't matter at all if you use 4 or 8 way connectivity for algorithms like A*.


问:
Orocos KDL issue with Rotation (matrix) - Inverse Kinematics
I have a problem with the Orocos IK solver, especially with the KDL::Rotation matrix input.

I try to call my KDL IK solver with a normal vector and a rotation. If I use the example values for the rotation everything went well. But as I tried to use my "own" orientation, the IK solver didn't find a solution.

```<code> KDL::Vector vektor(0.457101 , -0.629513, -0.627317);
 KDL::Rotation rotation(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); //myValues
 KDL::Frame end_effector_pose(rotation, vektor);

 rc=kdl_solver.CartToJnt(origin,end_effector_pose,result);
</code>```

As you can see it's a simple identity matrix -> no rotation -> in my opinion it should work. Anyway, if I try to call it with any other rotation matrix, it doesn't find a solution.

Just in case of

```<code>KDL::Rotation rotation(-0.0921467,0.939391, 0.330232, 0.925128, 0.203433,-0.32055,-0.368302,0.275969,-0.887803);
</code>```

it terminates with a valid solution. These values are test values from my robot.

Do I have a wrong comprehension of the rotation matrix ?

Thank you very much for your time

Devel

EDITE:

With .msg communication it works. I have no idea why ?
Does anyone know how the following lines construct the rotation matrix ??

```<code>geometry_msgs::PoseStamped pose_msg_in = pose_stamp;
tf::Stamped<tf::Pose> transform;
tf::Stamped<tf::Pose> > transform_root;
tf::poseStampedMsgToTF(pose_msg_in, transform);

tf_listener.transformPose(root_name, transform, transform_root);

KDL::Frame F_dest;  tf::transformTFToKDL(transform_root, F_dest);

int ik_valid = ik_solver_pos->CartToJnt(jnt_pos_in, F_dest, jnt_pos_out);
</code>```

Or is the matrix related to something? I get the feeling that I miss a important information.

SOLVED: Sorry, for the delay. Shahbaz answer was totally right. I simply overestimated the capabilities of my robot. The position was not reachable. After using Moveit(visualisation), it became clear that the orientation is not possible for the robot at that position (x,y,z). THANKS

答:
The vector and rotation together define the pose of the end-effector, which means its position and orientation. There are 6 degrees of freedom here (presumably), so you can think of the position as a point and the orientation as a direction (I'm avoiding "vector" to avoid confusion):

```<code> |
 |
 |       P .-----> O
 |
 |
 +--------------------------
</code>```

Where:

P is the position of the end-effector (defined with vector in your example)

O is the orientation of the end-effector (defined with rotation in your example)

So, what does the identity mean for the rotation matrix? It means the end-effector has the same orientation as a predefined original orientation. This could be different per robot. Let's say the original orientation has z upwards and x westwards.

What you are asking the solver is to solve IK for the end-effector at a given position and pointing upwards. As the function fails, it's clear that such a pose is unreachable by the robot.

Do I have a wrong comprehension of the rotation matrix ?

Can't tell without knowing what your comprehension of the rotation matrix is! But the rotation matrix as I said defines the orientation based on some original orientation. The identity matrix is not a magic matrix where everything should work.

Body:
The vector and rotation together define the pose of the end-effector, which means its position and orientation. There are 6 degrees of freedom here (presumably), so you can think of the position as a point and the orientation as a direction (I'm avoiding "vector" to avoid confusion):

 |
 |
 |       P .-----> O
 |
 |
 +--------------------------

Where:

P is the position of the end-effector (defined with vector in your example)

O is the orientation of the end-effector (defined with rotation in your example)

So, what does the identity mean for the rotation matrix? It means the end-effector has the same orientation as a predefined original orientation. This could be different per robot. Let's say the original orientation has z upwards and x westwards.

What you are asking the solver is to solve IK for the end-effector at a given position and pointing upwards. As the function fails, it's clear that such a pose is unreachable by the robot.

Do I have a wrong comprehension of the rotation matrix ?

Can't tell without knowing what your comprehension of the rotation matrix is! But the rotation matrix as I said defines the orientation based on some original orientation. The identity matrix is not a magic matrix where everything should work.


问:
Scale problem with monocular visual odometry
Is monocular visual odometry able to estimate relative scale? Say I have a sequence of 10 images that are taken on a single track each 1 m after the previous. Can some mono odometry method distinguish relative scale when it processes image pairs that are in various distances from each other? I mean like processing 1st vs 10th image and 9th vs 10th image - will the fist give 10x relative scale than the second?

I am examining OpenCV based odometry code (https://github.com/avisingh599/mono-vo) but it only gives something like "translation vector" that always has a size of 1 regardless the distance measured. I know mono odometry can not do absolute scale but I thought it can do relative (question is what "relative" actually means here). Seems like OpenCV's recoverPose only do a translation vector that has always the same size (I guess the size is 1)?

答:
processing 1st vs 10th image and 9th vs 10th image - will the fist give 10x relative scale than the second?

It depends. In the simplest perspective, 'relative' means what the transformation is from one view to another, given two images. So if you just use multiple view geometry techniques to find the transformation between any two images, you'll always end up with a unit vector. (This is what the OpenCV based odometry code is doing, through the findEssentialMat/recoverPose function). Without any additional initialization or accumulation of external information, relative translation will always be a unit vector: i.e., just the bearing/direction between the views, and the definition of 'relative' is "view 2 relative to view 1".

But let's say you capture 10 images with equal intervals in between, moving in a straight line. If you use the 1st and the 10th image (which, naturally, would be described through a relative translation of magnitude 1), you can reconstruct the environment you were observing in 3D up to (arbitrary) scale through triangulation. Now if you use this 3D set of points to localize the rest of the images and obtain the distance between 5 and 6, or view 9 and 10 for instance, you'll see that the relative distance now, is 0.1. Here, the definition of 'relative' becomes "relative distance between view x and view y with respect to a 3D environment that I've already triangulated".


问:
what is the difference between a voltage source and current source?
I know,this question is irrelevant.But,while working suddenly this question came through my head..my point is there should not be any difference between a voltage source and a current source.cause,these two are dependent on each other.if there is a  potential difference then,there will be a current flow...similarly,if there is a flow of current then there must be a voltage difference....isn't it?

please,make the topic clear.....

答:
You are correct in that they are related, via Ohm's law:

$$
V = IR \\
$$

The difference is in what gets regulated. A voltage source will keep supply voltage at a constant level by altering the current that is supplied. If the effective (Thevenin) resistance goes down, then the applied current must go up to keep the supplied voltage constant.

Similarly, if you rearrange Ohm's law to look at the supplied current:

$$
I = V/R \\
$$

You can see that, for a current source, if the effective resistance goes down, the applied voltage must also go down in order to keep the supplied current constant.


问:
RobotC Code Malfuncion (VEX Robotics Clawbot)
I have a standard VEX Clawbot, which I've been trying to make go straight for some time.

I've been following this guide:
http://www.education.rec.ri.cmu.edu/products/cortex_video_trainer/lesson/3-5AutomatedStraightening2.html

This is my code:

```<code>#pragma config(I2C_Usage, I2C1, i2cSensors)
#pragma config(Sensor, I2C_1,  ,               sensorQuadEncoderOnI2CPort,    , AutoAssign )
#pragma config(Sensor, I2C_2,  ,               sensorQuadEncoderOnI2CPort,    , AutoAssign )
#pragma config(Motor,  port1,           leftMotor,     tmotorVex393_HBridge, openLoop, driveLeft, encoderPort, I2C_1)
#pragma config(Motor,  port10,          rightMotor,    tmotorVex393_HBridge, openLoop, reversed, driveRight, encoderPort, I2C_2)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

void GOforwards()
{
    nMotorEncoder[rightMotor]=0;
    nMotorEncoder[leftMotor]=0;
    int rightEncoder = abs(nMotorEncoder[rightMotor]);
    int leftEncoder = abs(nMotorEncoder[leftMotor]);

    wait1Msec(2000);
    motor[rightMotor] = 60;
    motor[leftMotor] = 60;

    while (rightEncoder < 2000)
    {
        if (rightEncoder > leftEncoder)
        {
            motor[rightMotor] = 50;
            motor[leftMotor] = 60;
        }
        if (rightEncoder < leftEncoder)
        {
            motor[rightMotor] = 60;
            motor[leftMotor] = 50;
        }
        if (rightEncoder == leftEncoder)
        {
            motor[rightMotor] = 60;
            motor[leftMotor] = 60;
        }
    }
    motor[rightMotor] = 0;
    motor[leftMotor] = 0;
}

task main()
{
GOforwards();
}
</code>```

I am using integrated Encoders.

When I run the code my robot runs without stopping and the Encoder values diverge quickly. This is a video of the code running from the debugger windows:

https://www.youtube.com/watch?time_continue=2&v=vs1Cc3xnDtM

I am not sure why the power to the wheels never changes, or why it seems to believe that the Encoder values are equal... much less why it runs off into oblivion when the code should exit the while loop once the right encoder's absolute value exceeds 2000.

Any help would be appreciated.

答:
It looks like you don't ever update the encoder values after you initialize them. The problem seems to be that maybe you're thinking that the left and right encoder values will update automatically, but that is generally not the case. The exception might be if those variable names are actually protected variable names that have special meaning in your development environment - more on that later.

I don't know about VEX robotics, but I'll caution you that your left and right encoders are based on nMotorEncoder and, just like how leftEncoder and rightEncoder doesn't get updated anywhere in your loop, nMotorEncoder doesn't get updated anywhere either.

So, that said, try using the following:

```<code>void GOforwards()
{
    nMotorEncoder[rightMotor]=0;
    nMotorEncoder[leftMotor]=0;
    int rightEncoder = abs(nMotorEncoder[rightMotor]); // <----- Define
    int leftEncoder = abs(nMotorEncoder[leftMotor]);   // <----- Define

    wait1Msec(2000);
    motor[rightMotor] = 60;
    motor[leftMotor] = 60;

    while (rightEncoder < 2000)
    {
        rightEncoder = abs(nMotorEncoder[rightMotor]); // <----- Update
        leftEncoder = abs(nMotorEncoder[leftMotor]);   // <----- Update

        if (rightEncoder > leftEncoder)
        {
            motor[rightMotor] = 50;
            motor[leftMotor] = 60;
        }
        if (rightEncoder < leftEncoder)
        {
            motor[rightMotor] = 60;
            motor[leftMotor] = 50;
        }
        if (rightEncoder == leftEncoder)
        {
            motor[rightMotor] = 60;
            motor[leftMotor] = 60;
        }
    }
    motor[rightMotor] = 0;
    motor[leftMotor] = 0;
}
</code>```

By adding the two lines inside the while loop, now you are checking and updating the encoder counts every time you step into a new loop. This is one of the tricky things with debugging - you have to be looking at the correct variables! In your video, you are looking at leftMotor and rightMotor, and what appears to be fields for those motors.

You were NOT looking at the actual variables that control which case gets selected! Those variables are leftEncoder and rightEncoder.

And again, final warning - it looks like you're counting on things like motor and nMotorEncoder to be function names or keywords that do something, because otherwise it just looks like you enter an infinite loop that never actually writes any values to the motors.

I would have expected something more along the lines of a speed assignment followed by writing that speed to a function, but that second step never happens. For example, I would have thought you'd do something like the following:

```<code>motor[leftMotor] = 60;
motor[rightMotor] = 60;
WriteMotorSpeed(motor);
</code>```

But that last function, WriteMotorSpeed() never happens. Similarly, there is no function that returns an updated encoder count. Here too it looks like you're expecting the nMotorEncoder variable name to auto-magically update, where I would have expected you to need to call a function that returns an updated value, like the following:

```<code>nMotorEncoder = GetEncoderCounts([leftMotor,rightMotor]);
</code>```

or something similar.

I could absolutely be wrong; it looks like you're using ROBOTC, and also it's VEX robotics, so there could 100% be a set of pre-defined keywords or key variable names that hold special meaning in that development environment, but again I'm just pointing out what I see versus what I would expect to see. I would highly suggest you check the documentation to see if those values automatically update or if there is, in fact, a function you should be calling to read/write encoder counts and motor speeds.

Body:
It looks like you don't ever update the encoder values after you initialize them. The problem seems to be that maybe you're thinking that the left and right encoder values will update automatically, but that is generally not the case. The exception might be if those variable names are actually protected variable names that have special meaning in your development environment - more on that later.

I don't know about VEX robotics, but I'll caution you that your left and right encoders are based on nMotorEncoder and, just like how leftEncoder and rightEncoder doesn't get updated anywhere in your loop, nMotorEncoder doesn't get updated anywhere either.

So, that said, try using the following:

void GOforwards()
{
    nMotorEncoder[rightMotor]=0;
    nMotorEncoder[leftMotor]=0;
    int rightEncoder = abs(nMotorEncoder[rightMotor]); // <----- Define
    int leftEncoder = abs(nMotorEncoder[leftMotor]);   // <----- Define

    wait1Msec(2000);
    motor[rightMotor] = 60;
    motor[leftMotor] = 60;

    while (rightEncoder < 2000)
    {
        rightEncoder = abs(nMotorEncoder[rightMotor]); // <----- Update
        leftEncoder = abs(nMotorEncoder[leftMotor]);   // <----- Update

        if (rightEncoder > leftEncoder)
        {
            motor[rightMotor] = 50;
            motor[leftMotor] = 60;
        }
        if (rightEncoder < leftEncoder)
        {
            motor[rightMotor] = 60;
            motor[leftMotor] = 50;
        }
        if (rightEncoder == leftEncoder)
        {
            motor[rightMotor] = 60;
            motor[leftMotor] = 60;
        }
    }
    motor[rightMotor] = 0;
    motor[leftMotor] = 0;
}

By adding the two lines inside the while loop, now you are checking and updating the encoder counts every time you step into a new loop. This is one of the tricky things with debugging - you have to be looking at the correct variables! In your video, you are looking at leftMotor and rightMotor, and what appears to be fields for those motors.

You were NOT looking at the actual variables that control which case gets selected! Those variables are leftEncoder and rightEncoder.

And again, final warning - it looks like you're counting on things like motor and nMotorEncoder to be function names or keywords that do something, because otherwise it just looks like you enter an infinite loop that never actually writes any values to the motors.

I would have expected something more along the lines of a speed assignment followed by writing that speed to a function, but that second step never happens. For example, I would have thought you'd do something like the following:

motor[leftMotor] = 60;
motor[rightMotor] = 60;
WriteMotorSpeed(motor);

But that last function, WriteMotorSpeed() never happens. Similarly, there is no function that returns an updated encoder count. Here too it looks like you're expecting the nMotorEncoder variable name to auto-magically update, where I would have expected you to need to call a function that returns an updated value, like the following:

nMotorEncoder = GetEncoderCounts([leftMotor,rightMotor]);

or something similar.

I could absolutely be wrong; it looks like you're using ROBOTC, and also it's VEX robotics, so there could 100% be a set of pre-defined keywords or key variable names that hold special meaning in that development environment, but again I'm just pointing out what I see versus what I would expect to see. I would highly suggest you check the documentation to see if those values automatically update or if there is, in fact, a function you should be calling to read/write encoder counts and motor speeds.