问:
angular velocity output of IMU
I am reading the paper

On-Manifold Preintegration for Real-Time
Visual-Inertial Odometry.

There is one paragraph about IMU model.

I have two questions.

The first one:
An IMU commonly includes a 3-axis accelerometer and a
3-axis gyroscope and allows measuring the rotation rate and
the acceleration of the sensor with respect to an inertial frame
what does an inertial frame mean?

The second one:
The vector(the second quantity from the first equation) is the instantaneous angular velocity of B relative
to W expressed in coordinate frame B.
The sentence is difficult for me, especially the highlighted part.

答:
1) An inertial frame is one in which a free particle travels in a straight line at constant speed, or is at rest. Practically speaking, you usually check if a frame is inertial or not by characterizing its motion w.r.t a reference inertial frame: all inertial frames are in a state of constant, rectilinear motion w.r.t one another.
In the context of visual-inertial odometry, your typical inertial frame is a local 'world' frame (W) attached to the surface of the earth where you are doing your experiment. (Note that it is only inertial because you neglect effects due to earth's rotation.)

2) Your text is missing the attached 'figure 2' but we can guess that frame 'B' is attached to your IMU.
In 3D, the rotation motion of a body (B) w.r.t to a fixed frame (W) can be characterized at any instant t by an instantaneous axis of rotation, which is a vector. This is a consequence of Euler's rotation theorem. To compute this vector, see this link.
Finally, this vector is obviously expressed differently in (B) and (W) since the two frames are rotated w.r.t one another: the vector will have different coordinates in both. Hence the addition of 'expressed in coordinate frame B'.

Title: angular velocity output of IMU


问:
Wait simulation time in a non realtime ROS simulation in Python
I want to control a quadrotor with a Python script and run the simulation as fast as my laptop can, not only in real time. I've modified my world and now the simulation runs with 7-10 real time factor.

My problem is that after acting I want the physics to run for a determinate amount of simulation time, but if I do time.sleep(steptime) the sleep is in real time, which is 7-10 times simulation time. So I need to know the real time factor in Python to divide the sleep time. Is there a way to get it?

答:
@kNo the proper way to use time in ROS is generally to use the ros::Time abstraction and the /clock topic. This way you can use the same program with simulated and real time. Your simulator program should be the one publishing on <code>/clock</code>.
Trying to access the real time factor is unnecessarily complicated. </p>

ContentLicense: CC BY-SA 4.0

Body:
@kNo the proper way to use time in ROS is generally to use the ros::Time abstraction and the /clock topic. This way you can use the same program with simulated and real time. Your simulator program should be the one publishing on /clock.
Trying to access the real time factor is unnecessarily complicated.


问:
Lost on Graph slam's loop cloursure
What is the definition of loop closure in Graph Slam?

Ref: Graph Slam

The theory of Graph Slam define here but I think there is no hints about loop closure. I give this reference for review purpose.

答:
The GraphSLAM algorithm from the paper you linked does not have a loop closure mechanism in the sense of a dedicated procedure for finding correspondences between landmarks observed at different nodes separated by an arbitrary distance/time interval. GraphSLAM effectively tests every non-corresponding pair of features/landmarks in turn to look for new correspondences.

If it seems inefficient, note that it is an offline SLAM algorithm: its purpose is to estimate the posterior probability over the entire path along with the map, instead of just the current pose. Offline algorithms are typically less concerned with computational or memory constraints as they can sometimes run on more powerful computers and can take longer to run.

The paper also notes just above the algorithm (Table 10) that "The inner loop of this algorithm can be made more efficient by selective probing of feature pairs m_j, m_k, [...]". Such a 'selective probing' would - at least naively - be done using some form of nearest neighbour search to test 'close' features before 'far' features for correspondence. It still wouldn't be a dedicated procedure so I wouldn't call it 'Loop closure', but it gets closer to the idea.

Title: Lost on Graph slam's loop cloursure


问:
Why are two cameras mounted in paralle in stereo application?
For stereo cameras on the market, two cameras are always mounted side by side and with a displacement that is perpendicular to the cameras’ optical axes. I take this setup for granted. One idea came to my mind whether this is necessary? If two cameras are not parallel and have different focal length, camera calibration can correct the difference. Why are two cameras mounted in parallel? My guess is that two cameras can have a large overlapping region. Am I correct?</p>

答: Making them parallel is beneficial for reducing distortion after a rectification. We usually rectify two images for a fast matching. If speed is not your concern you can skip the rectification stage.</p>

ContentLicense: CC BY-SA 3.0


问:
Fixing the first node in Graph-based SLAM
The first node in the graph SLAM should be fixed. The famous "a tutorial on graph based slam" paper is showing that we can fix a node by adding identity matrix. Why adding identity to the Hessian of the specific node results in fixing that node? What is the theory behind it? Any good material to read?

答:
Not a definitive answer but here are my thoughts:
Fixing node $k$ is equivalent to enforcing $\Delta x_{k} = 0$. Now we must show that adding $I$ to diagonal block $H_{kk}$ will result in $\Delta x_{k} = 0$. Let's name $H_{orig}$ the original matrix $H$ before adding $I$ to diagonal block $H_{kk}$, we have:
$$
(H_{orig}+\begin{bmatrix}
 0  &  &  &  &  & \\
 &  ...  &  &  &  & \\
 &  &  0  &  &  & \\
 &  &  &  I  &  & \\
 &  &  &  &  0  & \\
 &  &  &  &  &  ... \\
 &  &  &  &  &  & 0
\end{bmatrix})\Delta x = -b \Leftrightarrow H_{orig}\Delta x + \Delta x_{k} = -b
$$
Can we show that $H_{orig}\Delta x + \Delta x_{k} = -b \Rightarrow \Delta x_{k} = 0$ ?</p>


问:
Robotic arm ["FAiL"] error display. - Festo / Mitsubishi Melfa RV-2AJ (Controller CR1-571)
To avoid wasting your time on this question, you might only want to react on this if you have knowledge of industrial robotic arms specific.
Common troubleshooting is unlikely to fix this problem or could take too much time.

We've started a project with the Mitsubishi Melfa RV-2AJ robotic arm.
Everything went fine until the moment we replaced the batteries.

The controller displays: "FAiL" and does not respond to any buttons or commands sent through serial connection.

We did replace the batteries of both the robot and the controller. As it took some time to get the batteries delivered, we've left the robot (and controller) withouth power for the weekend. (Which might have caused this problem)

Is there anyone with knowledge of Mitsubishi Robotic arms around here?
I'm kinda hoping it would be a common problem/mistake and anyone with experience on this subject would know about it?

答:
All the steps are actually correct there- accept, when you press RESET, you curt need to select your
Robot type, I usually just keep pressing RESET till I get USER, then press start & only then it displays
ramclr or something</p>


问:
What is the cheapest / easiest way of detecting a person?
I'd like to know if anyone has had success detecting a warm-bodied mammal (ie. Human) using standard off the shelf, inexpensive sensors?

Ideally, I'd like to use an inexpensive sensor or combination of sensors to detect a person within a room and localize that person. I would like the robot to enter a room, detect if a human(s) is/are present and then move to the detected human. The accuracy does not need to be 100%, as cost is more of a factor. I'd like the computational requirements of such a sensor to be such that it can run on an Arduino, although if it's impossible, I'd be willing to utilize something with more horespower, such as a Raspberry Pi or a BeagleBone Black. I have a few thoughts; however, none of them are ideal:

PIR Sensor - Can detect movement within a large field of vision (ie. usually 120 degrees or more).  Might be the closest thing to a "human" detector that I'm aware of; however, it requires movement and localizing/triangulating where a person is would be very difficult (impossible?) with such a large field of vision.

Ultrasound - Can detect objects with good precision.  Has a much narrower field of view; however, is unable to differentiate between a static non-living object and a human.

IR detectors - (ie. Sharp range sensors) Can again detect objects with great precision, very narrow field of view; however, it is again unable to differentiate objects.

Webcam + OpenCV - Possibly use face detection to detect human(s) in a room.  This may be the best option; however, OpenCV is computationally expensive and would require much more than an arduino to run.  Even on a Raspberry Pi, it can be slow.

Kinect - Using the feature detection capabilities of Kinect, it would be relatively easy to identify humans in an area; however, the Kinect is too expensive and I would not consider it a "cheap" solution.

Perhaps someone is aware of a inexpensive "heat-detector" tuned to body heat and/or has had success with some combination of (#1-4) above and would like to share their results?

答:
A non-bare-metal solution that will probably become increasingly popular over the next few years would be to offload your heavy data processing task (e.g recognizing a human in an image) to a Cloud service. That's assuming your device is connected to the internet.
Here is an example with the Raspberry Pi and the Google Cloud Vision API : https://www.dexterindustries.com/howto/use-google-cloud-vision-on-the-raspberry-pi/. Note that it requires a subscription to google cloud past a trial period, but some other cloud vision APIs (Amazon, Microsoft Azure, ... ?) may even offer their services for free if you submit less than N requests per month to their servers.

Yet another solution for heavy data processing on small platforms would be to offload the work to a thumbdrive-like device on your robot with a dedicated processor unit for running already-trained machine learning models (e.g Movidius Neural Compute Stick with the Raspberry PI: https://medium.com/deep-learning-turkey/a-brief-guide-to-intel-movidius-neural-compute-stick-with-raspberry-pi-3-f60bf7683d40 ). This works offline too. They're still a bit expensive for hobby projects but I expect their cost will go down like everything.


问:
Getting error on serial monitor when using serial controlled motor
I am using this motor in a robotic arm.

I wanted to move it to a position and the position was provided via an input but I am getting errors on Serial Monitor. Initially when I tried this ,  name of the serial controller i.e Rhino Motor Controller got printed on serial monitor indicating that the controller is working .But the problem is that I am not able to control the motor via Serial communication because I think it is not accepting the serial commands.

Here is the datasheet for the motor driver.

Here is the code:

```<code>#include <SoftwareSerial.h>
int angle ;

int position ;

int speed ;

String stringG1 ;

SoftwareSerial Serial1(10,11);

void setup()
{
  Serial.begin(38400);
  Serial1.begin(38400);

}
void loop()
{
  angle = Serial.read();
  int position = 4*angle  ;
  speed = 10 ;

  if(Serial.available()>0)
    {
    stringG1 = "N1" + String(position) + String(speed);
    Serial1.println(stringG1);

    if (Serial1.available()>0)
      {
      Serial.print(Serial1.readString());
      }
    }
}
</code>```

Output on serial monitor ,

```<code>N1-410
Err
:N1-410
Err
:N122810
Err
:N1-410
⸮⸮⸮5
:N119215⸮⸮5
:Nj⸮⸮0
Err
:N⸮⸮2810
Err
:N1-410
Err
:N119610
Err
:N119210
Err
:N119210RErr
:N1-41jT⸮⸮5
:N122810
⸮⸮⸮5
:N1-410
⸮⸮⸮5
:
</code>```

答:
Welcome to Robotics, Sam. You've posted your code and the errors you're getting, which is great. There are still a few pieces of information lacking, though. Unfortunately, it looks like the "datasheet" is pretty poor and there are several items that I would like to see that I can't find.

With some information missing, here's the list of troubleshooting steps I would take to try to identify the problem. I'm assuming, since you're able to get an error message back from the motor controller, that the wiring between the Arduino and the motor controller is generally okay. Here are the next things I would check:

Obviously, if it was working previously and now it is not working, then what did you change? Did you change software, or wiring, power supplies, power supply settings, etc.?

Riding on point (1) above, but there is a motor connected, right? You're requesting a particular position, but if there's no motor connected then it's not getting any feedback, or it might fault if it applies terminal voltage to the motor but then doesn't register any current flow.

This seems most likely to me - is your command formatted correctly? You send a command like N122810, but how does the motor controller know where position ends and speed starts? In carefully reading the datasheet, it looks like there's supposed to be a space between position and speed when you send the command. You do not have a space. I had thought maybe the space was a typo on the datasheet, but I can't tell how the motor controller would tell the difference between a pos/speed of 12 and 5 and a pos/speed of 1 and 25 without some kind of delimiter.

If that doesn't work, try using other commands. If you can successfully (and repeatably!!) poll the device with the S command, then that would eliminate the rest of the steps I've given here. If you can get S to work, try a position-only move with the P or N0 commands.

If that doesn't work, it might be an issue with the println. The data sheet says to terminate the command with \r, but println terminates with \r\n. If the motor controller can parse correctly then this shouldn't be an issue.

If that doesn't work, it might be an issue with ASCII/binary, and you might need to use Serial1.write() instead of Serial1.print() or Serial1.println().

It could also be an issue with voltage levels and proper registration of HIGH/LOW signals. If the Arduino is outputting on a 3.3V level, but the motor controller is expecting a 5V level, then HIGH on the Arduino output would fall in the "no man's land" of levels. Typically, a low is guaranteed to be registered at <0.3*vMax, a high is guaranteed to be registered at >0.7*vMax, and any signal between 0.3 and 0.7 of vMax is "ambiguous" and not guaranteed to be read correctly.

It could be an issue with voltage supply to the motor controller. The motor controller is supposed to get a 7-12V input. If, for example, you're powering it off of the 5V output on the Arduino, then you're under-powering the board and can get unexpected results.

:EDIT:

I think your issue might be due to a lack of common ground reference between the Arduino and the motor controller. If you're using a 9V battery to power the motor AND the motor controller, consider the circuit below:

It's also important to note that your 9V battery is probably insufficient to run the motor. For starters, the motor datasheet states the motor should be running on 12V.

Here is a source that shows battery capacity versus discharge rate. The "no load" rating on the motor shows it draws 75mA with zero load. The capacity chart then gives a battery life of about 4 hours with no load. If, however, you go to the rated load of 1400 mA, the battery chart, which tops out at a discharge rating of 1000 mA, estimates the battery life to be about four minutes.

My reading of the datasheet (it's sparse) gives me the feeling that the Vcc 5V connection is a 5V output, meant to power the actual encoder on the motor. You should not be powering this pin.

Finally, if the motor is drawing a large amount of current, it could be browning out battery supply. If/when the 9V battery's terminal voltage falls below 7V, the motor controller becomes underpowered and you become likely to get erratic operation. This might also explain the weird symbols you're getting back from the motor controller, like ⸮⸮⸮5

If this doesn't help, please edit your question to include pictures and/or a drawing of how you currently have everything wired.

Also, I might have the Rx/Tx lines backward in the drawing, but it sounds like you've got your communication to the motor controller already correct.


问:
Why do quadcopters use brushless motors?
I've been thinking about starting a quadcopter project, maybe building it from scratch. One of the main barriers-to-entry for me is the motors: it seems like most quadcopters use brushless motors. I have some experience with DC motors and using PWM signals to regulate speed, but no experience with brushless motors. As I understand it, brushless motors are more expensive than the typical DC motor I would use on a land robot, and they also require Electronic Speed Controllers (ESCs), which seem to make them (from my perspective) even more expensive and more complicated to use.

So, my question: what is it about brushless motors that make them useful in a quadcopter? Is it more torque, less weight, something to do with efficiency? And would it be significantly harder (or even possible) to achieve lift using DC motors instead?

答:
The brushless motors are way more powerful for their weight than available brushed motors, and they last longer.

Power to weight ratio is king, in an aircraft.


问:
GraphSLAM equation doubt
I have question about GraphSLAM implementation.

To find out the path and map using GraphSLAM we rely on this equation:

$$\mu=\Omega^{-1}\xi$$

where $\Omega$ is our information matrix which determine the link between two nodes of graph and link between a landmark and a node. The $\xi$ vector give us the value of constraint between two consecutive robot pose or a robot pose and landmark.

I want to clarify that why a matrix inversion multiplied by a vector give us path and map. What is the mathematical logic, algorithm or assumption behind this?

Is it related to Floyds' shortest path algorithm or any other graph based algorithm related to it?

For reference I studied The GraphSLAM Algorithm with Applications to Large-Scale Mapping of Urban Structures and listened to the lecture series of Udacity.

However, I cannot understand where this equation came from. Also, I have a little bit of doubt about implementing GraphSLAM in a real dataset for the huge dimension on $\Omega$ Matrix and its inversion. Is it possible for a 75000 dataset?

答:
1) I believe the previous replies/comments already directed you to good online resources. I will just add some comments about the intuition behind the equations.

Putting aside SLAM, in general mathematics, I assume you have an understanding of what the covariance matrix $\Sigma$ represents for a multivariate Gaussian.
Now the information matrix is defined as its inverse:
$$
\Omega = \Sigma^{-1}
$$
and the information vector is defined as:
$$
\xi = \Sigma^{-1} \mu
$$
Note that these are mathematical definitions, you don't have to worry about the meaning of these quantities just yet.
From these definitions, you obviously get:
$$
\Sigma = \Omega^{-1}
$$
$$
\mu = \Omega^{-1} \xi
$$

Now what do these quantities represent in GraphSLAM?

Remember that the objective of the GraphSLAM algorithm is to compute a Gaussian approximation of the posterior over the entire robot trajectory and the map. This gaussian approximation, like all gaussian distributions, has a mean $\mu$ and a covariance matrix $\Sigma$, which means that you can also define its information matrix $\Omega$ and information vector $\xi$ using the definitions above.
If you have $\Omega$ and $\xi$ you can get $\Sigma$ and $\mu$ (and vice-versa), it's as simple as that.

The real question is, why would you bother with the information form ($\Omega$ and $\xi$) instead of trying to find the mean $\mu$ and the covariance $\Sigma$ of your posterior directly?

Thrun answered this question previously, in 2002, when he published another algorithm, the Sparse Extended Information Filters (SEIFs). SEIFs was a variation of the Extended Information Filter (EIF), the dual of the very popular Extended Kalman Filter (EKF). The SEIFs paper showed that sparsity in the information form of the SLAM problem:
1) had a 'physical' meaning as a graphical network of locally-interconnected features (which is actually a Gaussian Markov Random Field), and
2) enabled us to use well-known, highly efficient algorithms from linear algebra for matrix factorization.

I highly suggest that you check out the SEIFs paper - or section 3.4 of Probabilistic Robotics as others have suggested - if you want to understand the information form of SLAM.

Now GraphSLAM (2006) is very closely related to SEIFs, but it introduces several new things:
1) it is an offline algorithm (estimates entire trajectory + map) instead of an online algorithm/'filter' (estimates current trajectory + map),
2) after linearizing constraints, it uses a factorization trick (see Fig. 3 in the paper) to shift information between poses and features to information between pairs of poses. This gives you a new structure constraining poses only, making it easier to compute them. Once they are computed, the feature location are computed too, based on the original feature-to-pose information.

Regardless of the specificities of GraphSLAM, if you understand the information form of SLAM from SEIFs and you understand that GraphSLAM is offline instead of online, you should be able to understand $\mu = \Omega^{-1} \xi$.

2) Now on to your 2nd question regarding the dataset. By '75000 dataset' I suppose you mean a dataset of 75000 landmarks. By asking if it is 'possible' I am not sure whether your are concerned about the accuracy of the map, the computational complexity, or both?
Inverting a large $\Sigma$ matrix is what initially deterred people from investigating the EIF-route, until they figured out the inherent sparsity of the SLAM problem.
As I explained above, this sparsity allows for efficient matrix factorization.
Section 7 of the GraphSLAM paper has some quantified results that should answer your question. If not, please clarify.

Title: GraphSLAM equation doubt


问:
iRobot Create 2 Flash CRC message
In testing my iRobot Create 2, I discovered that the following message is being sent periodically over the serial interface: "    Flash CRC successful: 0x0 (0x0)". Is this expected behavior or am I making an error in the way I'm connecting? I could not find this message documented anywhere.

To reproduce this: iRobot Create 2 connected to a Windows 10 PC via the USB-Serial cable. Connecting via Putty at 115200 baud. Type ctrl-G to reboot the robot. I'll see the normal reboot message, then after a few minutes, the robot sends the above Flash CRC message.

答:
Yes, Create 2 displays all kinds of internal debugging messages in plain text when it is not in an open interface mode. (For a less obtuse one, try putting it on the dock while you are connected to the serial port!) These will go away once you enter OI mode (op code 128).

Please note that I am an iRobot employee, but the postings on this site are my own and don't necessarily represent iRobot's positions, strategies, or opinions.

Title: iRobot Create 2 Flash CRC message


问:
Graph slam augmentation of Identity Matrix
I am trying to implement GraphSlam. I go through this paper http://robots.stanford.edu/papers/thrun.graphslam.pdf. I have some doubt about the algorithm. I attached a picture with this question

My question is that what is the need to augmented a identity matrix in line no 7 and 8 of this algorithm.

Please help to clear the doubt.

答:
In GraphSLAM, the information matrix $\Omega$ and the information vector $\xi$ are given directly by the log of the full posterior via the following expression:

Therefore we need to derive an expression for our full posterior which looks like Eq 26 above so that we can identify $\Omega$ and $\xi$.

This is done in sections 5-1 to 5-3 of the paper, and results in this ugly expression for the full posterior:

Even if you don't fully understand this expression, you can see that it includes two sums: one over $t$ and the other one over $i$. The first sum corresponds to the constraints resulting from controls/odometry, whereas the second corresponds to the constraints resulting from landmark measurements.
The lines 7 and 8 of the algorithm you posted above simply add the contribution of one control/odometry constraint to $\Omega$ and $\xi$. You can see that they are inside a loop iterating over all the $t$ controls, which corresponds exactly to our first sum in equation 25.
In lines 18 and 19 of the algorithm (not visible on your image) you can see the same thing being done for the measurement constraints.

And this is how we build $\Omega$ and $\xi$.


问:
How to generate Particles in Particle Filter?
I have been trying to implement FastSlam 1.0. To implement this, I need to create particles. Now my confusion is how to create Particles? I have some odometry and Measurement data. Using those data values, how could I generate the Particles?</p>

答:
At $t_{0}$ your particles should have some initial distribution. To simplify you can assume that all particles are aligned at the same pose $x_{0}$.

For subsequent timesteps, let's say you have all the particles at time $t-1$ and you want to get a new particle set for time $t$. FastSLAM 1.0 uses only the motion model to propagate the particles, so the new particles at time $t$ are sampled according to:

Now to translate this equation into code you need to define a motion model for your robot. These slides introduce several probabilistic motion models depending on the type of robot you are using (odometry-based, velocity-based).

Let's assume we take the following odometry-based motion model:

Now to propagate particle $k$ from time $t-1$ to time $t$, you take the pose $x, y, \theta$ of particle $k$ at time $t-1$ + your odometry measurements $u$ and you feed them to the sample_motion_model(u,x) algorithm. The output will be $x', y', \theta'$, the pose of particle $k$ at time $t$.


问:
Serious about robotics programming, should I start with an Arduino?
I've read that Arduino's are actually not necessarily a good option for getting into robotics/embedded systems, as there are many shortcuts and you don't learn the real way of how it all works. When I started app dev, I jumped straight into it and never had any practice with simpler things such as Scratch or other app builders. I got straight into the IDE and learned the programming language. If Arduino's are just for hobbyists, I want nothing to do with them.

I'm able to grasp things quickly and study intensively, should I start with an individual microcontroller or still stick to the Arduino? If a microcontroller, which one and why? I understand the differences between the Arduino and a stand-alone microcontroller, have no previous experience programming hardware, but that was the same with app dev and I got on just fine with the programming.

Many thanks.

答:
Arduino boards are simple microcontroller boards that are a good complexity for learning. The arduino IDE hides the details of typical bare metal microcontroller development, but not in a bad way.

The difference between a hobbyist that only knows arduino and a professional is that a professional will select the right microcontroller for the job from the 1000's available, and will often (but not always) write software using a more sophisticated approach. Sophisticated is a vague idea but includes things like the way interrupts or DMA are used, or using an embedded operating system.

I think the biggest risk you would face if you started with arduino is that most of the information out there is written for hobbyist, which assumes the reader does not know or understand the fundamentals of embedded design, and sometimes is written by a hobbyist who does not know what they are talking about and will provide (unintentionally) misleading or wrong information.

Start with a course in embedded systems so that you understand some of the basic concepts. You can find useful stuff on the internet if you can't attend a real one.


问:
Is this SLAM performance typical or am I doing something wrong?
I'm experimenting with SLAM for the first time. I am using ROS on a Turtlebot3, which has a Raspberry Pi and a single Lidar sensor, Robotis LDS-01. I am running a configuration with three computers, the Pi, a computer running just Roscore and a computer where I do my development. I have a very simple maze set up covering around a 3x3M carpeted area. I am using gmapping to make the map. As I am a remote worker, I've not had an "expert" looking over my shoulder although I am very active on boards to ask questions.

My experience with SLAM is that I am not impressed with the results so far.  I've been following these instructions from Robotis as a starting point.

I run gmapping and traverse the maze completely and do get a map that is pretty accurate although the resolution is I think 5x5cm by default so its a little rough. Its super simple.

But then I save the map and run navigation, using move_base, amcl and map_server. To my eye the results are not impressive:

when I use RVize to give the initial pose hint, the map is not particularly well aligned with the results of the lidar

When I ask to navigate it will get there but throwing lots of errors in the console. See below for a sampling of the errors

the robot moves in fits and starts. Sometimes stopping for a few seconds, sometimes repeating the same motion over and over again, and in general not being smooth.

Questions:

Does it sounds like I have a setup problem fundamentally?

Is this just what you get when you use just LIDAR?

Is my maze too small?

Is this because I need to "tune" my SLAM?

Sampling of Errors from slam

```<code>$ roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:=$HOME/map.yaml

[INFO] [1535381131.875583266]: Got new plan
[ INFO] [1535381132.075471469]: Got new plan
[ WARN] [1535381132.180568313]: DWA planner failed to produce path.
[ INFO] [1535381132.275184519]: Got new plan
[ INFO] [1535381132.475446249]: Got new plan
[ WARN] [1535381132.575722364]: Rotate recovery behavior started.
[ERROR] [1535381132.576713131]: Rotate recovery can't rotate in place because there is a potential collision. Cost: -1.00
[ INFO] [1535381132.675482447]: Got new plan
[ INFO] [1535381132.875441949]: Got new plan

[ INFO] [1535381156.901500928]: Got new plan
[ INFO] [1535381157.101396956]: Got new plan
[ INFO] [1535381157.301632070]: Got new plan
[ INFO] [1535381157.302170120]: Goal reached
[ WARN] [1535381169.092857809]: Costmap2DROS transform timeout. Current time: 1535381169.0925, global_pose stamp: 1535381168.5424, tolerance: 0.5000
[ WARN] [1535381169.093196300]: Could not get robot pose, cancelling reconfiguration
[ WARN] [1535381170.092852095]: Costmap2DROS transform timeout. Current time: 1535381170.0926, global_pose stamp: 1535381168.5424, tolerance: 0.5000
[ WARN] [1535381170.192729304]: Could not get robot pose, cancelling reconfiguration
[ WARN] [1535381171.097531131]: Costmap2DROS transform timeout. Current time: 1535381171.0972, global_pose stamp: 1535381168.5424, tolerance: 0.5000
[ WARN] [1535381171.292652884]: Could not get robot pose, cancelling reconfiguration
[ WARN] [1535381172.097543923]: Costmap2DROS transform timeout. Current time: 1535381172.0973, global_pose stamp: 1535381168.5424, tolerance: 0.5000
[ WARN] [1535381172.393145114]: Could not get robot pose, cancelling reconfiguration
[ WARN] [1535381190.292336646]: Costmap2DROS transform timeout. Current time: 1535381190.2920, global_pose stamp: 1535381189.7725, tolerance: 0.5000
[ WARN] [1535381190.292683124]: Could not get robot pose, cancelling reconfiguration
^C[rviz-5] killing on exit
</code>```

Here is map.yaml:

```<code>resolution: 0.050000
origin: [-10.000000, -10.000000, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196
</code>```

And here is the map:

答:
Your lidar has a minimum range for 12 cm, which means your maze corridors should probably be double that range (for either side of the sensor), plus the width of the sensor itself, which is 9.5 cm. That is, if your maze corridors are narrower than (12 + 12 + 9.5) = 33.5 cm, you're likely operating inside the minimum range of the scanner and may not be getting valid data.

:EDIT:

It seems like you might have a navigation issue that could be caused by your Costmap2DROS parameters. Specifically,

~<name>/inflation_radius (double, default: 0.55)

The radius in meters to which the map inflates obstacle cost values

If you are using the default value here, then it seems that the left wall would get a 0.55 meter buffer, the right wall would also get a 0.55 meter buffer, which now means your navigation algorithm might not let you pass through a corridor that's less than 1.1 meters wide.

This could combine with the navigation system's perception of the robot, defined by default as

~<name>/robot_radius (double, default: 0.46)

The radius of the robot in meters, this parameter should only be set for circular robots, all others should use the footprint parameter described above.

The footprint parameter's default setting is empty [], meaning the Costmap2DROS defaults to assuming your robot is (2*0.46) = 0.92 meters wide (that's robot radius), which compounds with the obstacle dilation described above, to where now your navigation system might think your robot won't fit unless the corridor is (1.1 + 0.92) = 2.02 meters wide. Even at that point, it could consider the corridor to be a "tight fit" because it would believe the sides of your robot are scraping the walls.

A relatively straightforward test would be to check and correct the robot_radius parameter, or disable it by entering values for the footprint parameter, then try setting the inflation_radius to zero or something close to zero.

If this doesn't work, please edit your question to post the local_ and global_costmap settings and then please also provide a dimensioned drawing (sketch, etc.) of how your maze is actually arranged, along with the coordinates you're asking the robot to maneuver to.

FYI, if the image you've posted of your map is exactly your map, you've said (with your map.yaml file) that the bottom-left pixel is -10 meters, -10 meters, and each pixel is 5 cm. This means that the coordinates of approximately the middle of the top-left chamber in your "maze" is (1.6, -0.35), the center of the top-right is approximately (3.05, -0.05), and the center of the bottom chambe is approximately (2.8, -1.35). Again, all these dimensions are in meters. I don't know if these numbers sound correct to you or not, but this is how you've defined your map. This may or may not be contributing to the navigation trouble.


答: Most motors on quadcopters are outrunners. In outrunner motors, the rotating part is on the outside, and not the inside (as opposed to the inrunner motors). Because of this layout this type of motors can generate much more torque. High torque is required for quadcopters, since you balance by changing the revolutions of the motor. The higher your torque the faster you can change the speed of your propellers. High torque also means you don't need a gearbox, and save a lot of mass. Outrunners are not very practical for brushed commutation, as it would require lots of wires and additional contacts. Hence most of the outrunners are brushless.</p>

Title: Why do quadcopters use brushless motors?

Body:
I've been thinking about starting a quadcopter project, maybe building it from scratch. One of the main barriers-to-entry for me is the motors: it seems like most quadcopters use brushless motors. I have some experience with DC motors and using PWM signals to regulate speed, but no experience with brushless motors. As I understand it, brushless motors are more expensive than the typical DC motor I would use on a land robot, and they also require Electronic Speed Controllers (ESCs), which seem to make them (from my perspective) even more expensive and more complicated to use.

So, my question: what is it about brushless motors that make them useful in a quadcopter? Is it more torque, less weight, something to do with efficiency? And would it be significantly harder (or even possible) to achieve lift using DC motors instead?


问:
Gazebo - Unable to load SensorPlugin
I want to write a Doppler Velocity Log (DVL) SensorPlugin for gazebo, but gazebo fails to load the plugin. My DvlPlugin.cpp looks like this

```<code>#include "DvlPlugin.hpp"

using namespace std;
using namespace gazebo;

void DvlPlugin::Load(sensors::SensorPtr sensor, sdf::ElementPtr pluginElement){
    gzmsg << "Load" << endl;
}
</code>```

and my DvlPlugin.hpp looks like this

```<code>#ifndef _GAZEBO_DVL_PLUGIN_HPP_
#define _GAZEBO_DVL_PLUGIN_HPP_
#include <gazebo/common/common.hh>
#include <gazebo/sensors/Sensor.hh>

namespace gazebo {
    class DvlPlugin : public gazebo::SensorPlugin
    {
    public:
        DvlPlugin(){}
        ~DvlPlugin(){}
        void Load(gazebo::sensors::SensorPtr sensor, sdf::ElementPtr sdf);
    };
    GZ_REGISTER_SENSOR_PLUGIN(DvlPlugin)
}
#endif
</code>```

So there is really nothing big that is done in the code, and everything compiles without errors. When I load following simple sdf file

```<code><?xml version="1.0" ?>
<sdf version="1.6">
    <world name="worl_test">
        <model name="model_test">
            <link name="link_test">
                <pose>0 0 0 0 0 0</pose>
                <inertial><mass>0.01</mass></inertial>
                <sensor type="dvl" name="dvl_test">
                    <plugin name="gazebo_dvl" filename="libgazebo_dvl.so"/>
                </sensor>
            </link>
        </model>
    </world>
</sdf>
</code>```

I get the error [Err] [SensorManager.cc:276] Unable to create sensor of type[dvl] (which means, when we look the SensorManager.cc code, that the Sensor dvl is not in the SensorFactory. Do you have an Idea why I get this error?

PS: I am under Ubuntu 16.04 and I use gazebo 7 and I get the error even if i load the full path to the libgazebo_dvl.so.

答:
Welcome to Robotics, Chris. This question is specific to Gazebo, so you might have better luck getting a question if you ask over at the Gazebo forums.

I'll start with the comment that using namespace ____ is bad practice and just leave the comment at that.

I'm not sure how you got started with creating the plugin the way you did, but I would suggest having a look at the sensor plugin tutorial. Specifically, the example includes gazebo/gazebo.hh, which you do not. Then, they have the class inherit class ContactPlugin : public SensorPlug. You call the inheritance class DvlPlugin : public gazebo::SensorPlugin, but I'm not sure how you're getting gazebo:: anything without having included the gazebo header.

Your header calls the ElementPtr sdf, but your source file calls the same thing pluginElement. Your source file doesn't define the constructor, or the destructor, and the Load method doesn't bind the plugin to anything.

Personally, I would start with the example code in the tutorial, gut it one section at a time until you get the minimum that compiles, then fill the shell with the functionality you want. Since the specific error that you're getting is that it can't create the sensor, I would at least try adding the constructor and destructor definitions.

Title: Gazebo - Unable to load SensorPlugin


问:
Mobile robot speed synchronization for straight line moving
I would like to build a simple mobile robot with differential wheels, and I am currently design the wheel speed controller. After reading some papers, I noticed that to realize a straight line moving, the linear speed and angular speed of the mobile robot have to be controlled at the same time, which makes the system a Multi-input-multi-output (MIMO) system. I plotted two different controller structures I came across while reading materials. Both of them have angular speed feedback and control, but one with linear speed feedback and control, the other without. In the picture, Gl(s) and Gr(s) refer to the motor transfer function, and vl and vr are the measured wheel speed.

Would anyone please suggest which controller structure is more reasonable and can realize better straight line moving?

Updates
v* and w* are linear speed reference and angular speed reference respectively that could either be fixed values or come from trajectory generation; corrected a typo in the motor block in structure 2, as @Chuck pointed out, and changed G1(s) and G2(s) to Gl(s) and Gr(s) for better illustration.

答:
Chuck made a very good observation that unless your control algorithm can use sensors to reference the external environment, an odometry-based vehicle can't go perfectly straight - there's always factors unaccounted for by wheel encoders.

That said, if LIDAR/SLAM/rangefinders/compasses are out of the question (or are unnecessary for your application), you may be making this too complicated:

Drive one motor at a constant speed.

Use PID to slave other motor to the first, attempting to match speed/angular position.

In a controlled environment, with a well-tuned PID, this will achieve very good results.


问:
How reliable are IMUs for a long usage (6 hours) rotation (only) tracking?
I know they are bad for positional tracking and drift from actual position over time but would like to know what is the situation with rotation only.

I know Oculus DK1 used ordinary off-the-shelf cheap IMUs for rotation tracking of the user's head, as does any other VR headset, such as GearVR, where there is no positional tracking, but I haven't had chance to use them more than few minutes to know how much they (their IMUs) drift from original orientation over time.

答:
Take a look at this article:

When estimating attitude and heading, the best results are obtained by combining data from multiple types of sensors to take advantage of their relative strengths. For example, rate gyros can be integrated to produce angle estimates that are reliable in the short-term, but that tend to drift in the long-term. Accelerometers, on the other hand, are sensitive to vibration and other non-gravity accelerations in the short-term, but can be trusted in the long-term to provide angle estimates that do no degrade as time progresses.  Combining rate gyros and accelerometers can produce the best of both worlds - angle estimates that are resistant to vibration and immune to long-term angular drift.

To answer your question, an IMU will not drift as the accelerometers will always read against gravity.


问:
Fixed point arithmetic on microcontrollers
Often we use microcontrollers to do things in our robots, but need to make some calculations in decimal. Using floating point variables is very slow, because a software floating point library is automatically included (unless you have a high-end microcontroller). Therefore, we generally use fixed point arithmetic.

Whenever I do this, I just use an integer, and remember where the decimal place is. However, it does take some care to ensure that everything is consistent, especially when calculations involve variables where the decimal point is in a different place.

I have implemented a fixed point atan2 function, but because I was trying to squeeze every last drop of limited precision (16 bits), I would often change the definition of where the decimal point is, and it would change as I tweaked it. In addition, I would have some constants, as a quasi look-up table, which themselves have an implied decimal point somewhere.

I want to know if there is a better way. Is there a library, or set of macros, that can simplify the use of fixed point variables, making multiplication and division between mixed variables easier, and allowing declaration of decimal numbers or constant expressions, but automatically converting to the desired fixed point representation at compile time?

答:
I've used the TI IQMath Library to implement virtual floating-point on their fixed-point DSPs.

Texas Instruments TMS320C28x IQmath Library is collection of highly
  optimized and high  precision mathematical functions for C/C++
  programmers to seamlessly port a floating-point  algorithm into fixed
  point code on TMS320C28x devices. These routines are typically used in
  computationally intensive real-time applications where optimal
  execution speed and high  accuracy is critical. By using these
  routines you can achieve execution speeds considerable  faster than
  equivalent code written in standard ANSI C language. In addition, by
  providing readyto-use high precision functions, TI IQmath library can
  shorten significantly your DSP application development time.

That uses some TI specific stuff but I've also used that code as a base to implement virtual floating-point math on other microcontrollers. It takes a bit of work to port but it's a lot easier than starting from scratch.


问:
Ultra Low Power servo and controller for long usage..?
So I have an idea which would require the following:

1-4 servos
1 microcontroller
some way of communicating with it via smartphone (bluetooth or wifi)

Ability to run for 14 days on a small power source 2-3AA or AAA battries.

I'm seeing a lot of boards run in the 200Ma range which makes using batteries look like a no go as this even with a 13000mAh pack will only last 65hrs or about 3 days or so.

If I were able to get into thee micro amp range this would be great or very low mA range. Servos should only have to run <1second about 2-3 times a day.

Looking for starter information on this.

答: You may want to look into using an arduino pro mini, after disabling the power LED. This Article claims a power consumption of 0.0232 mA in power down sleep. However, adding BLE will increase power consumption greatly. I'd look into alternative solutions, such as solar power. </p>


答:
Welcome to Robotics, Mark!

IMUs are typically comprised of two core components: accelerometers and gyroscopes. They may also have a magnetometer.

An accelerometer measures linear acceleration, and a gyroscope measures angular velocity.

In order to get linear and angular position estimates, those outputs need to be integrated. I'm not sure what your background is, but integration is just an accumulation of samples with respect to time.

If you travel 50 km/h for an hour, you have gone 50 km. If you then go 25 km/hr for half an hour, you have gone and additional (25 * 0.5) = 12.5 km. Your total distance traveled is (50 + 12.5) = 62.5 km. Get the current speed, multiply by how long you've been going that speed, and add it to a running total. This is integration.

For the accelerometer, you multiply the current reading by the amount of time that has elapsed since the last reading and add that to a running total to get the current linear speed. You need to do the same over again to get current linear position.

In code form, it looks like:

```<code>sampleTime = GetElapsedTime();
linearAcceleration = GetAccelerometerOutput();
linearSpeed = linearSpeed + linearAcceleration*sampleTime;
linearPosition = linearPosition + linearSpeed*sampleTime;
</code>```

A gyroscope outputs an angular speed, so you only need to integrate once to get to the angular position:

```<code>sampleTime = GetElapsedTime();
angularSpeed = GetGyroscopeOutput();
angularPosition = angularPosition + angularSpeed*sampleTime;
</code>```

The trouble here is that no sensors are perfect. The gyroscope and the accelerometer both have noise, biases, bias drift, etc. You integrate the sensor outputs, and integration is an accumulation of sorts, so the linear and angular position estimates "remember" all the noise.

The noise might be zero-mean, meaning your long-term average of that signal should be the true signal, but the integration of that noise is not.

Consider the following example: Have your speed be solely determined by the "white noise" of a coin flip. If the coin flip is heads, you are moving forward, if it is tails, you're moving backwards. On each sample, take a step in the appropriate direction.

If the total results of coin flips are even heads/tails, then your position should be where you started, right?

If you have flipped the coin one time, is it possible for you to be 10 steps away from the starting position? No, that's not possible. You take one step per flip, so you could only possibly be 1 step away from where you started, which should be your "true position."

If you have flipped the coin 10 times, is it possible for you to be 10 steps away from the starting position? Now it is possible. It's very unlikely, but it's possible.

If you have flipped the coin 100 times, now it's pretty reasonable to assume you could be 10 steps away from the "true" position.

For a gyroscope, the random distance traveled each "flip" (sample) is called the "random walk" or "angle random walk," and this should be a parameter given in the datasheet.

The angle random walk tells you how you can expect the standard deviation to change with respect to time. You can use the standard deviation with the empirical rule to estimate the possible error in your integrated angle.

The empirical rule says that 68 percent of measurements should fall within +/- one standard deviation, 95 percent should fall within +/- two standard deviations, and 99.7 percent should fall within +/- three standard deviations.

A high quality gyroscope should give the angle random walk in units of $\mbox{ARW} = \mbox{deg}/\sqrt{\mbox{hr}}$. This means your standard deviation after 1 hour should be $\mbox{ARW}*\sqrt{1}$, after two hours it would be $\mbox{ARW}*\sqrt{2}$, etc.

Lower quality gyroscopes give the same parameter in units of $\mbox{ARW} = \mbox{deg}/\sqrt{\mbox{s}}$, so you get to "dilate" your standard deviation on a much faster time scale.

For example, if your datasheet gave $\mbox{ARW} = 0.01 \mbox{deg}/\sqrt{s}$, then your standard deviation after 60 seconds is $0.01 * \sqrt{60} = 0.0775 \mbox{deg}$. By the empirical rule, your actual angle is probably (68 percent sure) within +/- (1*0.0775) = +/- 0.0775 deg and almost certainly (99.7 percent sure) within +/- (3*0.0775) = +/- 0.23 deg.

If you had a gyro with that rating and you ran it for six hours, as you asked in your question, the standard deviation would be $0.01 * \sqrt(6*3600) = 1.47 \mbox{deg}$. Your estimate could be as far as +/- (3*1.47) = +/- 4.4 deg away.

Some data sheets give the noise in terms of a noise power spectral density, sometimes with units of $\mbox{deg}/\mbox{s}/\sqrt{\mbox{Hz}}$. You can review IEEE Std 952-1997 for a more detailed description of the noise PSD, but section C.1.1 of that document gives a conversion of:

$$
N\left(^{\circ}/\sqrt{\mbox{hr}}\right) = \frac{1}{60}\sqrt{\mbox{PSD}\left[\left(\frac{^{\circ}}{\mbox{hr}}\right)^2/\mbox{Hz}\right]} \\
$$

Note the units there. It seems like most noise PSD are listed with units of $^{\circ}/\mbox{s}/\sqrt{hr}$, which would imply that they've already taken the square root of the proper noise PSD. That leaves the conversion to random walk as (1/60) of the listed noise PSD.

So, finally, for example, here is a listing of some three-axis accelerometer/gyro IMUs on Digikey. The first item you can buy in quantity (1) is the Bosch BMI160. The datasheet for that sensor gives the Output Noise for the 200 Hz data rate to be 0.07 $^{\circ}/\mbox{s rms}$.

In the first second, at 200 Hz, there are 200 samples. The standard deviation is $0.07\sqrt{200} = 1 \mbox{deg}$. After 60 seconds there are (60*200) = 1200 samples, and the standard deviation is $0.07\sqrt{1200} = 2.4 \mbox{deg}$.

This is the least expensive surface mount, in stock, 3 axis, exclusively accelerometer/gyro chip listed on Digikey's website (\$5.39 at the time of the writing). The most expensive is the Analog Devices ADIS16477-3BMLZ (\$610.95 at the time of writing). The datasheet for that sensor gives the random walk as 0.15 $^{\circ}/\sqrt{hr}$.

One minute is 0.0167 hours, so after one minute the gyro standard deviation is $0.15\sqrt{0.0167} = 0.0194 \mbox{deg}$. After two minutes, the standard deviation is $0.15\sqrt{2/60} = 0.0274 \mbox{deg}$.

For your six hour run, the cheapest IMU has a standard deviation of $0.07\sqrt{6*3600*200} = 145.5 \mbox{deg}$, and the most expensive has a standard deviation of $0.15\sqrt{6} = 0.367 \mbox{deg}$. Keep in mind that 95% of samples should fall within +/- 2 standard deviations.

And, since I started writing this post, benh has written an answer that says, in part,

An IMU will not drift as the accelerometers will always read against gravity.

This is true if you're using accelerometers, but it will only fix the horizontal axes (typically x/y, roll/pitch). Gravity acts along the vertical axis, so rotations about the vertical axis (heading/yaw) aren't able to use the gravity vector as a means of absolute orientation reference.

Title: How reliable are IMUs for a long usage (6 hours) rotation (only) tracking?

Body:
I know they are bad for positional tracking and drift from actual position over time but would like to know what is the situation with rotation only.

I know Oculus DK1 used ordinary off-the-shelf cheap IMUs for rotation tracking of the user's head, as does any other VR headset, such as GearVR, where there is no positional tracking, but I haven't had chance to use them more than few minutes to know how much they (their IMUs) drift from original orientation over time.

Body:
Welcome to Robotics, Mark!

IMUs are typically comprised of two core components: accelerometers and gyroscopes. They may also have a magnetometer.

An accelerometer measures linear acceleration, and a gyroscope measures angular velocity.

In order to get linear and angular position estimates, those outputs need to be integrated. I'm not sure what your background is, but integration is just an accumulation of samples with respect to time.

If you travel 50 km/h for an hour, you have gone 50 km. If you then go 25 km/hr for half an hour, you have gone and additional (25 * 0.5) = 12.5 km. Your total distance traveled is (50 + 12.5) = 62.5 km. Get the current speed, multiply by how long you've been going that speed, and add it to a running total. This is integration.

For the accelerometer, you multiply the current reading by the amount of time that has elapsed since the last reading and add that to a running total to get the current linear speed. You need to do the same over again to get current linear position.

In code form, it looks like:

sampleTime = GetElapsedTime();
linearAcceleration = GetAccelerometerOutput();
linearSpeed = linearSpeed + linearAcceleration*sampleTime;
linearPosition = linearPosition + linearSpeed*sampleTime;

A gyroscope outputs an angular speed, so you only need to integrate once to get to the angular position:

sampleTime = GetElapsedTime();
angularSpeed = GetGyroscopeOutput();
angularPosition = angularPosition + angularSpeed*sampleTime;

The trouble here is that no sensors are perfect. The gyroscope and the accelerometer both have noise, biases, bias drift, etc. You integrate the sensor outputs, and integration is an accumulation of sorts, so the linear and angular position estimates "remember" all the noise.

The noise might be zero-mean, meaning your long-term average of that signal should be the true signal, but the integration of that noise is not.

Consider the following example: Have your speed be solely determined by the "white noise" of a coin flip. If the coin flip is heads, you are moving forward, if it is tails, you're moving backwards. On each sample, take a step in the appropriate direction.

If the total results of coin flips are even heads/tails, then your position should be where you started, right?

If you have flipped the coin one time, is it possible for you to be 10 steps away from the starting position? No, that's not possible. You take one step per flip, so you could only possibly be 1 step away from where you started, which should be your "true position."

If you have flipped the coin 10 times, is it possible for you to be 10 steps away from the starting position? Now it is possible. It's very unlikely, but it's possible.

If you have flipped the coin 100 times, now it's pretty reasonable to assume you could be 10 steps away from the "true" position.

For a gyroscope, the random distance traveled each "flip" (sample) is called the "random walk" or "angle random walk," and this should be a parameter given in the datasheet.

The angle random walk tells you how you can expect the standard deviation to change with respect to time. You can use the standard deviation with the empirical rule to estimate the possible error in your integrated angle.

The empirical rule says that 68 percent of measurements should fall within +/- one standard deviation, 95 percent should fall within +/- two standard deviations, and 99.7 percent should fall within +/- three standard deviations.

A high quality gyroscope should give the angle random walk in units of $\mbox{ARW} = \mbox{deg}/\sqrt{\mbox{hr}}$. This means your standard deviation after 1 hour should be $\mbox{ARW}*\sqrt{1}$, after two hours it would be $\mbox{ARW}*\sqrt{2}$, etc.

Lower quality gyroscopes give the same parameter in units of $\mbox{ARW} = \mbox{deg}/\sqrt{\mbox{s}}$, so you get to "dilate" your standard deviation on a much faster time scale.

For example, if your datasheet gave $\mbox{ARW} = 0.01 \mbox{deg}/\sqrt{s}$, then your standard deviation after 60 seconds is $0.01 * \sqrt{60} = 0.0775 \mbox{deg}$. By the empirical rule, your actual angle is probably (68 percent sure) within +/- (1*0.0775) = +/- 0.0775 deg and almost certainly (99.7 percent sure) within +/- (3*0.0775) = +/- 0.23 deg.

If you had a gyro with that rating and you ran it for six hours, as you asked in your question, the standard deviation would be $0.01 * \sqrt(6*3600) = 1.47 \mbox{deg}$. Your estimate could be as far as +/- (3*1.47) = +/- 4.4 deg away.

Some data sheets give the noise in terms of a noise power spectral density, sometimes with units of $\mbox{deg}/\mbox{s}/\sqrt{\mbox{Hz}}$. You can review IEEE Std 952-1997 for a more detailed description of the noise PSD, but section C.1.1 of that document gives a conversion of:

$$
N\left(^{\circ}/\sqrt{\mbox{hr}}\right) = \frac{1}{60}\sqrt{\mbox{PSD}\left[\left(\frac{^{\circ}}{\mbox{hr}}\right)^2/\mbox{Hz}\right]} \\
$$

Note the units there. It seems like most noise PSD are listed with units of $^{\circ}/\mbox{s}/\sqrt{hr}$, which would imply that they've already taken the square root of the proper noise PSD. That leaves the conversion to random walk as (1/60) of the listed noise PSD.

So, finally, for example, here is a listing of some three-axis accelerometer/gyro IMUs on Digikey. The first item you can buy in quantity (1) is the Bosch BMI160. The datasheet for that sensor gives the Output Noise for the 200 Hz data rate to be 0.07 $^{\circ}/\mbox{s rms}$.

In the first second, at 200 Hz, there are 200 samples. The standard deviation is $0.07\sqrt{200} = 1 \mbox{deg}$. After 60 seconds there are (60*200) = 1200 samples, and the standard deviation is $0.07\sqrt{1200} = 2.4 \mbox{deg}$.

This is the least expensive surface mount, in stock, 3 axis, exclusively accelerometer/gyro chip listed on Digikey's website (\$5.39 at the time of the writing). The most expensive is the Analog Devices ADIS16477-3BMLZ (\$610.95 at the time of writing). The datasheet for that sensor gives the random walk as 0.15 $^{\circ}/\sqrt{hr}$.

One minute is 0.0167 hours, so after one minute the gyro standard deviation is $0.15\sqrt{0.0167} = 0.0194 \mbox{deg}$. After two minutes, the standard deviation is $0.15\sqrt{2/60} = 0.0274 \mbox{deg}$.

For your six hour run, the cheapest IMU has a standard deviation of $0.07\sqrt{6*3600*200} = 145.5 \mbox{deg}$, and the most expensive has a standard deviation of $0.15\sqrt{6} = 0.367 \mbox{deg}$. Keep in mind that 95% of samples should fall within +/- 2 standard deviations.

And, since I started writing this post, benh has written an answer that says, in part,

An IMU will not drift as the accelerometers will always read against gravity.

This is true if you're using accelerometers, but it will only fix the horizontal axes (typically x/y, roll/pitch). Gravity acts along the vertical axis, so rotations about the vertical axis (heading/yaw) aren't able to use the gravity vector as a means of absolute orientation reference.


问:
How to do IMU and camera "sensor fusion" tracking?
I have some 50ms latency cameras at hand and a  800Hz IMU (gyro+accelerometer+magnetometer). I would like to know how exactly how I should do a sensor fusion of such an IMU and camera to fix the positional data from the IMU positional drift. I'm not able to find much resources online.
The reason is that I don't want to go with just a camera  due to its 50ms latency.

The optical markers for the camera can be LEDs, ORB-SLAM data or AruCo markers which I currently use and which add another few ms latency to the camera tracking.

Maybe there is even an existing library or documented implementation I can use?

答:
The easiest platform for a multi-modal sensor fusion is a continuous-time trajectory model. Please have a look at this repo and related papers. I believe that it should be state of the art implementation of what you are looking for.

Temporal difference between sensors can be estimated through a windowed trajectory optimization. Asynchronicity as well.


问:
Problem with tuning PID for motor
I am trying to tune my PID to make my motor have a consistent output:

input(pidOutput) => 100rpm

I used the following step to tune my PID:

Set all gains to zero.

Increase the P gain until the response to a disturbance is steady oscillation.

Increase the D gain until the the oscillations go away (i.e. it's critically damped).

Repeat steps 2 and 3 until increasing the D gain does not stop the oscillations.

Set P and D to the last stable values.

Increase the I gain until it brings you to the setpoint with the number of oscillations desired (normally zero but a quicker response
  can be had if you don't mind a couple oscillations of overshoot)

As I do not know the values of PID i should increase,

I started with a value of P = 0.2, D = 0 and this resulted in an output of about 36~38 RPM.

Then I increased P = 0.3, D= 0 and the output goes to about 42~46 RPM.

I then had to slowly increase my D till i found a sweet spot eg, D=0.2 till the range of RPM goes from 44~46 RPM.

After about 3 hours, I only achieved the range of about 60~62 and it is really frustrating as it is really slow and I have 2 motors and have not even tune one motor.

I have a few doubts which is:

Am I tuning wrongly as it is taking too long and far from my target of 100rpm.

And how much of a range for RPM is counted as unacceptable? I have two motors with a PID on it's own, Would a difference of 2 RPM on each
  wheel cause the car to go sideways?

After tuning (with the I gain), what output am I expected to see? will it be an output of a constant 100rpm? Or will it be 99~101 for
  example

The PID code I used:

```<code>double pidtune1(double rpm){
  double kp, ki, kd, p, i, d, error, pid;
  kp = 0.79;
  ki = 0;
  kd = 0.6395;

  error = 100 - rpm1;
  integral += error;
  p = kp*error;
  i = ki*integral;
  d = kd*(prevRPM - rpm);
  prevRPM = rpm;
  pid = p+i+d;
  return pid;
}
</code>```

Called By:

```<code>while (distance < 100)
{
  pid_output1=pidtune1(rpm1);
  pid_output2=pidtune1(rpm2);
  md.setSpeeds(pid_output1, pid_output2);
  recalculateRPMs();
}

 md.setBrakes(400,400);
</code>```

答:
Your goal is a bit unclear. In the sense that you don't really care about your motor control input, what you want is a given rotational velocity. the pid is going to give you the command (motor input) to achieve it given the desired one and the current one (plus derivative). Most likely this command is going to be a PWM signal which will be fed to a motor controller (the electronic card)  which converters it to the given voltage at the motor input.
Note that if you want to prevent damage you should saturate your PID output to be sure not to damage the motor with crazy commands.

Am I tuning wrongly as it is taking too long and far from my target of 100rpm.

Your timeline seem rather excessive to me, you should be able to converge way faster. I would suggest to increase the P gain at a faster rate and/or to higher values.

I have two motors with a PID on it's own, Would a difference of 2 RPM on each wheel cause the car to go sideways?

This mostly depends on your robot geometry (wheel size, inter wheel distance). If you goal is to go straight you should have a control loop (PID) ensuring it instead of trying  to feedforward the same wheel velocities.

After tuning (with the I gain), what output am I expected to see? will it be an output of a constant 100rpm? Or will it be 99~101 for example

After the initial transient you should reach a steady state, if you have no noise arising from your current wheel velocity measurement. Otherwise the noise while change the proportional error and thus propagate in your PID output

Title: Problem with tuning PID for motor


答:
Welcome to Robotics, Bloopie Bloops! You haven't stated what platform/language this is, so I'll just give some illustrative pseudo code. As Mark Booth mentioned, the typical way to evaluate/critique controller performance is by plotting the reference and output values together.

There are several glaring issues with your code, so I'll go over those. You're defining the gains okay, so I'll just repost the remainder of your code here for easy reference:

```<code>double pidtune1(double rpm){
  <define kp, ki, kd>

  error = 120 - rpm1;
  integral += error;
  p = kp*error;
  i = ki*integral;
  d = kd*(prevRPM - rpm);
  prevRPM = rpm;
  pid = p+i+d;
  return pid;
}
</code>```

The first problem is that there's no sample time involved. If your PID controller is running on an interrupt, which would mean the controller gets called on a fixed and repeatable interval, then it is possible to "roll" the sample time into the gains. However, this prevents you from using PID tuning guides like Ziegler-Nichols.

Consider the following:

$$
\mbox{D term} = k_P(\Delta \mbox{Error}/\Delta t) \\
\mbox{D term} = \hat{k}_P \Delta\mbox{Error} \\
\hat{k}_P = k_P/\Delta t
$$

You're (kind of) using the "hat" terms, $\hat{k}_I$ and $\hat{k}_P$, but again now the relationship between those terms is skewed such that you can't just set one as some empirical constant times another.

If the sample time is known (you know the interrupt interval), then you can hard-code it as a constant. If the sample time is not known, then you need to use a timer to evaluate how much time has elapsed since the previous loop.

Changes in logic flow/branches, state machines, communication delays, sensor delays, etc. can all affect when the controller is called. You need to account for those delays.

You could implement a timer with either a function call to something like elapsedMicros() or by making a variable retain its value across function calls and polling the current time:

```<code>double pidtune1(<inputs>){
  static double prevTime = 0.0f;
  double currentTime = micros();
  double  dT = (currentTime - prevTime)*0.000001f;
  // or double dT = getMicros()*0.000001f;
</code>```

Next, you need to calculate the error term correctly. Currently, you're passing an input of rpm, but your error = 120 - rpm1. I would guess that rpm is probably the reference speed, but you don't provide a feedback speed! Where is rpm1 defined? Also a nit-picking kind of point, but I can't actually tell if rpm is the reference or feedback by name alone.

Consider the following changes then:

```<code>double pidtune1(double rpm_ref, double rpm_fbk){
  <define control gains>
  <define dT>

  double error = (rpm_ref - rpm_fbk);
</code>```

Finally, the last important thing to point out is that the integral and derivative terms should be the integral and derivative of the error term. Your integral term is currently

```<code>integral += error;
</code>```

Which should change to include the elapsed time dT as:

```<code>integral += error*dT;
</code>```

But your derivative term is currently defined to be:

```<code>(prevRPM - rpm)
</code>```

This is where the actual definition of rpm and/or the ambiguous name is especially problematic. Are you looking at the change in reference speed, or are you looking at the change in feedback speed?

Regardless of the current intent, you need to be looking at the change in error, not the reference or feedback. That is, you should have:

```<code>double derivativeError = (error - prevError)/dT;
</code>```

Note the above line also has the current term minus the previous term.

Putting this all together, you should have a PID controller that looks more like:

```<code>double pidtune1(double rpm_ref, double rpm_fbk){
  // Define gains
  double kp, ki, kd;
  kp = 0.79;
  ki = 0;
  kd = 0.6395;

  // Get elapsed time
  static double prevTime = 0.0f;
  double currentTime = micros();
  double dT = (currentTime - prevTime)*0.000001f;
  // or double dT = getMicros()*0.000001f;
  // or double dT = <your interrupt interval>;

  // Evaluate errors
  static double integralError = 0.0f;
  static double prevError = 0.0f;
  double proportionalError = rpm_ref - rpm_fbk;
  integralError += proportionalError*dT;
  double derivativeError = (proportionalError - prevError)/dT;

  // Apply gains
  double p = kp*proportionalError;
  double i = ki*integralError;
  double d = kd*derivativeError;
  double pid = p+i+d;

  // Cleanup
  prevTime = currentTime;
  prevError = proportionalError;
  return pid;
}
</code>```

Again, I'm not sure of your language or platform, so the specific implementations may be a bit off, but the content is there. Be sure to use static or persistent, etc. to ensure the variable is "remembered" across function calls. I get the feeling you may be using global variables to avoid the fact that they're otherwise wiped between function calls, but that gets messy in a hurry, mostly because you can't easily re-use functions - you'd need a second set of global variables instead of creating a new instance of your class. Using static variables keeps everything contained inside the scope of that particular function.

That's all topics for another question, though. Hopefully the code above is enough to get you started. If not, please provide some graphs of the feedback speed versus the speed reference as Mark Booth mentioned and hopefully someone here can give you some more help :)

Title: Problem with tuning PID for motor

Body:
I am trying to tune my PID to make my motor have a consistent output:

input(pidOutput) => 100rpm

I used the following step to tune my PID:

Set all gains to zero.

Increase the P gain until the response to a disturbance is steady oscillation.

Increase the D gain until the the oscillations go away (i.e. it's critically damped).

Repeat steps 2 and 3 until increasing the D gain does not stop the oscillations.

Set P and D to the last stable values.

Increase the I gain until it brings you to the setpoint with the number of oscillations desired (normally zero but a quicker response
  can be had if you don't mind a couple oscillations of overshoot)

As I do not know the values of PID i should increase,

I started with a value of P = 0.2, D = 0 and this resulted in an output of about 36~38 RPM.

Then I increased P = 0.3, D= 0 and the output goes to about 42~46 RPM.

I then had to slowly increase my D till i found a sweet spot eg, D=0.2 till the range of RPM goes from 44~46 RPM.

After about 3 hours, I only achieved the range of about 60~62 and it is really frustrating as it is really slow and I have 2 motors and have not even tune one motor.

I have a few doubts which is:

Am I tuning wrongly as it is taking too long and far from my target of 100rpm.

And how much of a range for RPM is counted as unacceptable? I have two motors with a PID on it's own, Would a difference of 2 RPM on each
  wheel cause the car to go sideways?

After tuning (with the I gain), what output am I expected to see? will it be an output of a constant 100rpm? Or will it be 99~101 for
  example

The PID code I used:

```<code>double pidtune1(double rpm){
  double kp, ki, kd, p, i, d, error, pid;
  kp = 0.79;
  ki = 0;
  kd = 0.6395;

  error = 100 - rpm1;
  integral += error;
  p = kp*error;
  i = ki*integral;
  d = kd*(prevRPM - rpm);
  prevRPM = rpm;
  pid = p+i+d;
  return pid;
}
</code>```

Called By:

```<code>while (distance < 100)
{
  pid_output1=pidtune1(rpm1);
  pid_output2=pidtune1(rpm2);
  md.setSpeeds(pid_output1, pid_output2);
  recalculateRPMs();
}

 md.setBrakes(400,400);
</code>```

Body:
Welcome to Robotics, Bloopie Bloops! You haven't stated what platform/language this is, so I'll just give some illustrative pseudo code. As Mark Booth mentioned, the typical way to evaluate/critique controller performance is by plotting the reference and output values together.

There are several glaring issues with your code, so I'll go over those. You're defining the gains okay, so I'll just repost the remainder of your code here for easy reference:

double pidtune1(double rpm){
  <define kp, ki, kd>

  error = 120 - rpm1;
  integral += error;
  p = kp*error;
  i = ki*integral;
  d = kd*(prevRPM - rpm);
  prevRPM = rpm;
  pid = p+i+d;
  return pid;
}

The first problem is that there's no sample time involved. If your PID controller is running on an interrupt, which would mean the controller gets called on a fixed and repeatable interval, then it is possible to "roll" the sample time into the gains. However, this prevents you from using PID tuning guides like Ziegler-Nichols.

Consider the following:

$$
\mbox{D term} = k_P(\Delta \mbox{Error}/\Delta t) \\
\mbox{D term} = \hat{k}_P \Delta\mbox{Error} \\
\hat{k}_P = k_P/\Delta t
$$

You're (kind of) using the "hat" terms, $\hat{k}_I$ and $\hat{k}_P$, but again now the relationship between those terms is skewed such that you can't just set one as some empirical constant times another.

If the sample time is known (you know the interrupt interval), then you can hard-code it as a constant. If the sample time is not known, then you need to use a timer to evaluate how much time has elapsed since the previous loop.

Changes in logic flow/branches, state machines, communication delays, sensor delays, etc. can all affect when the controller is called. You need to account for those delays.

You could implement a timer with either a function call to something like elapsedMicros() or by making a variable retain its value across function calls and polling the current time:

double pidtune1(<inputs>){
  static double prevTime = 0.0f;
  double currentTime = micros();
  double  dT = (currentTime - prevTime)*0.000001f;
  // or double dT = getMicros()*0.000001f;

Next, you need to calculate the error term correctly. Currently, you're passing an input of rpm, but your error = 120 - rpm1. I would guess that rpm is probably the reference speed, but you don't provide a feedback speed! Where is rpm1 defined? Also a nit-picking kind of point, but I can't actually tell if rpm is the reference or feedback by name alone.

Consider the following changes then:

double pidtune1(double rpm_ref, double rpm_fbk){
  <define control gains>
  <define dT>

  double error = (rpm_ref - rpm_fbk);

Finally, the last important thing to point out is that the integral and derivative terms should be the integral and derivative of the error term. Your integral term is currently

integral += error;

Which should change to include the elapsed time dT as:

integral += error*dT;

But your derivative term is currently defined to be:

(prevRPM - rpm)

This is where the actual definition of rpm and/or the ambiguous name is especially problematic. Are you looking at the change in reference speed, or are you looking at the change in feedback speed?

Regardless of the current intent, you need to be looking at the change in error, not the reference or feedback. That is, you should have:

double derivativeError = (error - prevError)/dT;

Note the above line also has the current term minus the previous term.

Putting this all together, you should have a PID controller that looks more like:

double pidtune1(double rpm_ref, double rpm_fbk){
  // Define gains
  double kp, ki, kd;
  kp = 0.79;
  ki = 0;
  kd = 0.6395;

  // Get elapsed time
  static double prevTime = 0.0f;
  double currentTime = micros();
  double dT = (currentTime - prevTime)*0.000001f;
  // or double dT = getMicros()*0.000001f;
  // or double dT = <your interrupt interval>;

  // Evaluate errors
  static double integralError = 0.0f;
  static double prevError = 0.0f;
  double proportionalError = rpm_ref - rpm_fbk;
  integralError += proportionalError*dT;
  double derivativeError = (proportionalError - prevError)/dT;

  // Apply gains
  double p = kp*proportionalError;
  double i = ki*integralError;
  double d = kd*derivativeError;
  double pid = p+i+d;

  // Cleanup
  prevTime = currentTime;
  prevError = proportionalError;
  return pid;
}

Again, I'm not sure of your language or platform, so the specific implementations may be a bit off, but the content is there. Be sure to use static or persistent, etc. to ensure the variable is "remembered" across function calls. I get the feeling you may be using global variables to avoid the fact that they're otherwise wiped between function calls, but that gets messy in a hurry, mostly because you can't easily re-use functions - you'd need a second set of global variables instead of creating a new instance of your class. Using static variables keeps everything contained inside the scope of that particular function.

That's all topics for another question, though. Hopefully the code above is enough to get you started. If not, please provide some graphs of the feedback speed versus the speed reference as Mark Booth mentioned and hopefully someone here can give you some more help :)


问:
Cant see Kinect Data in ROS
I am working on this project that involves using the Kinect for XBOX 360S with ROS.

I did all the steps mentioned in the ROS Tutorials to have Openni Installed and the Prime sense and other drivers. and when i go to Openni samples i see a output. But in ROS i do a roscore and in another terminal do a roslaunch openni_launch openni.launch. And it loads with the regular calibration warnings and service already registered errors. Then in another terminal i open Rviz which gives a error /.rviz/display_config does not exist. And even though i accept the error and go ahead i see a black window which shows no output ,even if i do all tasks mentioned at the RVIZ Tutorials. Also i tried running "rosrun image_view image_view image:=/camera/rgb/image_color" and it shows up a blank window with no output. How do i resolve this and get ros to show my kinect data??

I need to run RGBDSLAM and use this kinect later.

I am on Ubuntu 12.04 and ROS-Fuerte.

Well when i launch the openni.launch it starts as usual except for the errors ¨Tried to advertise a service that is already advertised in this node.

And when i run a rostopic it just says subscribed to the /camera/depth_registered/points and cursor keeps blinking.
Even subscribing to the rectified topics just says subscribed and nothing more happens.

答:
First of all, I know this is not an answer, however since I am a new user I cannot comment on Preetham's question.

I have a very similar problem, however, when I first run roswtf, I get no errors but when I wait a bit after using rviz or trying to record a bagfile, the openni.launch terminal itself gives me this error:

terminate called after throwing an instance of 'openni_wrapper::OpenNIException'
  what():  virtual void openni_wrapper::OpenNIDevice::startImageStream() @ /tmp/buildd/ros-groovy-openni-camera-1.8.8-0precise-20130418-2203/src/openni_device.cpp @ 224 : starting image stream failed. Reason: Xiron OS got an event timeout!
[camera_nodelet_manager-2] process has died [pid 3788, exit code -6, cmd /opt/ros/groovy/lib/nodelet/nodelet manager __name:=camera_nodelet_manager __log:=/home/rosbotics/.ros/log/16b63744-e043-11e2-ac16-080027486aa8/camera_nodelet_manager-2.log].
log file: /home/rosbotics/.ros/log/16b63744-e043-11e2-ac16-080027486aa8/camera_nodelet_manager-2*.log

and roswtf  displays:

unknown network error contacting node: timed out

Warning These nodes have died:

camera_nodelet_manager-2

found 2 errors

ERROR The following nodes should be connected but aren't:

/camera_base_link1->/camera_nodelet_manager (/tf)

/camera_base_link->/camera_nodelet_manager (/tf)

/camera_base_link3->/camera_nodelet_manager (/tf)

/camera_base_link2->/camera_nodelet_manager (/tf)

ERROR Errors connecting to the following services: (then it displays a lot of services)

At first After looking around a bit I thought it was a problem with openni and tried using freenect instead, however that too gave a black screen. Then I tried using something completely unrelated to ros, freenect-glview, however that too gave me a black screen.

lsusb shows that all 3 parts of the kinect are connected and I've been able to control the kinect's motor through ubuntu so I know that there is at least a connection established between both.

I am using ubuntu 12.04 and ROS-Groovy.

I would appreciate anyone's help on the matter.

Title: Cant see Kinect Data in ROS


问:
Get data without command anything from Roomba Create 2
I use Arduino Uno R3 connected to the Roomba Create 2 as in this picture

All the output commands for Arduino work fine but I have a problem from reading data  from Create 2 sensors: I get invalid/wrong sensor  sensor data every approximately 2 minutes.

So I tried to test with an empty program to check the incoming data from Roomba.

This is the code:

```<code>#include <SoftwareSerial.h>
#include "roombaDefines.h"

int rxPin=10;  //yellow
int txPin=11;  //green
byte data1 ;
SoftwareSerial Roomba(rxPin,txPin);

void setup()
{
  Roomba.begin(19200);
  Serial.begin(9600);

  pinMode(ddPin, OUTPUT);
  delay(1000);

  wakeUp ();   // Wake-up Roomba
  startSafe(); // Start Roomba in Safe Mode
  playSound(1);
  setPowerLED(128,255);
  Serial.println("Start");
}

void loop()
{

 while(Roomba.available()>0)
 {
  data1 = Roomba.read();
  Serial.println(data1);
 }

}
</code>```

and I got this from Serial monitor approximately every two minutes

```<code>Start
32
32
32
32
70
108
97
115
104
32
67
32
115
117
99
99
101
115
115
102
117
108
58
32
48
120
48
32
40
48
120
48
41
10
13
</code>```

I think this is the cause of the error in reading the sensor data.

Did anyone have this problem before ?
How can I avoid this and read correct sensor  data from Roomba ?

I see from another post that somebody had the same issue as me, see iRobot Create 2 Flash CRC message

but I already tried op code 128 to start Roomba in OI mode and it still have the same issue

答:
It is a message.

See this  page.

https://en.wikipedia.org/wiki/ASCII#Printable_characters


问:
Does iRobot 681 have a serial interface?
I've read that recent Roomba 6XX from iRobot got a serial connector, but I removed the cover on my Roomba 681, and I haven't found any. From what I've found, 681 hasn't the same cover than other 6XX robots. Does this model have an accesible serial port?

答: I have the Roomba 671 from 2018 Prime Day, I had to pop the plastic top off with a screwdriver with some force. The ROI aerial port is on the front left of my model.</p>


问:
What does the number of teeth in a gear determine (when meshing identical gears)?
Suppose I want to mesh two identical gears (size and number of teeth). What would be the difference if both had 12 teeth versus both having 48? Assume the motor spins at the same speed in both scenarios.</p>

答:
So, assuming that the more teeth that there are, the smaller the teeth become (and logically for gears with few teeth, the bigger the teeth are):

Big teeth:

Capable of handling higher load

Capable of transmitting a greater force

less likely to strip

less precise

greater tolerance

more sliding friction1

greater backlash

Less smooth movement

Small teeth:

Less load capable (for a given material and gear thickness)

Capable of transmitting a lesser force

More likely to strip under heavy load (for a given material and gear thickness)

More precise

Tighter tolerance (more susceptible to defects, and misalignment, in the drive train)

Less sliding friction1

Less backlash

Smoother movement

Data summarised from Does the size of the teeth on a gear really matter?

1 Although, in the case that you describe, with a 1:1 ration the gears will be more geometrically perfect, and friction should be minimal


问:
The Arduino Turns Off After Attaching A Servo Motor
The Arduino turns off when I try to put the wire from the servo to its respective pin (9). Also, I've tried the code from the Arduino IDE, the knob code where the position of the motor depends on the value of the potentiometer. I don't really know what's wrong. Every time the servo tries to turn, the Arduino turns off, so the motor only turn for a very small degree, then the Arduino turns on, and so on.

By the way, I'm using an MG996R Tower Pro Digital Servo motor.

Is there a problem with the motor or/and the Arduino? I can't seem to remedy this problem.

答:
It sounds like you are drawing too much power from the Arduino, and causing it to reset. Try powering your servo from a separate power source.

The Arduino Playground has a useful page on Arduino Pin Current Limitations which you might find helpful if you're designing robots that use Arduinos.

 A summary of the information for the Arduino Uno is given below:

Input Voltage Limits:

Recommended: 7~12V

Absolute: 6~20V

Input/Output (I/O) pins: -0.5V to +5.5V (the actual max is “Vcc +
0.5V,” which for a 5V Arduino, is +5.5V)

Output Current Limits:

When powered by USB: total of 500mA

With external battery or power supply: total of 500mA~1A

5V pin: same as above: 500mA or 500mA~1A

Each input/output pin: 40mA

Sum of all input/output pins combined (but NOT including the “5V”
pin): 200mA


问:
Dimensioning a robotic arm for playing Chess
The intended purpose of the arm is to pick and place chess pieces.

I am planing to make a 3 DoFs system (only using 2 joints mounted on a revolving turntable), the link structure should be composed of  rectangular pieces of acrylic sheet. My chessboard is 28cm x 28cm.

I don't know how to calculate the length of the 2 links so that the robotic arm end-effector can reach each and every square.

答:
Assuming you put your manipulator along the middle of the chess board, your

(link1 + link2)^2 >= (28+6)^2+ (28/2)^2

and

(link1 + link2)^2 <= 6^2 + (28/2)^2

kinematically these two equations would suffice. you can choose any link1 and link2 values that satisfies the equation. But considering the dynamics it's preferable to choose l2 < l1


问:
Controlling a conveyor belt with a time based motor
I have some crude time based motors taken from a robot arm that we upgraded to proper servos. I want to be able to power a conveyor belt with one of them and I was wondering how I would go about the following setup:

A ball drops through a hole onto the conveyer belt hitting a lever switch on its way through. This switch triggers the motor to start. When the ball gets to the top of the belt and falls off it hits another lever switch that turns the motor off.

I could handle this logic by hooking it up to my raspberry pi and using python to start and stop the motor depending on which GPIO pin received input (top or bottom lever). Or I could use a single lever and set a constant time interval to stop the motor. I would prefer to use both to handle any change in scale/construction.

I was wondering however if this could be done with the breadboard alone, using logic gates or similar?

答:
To control the motor with logic gates, you could make a circuit with a monostable multivibrator (or  “one-shot”), an R-S flipflop (or R-S latch), and an AND gate or an OR gate to combine the one-shot and latch outputs.  You would use an AND if you want the motor to run when both the latch and the one-shot are active, vs an OR to make the motor run when either of them is active.  Whether to use AND or OR depends on what error conditions you want to detect or handle.

An R-S flipflop is easily made using two NAND gates, ie half of the gates in the quad NAND 74LS00.  A one-shot also can be made using  two NANDs (see “Simple NAND Gate Monostable Circuit” at about 1/3 thru page), or you can use a 74121, 74221, etc.  The 555 also is often used as a monostable multivibrator, and can also be used as an R-S flipflop.

So, you could use two 7400 packages for the circuit, or could use one 7400 and one 556 (which is a dual 555).  Circuits with NAND gates can be simulated by hand or in online simulators. Some simulators also simulate 555's.


问:
What's the difference between a sonar and ultrasonic sensor?
After having read the introductions of the Wikipedia articles about "sonar" and "ultrasonic sensor", it is still not clear to me what the differences between the two are. In the context of robotics, is there any difference between these two sensors (terms)?</p>

答:
Ultrasonic means above audible range,
Sonar may be within the audible range
In my opinion the ultrasonic being more precise also may come with higher price.</p>


问:
How to calculate the current consumed by a brushless motor on a quadcopter
I want to create a virtual quadcopter model, but I am struggling to come up with a satisfying model for the brushless motors & props.

Let's take an example, based on the great eCalc tool:

Let's say I want to know how much current is consumed by the motor in a hovering state. I know the mass of the quad (1500g), so I can easily compute the thrust produced by each motor:

```<code>Thrust = 1.5 * 9.81 / 4 = 3.68 N per motor
</code>```

Thrust is produced by moving a mass of air at an average speed of V:

```<code>Thrust = 0.5 * rho * A * V²
</code>```

Where rho (air density) is 1.225kg/m3 and A (propeller disk area) is PI * Radius² = 0.073m² (12" props). So I can compute V:

```<code>V = sqrt(Thrust / 0.5 / rho / A) = 9.07 m/s
</code>```

All right, now I can calculate the aerodynamic power created by the propeller:

```<code>P = Thrust * V = 3.68 * 9.07 = 33.4 W
</code>```

All right, now I can calculate the mechanical power actually produced by the motor. I use the PConst efficiency term from eCalc:

```<code>Pmec = Paero * PConst = 33.4 * 1.18 = 39.4W
</code>```

Here, eCalc predicts 37.2W. It's not too far from my number, I imagine they use more sophisticated hypotheses... Fair enough.

From this post, I know that this power is also equal to:

```<code>Pmec = (Vin - Rm * Iin) * (Iin - Io)
</code>```

Where I know Rm (0.08 Ohms) and Io (0.9 A). So, finally, my question: How do you calculate Vin and Iin from here? Of course, if I knew the rotation speed of the engine I could get Vin from:

```<code>n = Kv * Vin
</code>```

Where Kv = 680 rpm/V. But unfortunately I don't know the rotation speed...

(Note that Vin is assumed to be averaged from the pulse-width-modulated output produced by the ESC)

Thanks for your help!

答:
n = Kv * Vin only when there is no load on the motor. When there is a load on the motor, like from a propeller, you will need to be a bit more clever.

For a DC motor (which BLDC motors approximate by varying the Vin):

Torque = Kt * Vin / R - Ke * Kt * n / R

(Derivation example here: https://electronics.stackexchange.com/questions/90933/torque-relationship-to-speed-in-a-dc-motor)

Back the the propeller:

Paero = Thrust * Vp = torque * n

Vp = 0.5 * (Ve + Vac)

Since velocity of the aircraft at hover is 0, Vp becomes 0.5 * Ve

You actually used the Vp = 0.5 * (Ve + Vac) equation implicitly when you defined thrust. Those equations come from momentum theory. (Good read here: https://web.mit.edu/16.unified/www/FALL/thermodynamics/notes/node86.html)

From there you can solve for Vin and then Iin. Do note, this is the current and voltage of the motor. The ESc will be pulling from a higher voltage and lower current (but same power ignoring ESC losses)


问:
RRT star Convergence
My Code gives the following convergence characteristics, I wanted to know if it is correct

Updated code

{

```<code>    %Basic RRT star algorithm for non-holonomic body with obstacles
    close all
    clc
   clear all
   %Map and Initialization Data
   x_max = 100;
y_max = 100;
obs1 = [30,0,20,20];
obs2=  [30,60,20,20];
EPS = 5; % Step Size
Iter = 2000;

q_start.pos = [10 10];
q_start.cost = 0;
q_start.parent = 0;
q_start.child=[];
q_goal.pos = [90,90];
q_goal.cost = 1e9;
q_goal.child=[];
q_new.pos =[0,0];
q_new.cost=0;
q_new.parent=0;
q_new.child=[];
goal_reached=0;
tree(1) = q_start;
figure(1)
axis([0 x_max 0 y_max])
rectangle('Position',obs1,'FaceColor','b')
rectangle('Position',obs2,'FaceColor','b')
hold on
plot(q_start.pos(1),q_start.pos(2),'.','MarkerSize',10,'Color','m')
plot(q_goal.pos(1),q_goal.pos(2),'.','MarkerSize',10,'Color','b')
goal_nodes=[];
best_goal=[];
finalnodes=[];
  goals=0;
fc=[];
t=cputime;
for i=1:1:Iter
    q_rand=random_state(x_max,y_max);%Sampling a random state from the configuration space
    [q_near,val,idx] = nearest_neighbour(q_rand,tree); % Obtaining the nearest neighbour from the tree and its distance from q_rand
     q_new.pos=move(q_rand,q_near.pos,val,EPS);

 %Checking if goal has been reached
  stat= distance(q_rand,q_goal.pos);
        if (stat<=4 &&~isCollision(q_rand,q_near.pos,obs1)&&~isCollision(q_rand,q_rand,obs2))
            goal_reached = 1;
            goals=goals+1;
            goal_nodes(goals,:)=q_rand;
            q_new.pos=q_rand;
        end

   if(~isCollision(q_new.pos,q_near.pos,obs1)&&~isCollision(q_new.pos,q_near.pos,obs2))

   %line([q_near.pos(1), q_new.pos(1)], [q_near.pos(2), q_new.pos(2)], 'Color', 'k', 'LineWidth', 1);
        q_new.cost = distance(q_new.pos, q_near.pos) + q_near.cost;

    % Within a radius of r, find all existing nodes
        q_nearest = [];
        r = 10;
        neighbor_count = 0;
        ni=[];
        for j = 1:1:length(tree)
            if (noCollision(tree(j).pos,q_new.pos,obs1)&&noCollision(tree(j).pos,q_new.pos,obs2)&&distance(tree(j).pos, q_new.pos) <= r)
                neighbor_count = neighbor_count+1;
                q_nearest(neighbor_count).pos = tree(j).pos;
                q_nearest(neighbor_count).cost = tree(j).cost;
                ni=[ni,j];
            end
        end

        % Initialize cost to currently known value
        q_min = q_near;
        C_min = q_new.cost;

        % Iterate through all nearest neighbors to find alternate lower
        % cost paths

        for k = 1:1:length(q_nearest)
            if (q_nearest(k).cost + distance(q_nearest(k).pos, q_new.pos) < C_min)
                q_min = q_nearest(k);
                C_min = q_nearest(k).cost + distance(q_nearest(k).pos, q_new.pos);

            end
        end

        % Update parent to least cost-from node
        for j = 1:1:length(tree)
            if tree(j).pos == q_min.pos
                q_new.parent = j;
                q_new.cost = C_min;
                break
            end
        end

        % Add to tree
        tree = [tree,q_new];
        tree(q_new.parent).child=[tree(q_new.parent).child,length(tree)];

      %Rewire
      %Iterate through all nearest neighbors to rewire them with lower cost
      %path
        for k = 1:1:length(q_nearest)
            if ( q_new.cost + distance(q_nearest(k).pos, q_new.pos) < q_nearest(k).cost)
                tree(ni(k)).parent=length(tree);
                tree(ni(k)).cost= q_new.cost + distance(q_nearest(k).pos, q_new.pos);
                updatecost(tree,ni(k)); %Update cost of children

            end
        end
   end
  best_cost=1e9;
  best_goalindex=0;
    if(goal_reached)

for k=1:1:length(goal_nodes(:,2))
  for j = 1:1:length(tree)
      if(tree(j).pos(1)==goal_nodes(k,1)&&tree(j).pos(2)==goal_nodes(k,2)&&tree(j).cost<best_cost)
            best_goal=tree(j);
            best_cost=tree(j).cost;
            best_goalindex=j;

      end

  end
end

% Search backwards from goal to start to find the optimal least cost path
q_goal.parent = best_goalindex;
q_end = q_goal;
finalcost=0;
tree = [tree q_goal];
while q_end.parent ~= 0
    start = q_end.parent;
    finalcost=finalcost+distance(q_end.pos,tree(start).pos);
    plot(q_end.pos(1),q_end.pos(2),'*','Color','r')
    line([q_end.pos(1), tree(start).pos(1)], [q_end.pos(2), tree(start).pos(2)], 'Color', 'r', 'LineWidth', 2);
    hold on
    q_end = tree(start);
end
   finalnodes=[finalnodes,i];
   fc=[fc,finalcost];
   drawnow
    end
end
e=cputime-t
figure(2)
plot(finalnodes,fc);
title('RRT* Convergence')
xlabel('Iteration')
ylabel('Path Cost')
}
</code>```

答: No, at every iteration your RRT* should give a more optimized path once it has found it. The fluctuations are strange. You should try to get a convergence similar to this one.</p>

Title: RRT star Convergence


问:
Object detection using ToF sensor
I am making an indoor robot and in order to detect static and dynamic objects I have decided to go with ST VL53L1X ToF proximity sensor, here is the link:
https://www.st.com/en/imaging-and-photonics-solutions/vl53l1x.html

My question is, will this sensor show me a 3D reconstruction of what the sensor actually sees by emitting a light? And what is the difference between this sensor and other 3D ToF cameras?

答:
What do you mean when you say "3D reconstruction?" Lidar units will generally just return a line (or set of lines) of points. You index those points via the pose of the sensor platform and can build your own point cloud of return data.

The item you linked is not a lidar unit. It is a laser range finder. I didn't see any specs on measurement accuracy, and there are no specs on horizontal or vertical resolution. The device you linked emits a single beam and returns information on how far that beam traveled before contacting a surface.

It's possible for you to have a mechanism (servos, etc.) that move this device around to create some custom scan, but even then it's a single point measuring at 50 Hz. You get 50 points per second. Most laser scanners generate tens to hundreds of thousands of points per second.

Again, the definition of "3D reconstruction" is up to you, but I don't think this sensor is what you're looking for.

Title: Object detection using ToF sensor